728x90
# 조건
- 해커톤 대회에 참가하는 모든 참가자들에게는 숫자들과 3가지의 연산문자(
+, -, *
) 만으로 이루어진 연산 수식이 전달되며, 참가자의 미션은 전달받은 수식에 포함된 연산자의 우선순위를 자유롭게 재정의하여 만들 수 있는 가장 큰 숫자를 제출하는 것입니다.- 단, 연산자의 우선순위를 새로 정의할 때, 같은 순위의 연산자는 없어야 합니다. 즉,
+
>-
>*
또는-
>*
>+
등과 같이 연산자 우선순위를 정의할 수 있으나+,*
>-
또는*
>+,-
처럼 2개 이상의 연산자가 동일한 순위를 가지도록 연산자 우선순위를 정의할 수는 없습니다. - 수식에 포함된 연산자가 2개라면 정의할 수 있는 연산자 우선순위 조합은 2! = 2가지이며, 연산자가 3개라면 3! = 6가지 조합이 가능합니다.
- 단, 연산자의 우선순위를 새로 정의할 때, 같은 순위의 연산자는 없어야 합니다. 즉,
- 만약 계산된 결과가 음수라면 해당 숫자의 절댓값으로 변환하여 제출하며 제출한 숫자가 가장 큰 참가자를 우승자로 선정하며, 우승자가 제출한 숫자를 우승상금으로 지급하게 됩니다.
- 예를 들어, 참가자 중
네오
가 아래와 같은 수식을 전달받았다고 가정합니다."100-200*300-500+20"
- 일반적으로 수학 및 전산학에서 약속된 연산자 우선순위에 따르면 더하기와 빼기는 서로 동등하며 곱하기는 더하기, 빼기에 비해 우선순위가 높아
*
>+,-
로 우선순위가 정의되어 있습니다.
- 대회 규칙에 따라
+
>-
>*
또는-
>*
>+
등과 같이 연산자 우선순위를 정의할 수 있으나+,*
>-
또는*
>+,-
처럼 2개 이상의 연산자가 동일한 순위를 가지도록 연산자 우선순위를 정의할 수는 없습니다. - 수식에 연산자가 3개 주어졌으므로 가능한 연산자 우선순위 조합은 3! = 6가지이며, 그 중
+
>-
>*
로 연산자 우선순위를 정한다면 결괏값은 22,000원이 됩니다. - 반면에
*
>+
>-
로 연산자 우선순위를 정한다면 수식의 결괏값은 -60,420 이지만, 규칙에 따라 우승 시 상금은 절댓값인 60,420원이 됩니다.
참가자에게 주어진 연산 수식이 담긴 문자열 expression이 매개변수로 주어질 때, 우승 시 받을 수 있는 가장 큰 상금 금액을 return 하도록 solution 함수를 완성해주세요.
제한사항
- expression은 길이가 3 이상 100 이하인 문자열입니다.
- expression은 공백문자, 괄호문자 없이 오로지 숫자와 3가지의 연산자(
+, -, *
) 만으로 이루어진 올바른 중위표기법(연산의 두 대상 사이에 연산기호를 사용하는 방식)으로 표현된 연산식입니다. 잘못된 연산식은 입력으로 주어지지 않습니다.- 즉,
"402+-561*"
처럼 잘못된 수식은 올바른 중위표기법이 아니므로 주어지지 않습니다.
- 즉,
- expression의 피연산자(operand)는 0 이상 999 이하의 숫자입니다.
- 즉,
"100-2145*458+12"
처럼 999를 초과하는 피연산자가 포함된 수식은 입력으로 주어지지 않습니다. "-56+100"
처럼 피연산자가 음수인 수식도 입력으로 주어지지 않습니다.
- 즉,
- expression은 적어도 1개 이상의 연산자를 포함하고 있습니다.
- 연산자 우선순위를 어떻게 적용하더라도, expression의 중간 계산값과 최종 결괏값은 절댓값이 263 - 1 이하가 되도록 입력이 주어집니다.
- 같은 연산자끼리는 앞에 있는 것의 우선순위가 더 높습니다.
# 접근 방법
- 연산자와 숫자를 나눠서 저장해준다.
- 연산자의 idx가 0이라면 숫자 리스트의 0번과 1번 인덱스를 연산자 0번 인덱스로 연산해주면 된다.
- 이 때, 계산한 결과를 nums[idx]에 저장 해준 후 idx+1 번째 값을 pop 해준다.
- 여기서, 연산자의 idx를 pop 해주지 않아서 시간을 많이 뺏겼다.
- 또한, 연산자의 idx를 pop 해준 후 인덱스 에러를 해결하기 위하여 while문을 활용해주었다.
- val_op를 pop 해준다면 idx를 그대로, 하지 않는다면 +1 씩 해서 찾아준다.
from copy import deepcopy
def solution(expression):
# (+,-, *) -> 우선순위를 자유롭게 재정의 가능
# 동일한 연산자 우선순위는 불가능
# 계산 결과가 음수라면 해당 숫자의 절댓값으로 변환
answer = 0
oper = []
nums = []
num = ''
# 숫자 연산자 나눠서 저장 해주기
for i in expression:
if i == '+' or i == '-' or i == '*':
oper.append(i)
nums.append(num)
num = ''
else:
num += i
nums.append(num)
# 연산자 우선 순위
prior = [['*', '+', '-'],['*', '-', '+'],['+', '*', '-'],['+', '-', '*'],['-', '*', '+'],['-', '+', '*']]
result = 0
for op in prior:
val_op = deepcopy(oper)
val_num = deepcopy(nums)
now_val = ''
val = 0
for p in op:
idx = 0
while idx < len(val_op):
if not val_op:
break
if val_op[idx] == p:
now_val = eval(str(val_num[idx]) + p + str(val_num[idx+1]))
val_num[idx] = now_val
val_num.pop(idx+1)
val_op.pop(idx)
if len(val_num) == 1:
print(val_num[0])
if abs(val_num[0]) > result:
result = abs(val_num[0])
break
continue
idx += 1
answer = result
return answer
다른 분 풀이
- 문자열 포맷팅을 이용하여 풀었다.
- op에 있는 연산자의 역순으로 계산을 해주며 join과 eval을 사용해주었다.
- split을 이용하여 연산자를 기준으로 2번 나눠주는데, 이렇게 되면
- 현재 연산자가 + 인 경우, +를 포함한 연산들만 남는다 => [100, 10+20, 50]
- 역순으로 b와 a로 나눠놨던 연산자를 join을 이용하여 다시 문자열로 만들어 준다. => (100-(10+20)-50) * (30) 과 같이 된다.
- eval로 연산해준 후 max로 비교
역순과 문자열 포맷팅을 정말 잘 이용하신 것 같다. 한참 부족함을 또 느꼈지만 좋은 것 배워가는 것 같다
+ eval 은 보안상 문제가 있을 수 있어서 실전에선 사용하지 않는 것이 좋다는 것도 알게 되었습니다! eval 없이 푸는 방법도 연습해야 될 것 같다.
def solution(expression):
operations = [('+', '-', '*'),('+', '*', '-'),('-', '+', '*'),('-', '*', '+'),('*', '+', '-'),('*', '-', '+')]
answer = []
for op in operations:
a = op[0]
b = op[1]
temp_list = []
for e in expression.split(a):
temp = [f"({i})" for i in e.split(b)]
temp_list.append(f'({b.join(temp)})')
answer.append(abs(eval(a.join(temp_list))))
return max(answer)
728x90
'ALGORITHM > 자료구조' 카테고리의 다른 글
[백준 2042번] 파이썬 - 구간 합 구하기 (0) | 2023.05.14 |
---|---|
[백준 1655번] 파이썬 - 가운데를 말해요 (0) | 2023.05.06 |
[백준 4386번] 파이썬 - 별자리 만들기 (0) | 2023.04.22 |
[백준 2887번] 파이썬 - 행성 터널 (0) | 2023.04.21 |
[백준 20920번] 파이썬 - 영단어 암기는 괴로워 (0) | 2023.04.19 |