파이썬은 여러 모듈들이 굉장히 편리하게 사용이 가능하다.
자료구조를 제외하고 가급적 사용하지 않으려고 한다.
이번에는 정규표현식과 permutation을 사용하지 않고 구현한다.
expression을 숫자와 연산자를 분리한다.- 가능한 연산자의 순열을 만든다.
- 순열의 우선순위대로 연산한 결과의 절댓값을 저장한다.
- 저장한 결괏값의 최댓값이 정답
split()으로 좌라락 하고싶었지만 안타깝게도 파라미터는 하나의 문자열만 가능하다.
정규표현식을 이용하면 numbers = re.split(r'(\D)',expression) 로 숫자만 추출하는것이 가능하다.
+ - *만 등장하는 것이므로 약간의 노가다로 해결했다
expression = expression.replace('+', ' + ')
expression = expression.replace('-', ' - ')
expression = expression.replace('*', ' * ')
expression = expression.split()
우선 필요없는 연산자를 빼고 필요한 연사자만 모으고 싶었다.
for exp in expression:
if exp in ['+', '-', '*']:
operations[exp] = 1
operations = [k for k in operations.keys()]
그다음은 순열리스트를 구해야 한다. 사실 from itertools import permutations을 이용하면 순열을 구현하지 않고도 쉽게 순열리스트를 얻을 수 있다.
permutes = [list(x) for x in permutations(operations)]
실제 시험에서 허가될지 모르니 고민이 생겼다.
재귀로 직접 구현할까? 하다가 기껐해야 3개밖에 없으니 그냥 노가다로 구현하기로 했다
우선순위대로 연산을 먼저 수행해야하므로 계산하지 않은 연산자를 남겨야한다. 그리고 다음 연산순위에 왔을때 제대로 동작해야한다
내 방법은 스택과 비슷한 자료구조를 이용하여 연산이 필요하면 스택의 마지막 숫자와 현재 숫자를 연산하고 다시 스택에 넣는것이다.
예를 들면,
우선순위: ['-', '*']
배열: [50, *, 6, -, 3, *, 2]
루프1: [50, *, 3, *, 2] # 6-3=3이다
루프2: [300] (50*3*2=300이다)
def calc(x, y, op):
if op == '+':
return x + y
elif op == '-':
return x - y
else:
return x * y
def permute_list(L):
if len(L) == 1:
return L
elif len(L) == 2:
return [[L[0], L[1]], [L[1], L[0]]]
else:
return [
[L[0], L[1], L[2]],
[L[0], L[2], L[1]],
[L[1], L[0], L[2]],
[L[1], L[2], L[0]],
[L[2], L[0], L[1]],
[L[2], L[1], L[0]]
]
def sub_calc(operations, expression):
cur_expression = expression
for operation in operations:
tmp = []
i = 0
while i < len(cur_expression):
cur = cur_expression[i]
if cur == operation:
nxt = cur_expression[i + 1]
tmp[-1] = calc(tmp[-1], nxt, cur)
i += 2
else:
tmp.append(cur)
i += 1
cur_expression = tmp
#print('tmp', tmp)
return tmp
def solution(expression):
answer = 0
operations = {}
for exp in expression:
if exp in ['+', '-', '*']:
operations[exp] = 1
operations = [k for k in operations.keys()]
#print('Operations', operations)
expression = expression.replace('+', ' + ')
expression = expression.replace('-', ' - ')
expression = expression.replace('*', ' * ')
expression = expression.split()
for i in range(len(expression)):
if expression[i].isnumeric():
expression[i] = int(expression[i])
#print('Expression', expression)
#print(permute_list(operations))
permute_operations = permute_list(operations)
#print('Permute Operations', permute_operations)
results = []
for permute_operation in permute_operations:
result = sub_calc(permute_operation, expression)
results.append(abs(result[0]))
answer = max(results)
return answer
파이썬에는 기본적으로 eval()함수가 내장되어있는데, 문자열 형태로 연산형태를 주면 알아서 계산해서 결과를 반해준다. 이를 이용하면 나처럼 calc()함수를 정의하지 않아도 된다.