티스토리 뷰
반응형
📎 간략한 문제 정리
- 기존 사칙연산의 연산자 우선순위가 아니라 임의로 연산자 우선순위를 정해 주어진 expression의 연산을 합니다. 연산 결과의 절대값 중 가장 큰 값을 반환합니다.
📈 문제 분석
- 이 경우 모든 경우를 탐색하는 Brute-Force(완전 탐색)을 통해 최적의 결과를 찾아냅니다.
🙋♂️ 내가 처음 생각한 해결 방법
- 기존의 제 풀이는 연산자 우선순위대로 탐색하며 연산을 진행하고, 다음 연산자를 검색하며 다음 연산을 진행하는 방식으로 결과를 찾았습니다. 하지만 공부를 위해 이 문제를 새로 풀며 중위 표기를 후위 표기로 바꾸는 과정에 연산자 우선순위가 있음을 기억했고 그 연산자 우선순위 표만 바꾸는 구조로 작성하면 되므로 중위를 후위로 바꾸는 메소드 한개, 후위 연산을 계산하는 메소드 한개를 추가로 만들어 모든 경우 탐색을 했습니다. 중위 연산을 후위 연산으로 만드는 방법을 공부해보기 위해 새로운 코드를 짰습니다.
💻 풀이한 코드
⌚️ 예전 풀이
from itertools import permutations
import math
# 리스트의 내용물을 편집할 때 길이가 바뀔 때에는 직접 리스트를 편집하는 것은 좋지 않다.
def solution2(expression):
# 연산자의 우선 순위 정하기
# expression을 순회하며 존재하는 연산자를 확인한다.
opers = []
for i in range(len(expression)):
# 만약 i번째 요소가 연산자이면 연산자를 opers에 저장한다.
if not expression[i].isdecimal() and expression[i] not in opers:
opers.append(expression[i])
# 연산자 우선순위를 결정한다.
opers_priority = list(permutations(opers, len(opers)))
# expression을 연산자를 기준으로 나눈다.
idx = 0
temp = []
splited_expression = []
# expression을 연산자를 기준으로 나누어 저장한다.
while True:
# 숫자이면 임시저장소에 저장
if expression[idx].isdecimal():
temp.append(expression[idx])
# 마지막 요소라면 뒤에 연산자가 없으므로 바로 넣어주고 종료한다.
if idx == len(expression)-1:
splited_expression.append(''.join(temp))
idx += 1
# 연산자이면 기존에 저장되있던 요소와 연산자를 각각 splited_expression에 저장한다.
else:
splited_expression.append(''.join(temp))
splited_expression.append(expression[idx])
temp = []
idx += 1
# 끝까지 도달하면 종료
if idx == len(expression):
break
max_val = -math.inf
for i in range(len(opers_priority)):
# 연산자 우선순위가 결정된 리스트
order = opers_priority[i]
temp_list = splited_expression[:]
# 연산자 결정
for j in range(len(order)):
idx = 0
while idx<len(temp_list):
if temp_list[idx] == order[j]:
temp_list = temp_list[:idx-1]+[str(eval(''.join(temp_list[idx-1:idx+2])))]+temp_list[idx+2:]
else:
idx += 1
if abs(int(temp_list[0])) > max_val:
max_val = abs(int(temp_list[0]))
return max_val
🙋 새로운 풀이
def solution(expression):
from itertools import permutations
operations = [1, 2, 3]
operation_priorities = list(permutations(operations, 3))
priority_dict = {}
result = 0
for priority in operation_priorities:
priority_dict["+"] = priority[0]
priority_dict["-"] = priority[1]
priority_dict["*"] = priority[2]
oper_result = int(calculate_with_suffix(infix_to_suffix(expression, priority_dict)))
result = max(abs(oper_result), result)
return result
def infix_to_suffix(infix, priority):
suffix = []
stack = []
temp = ""
for token in infix:
if token.isnumeric():
temp += token
else:
suffix.append(temp)
temp = ""
if not stack or priority[stack[-1]] < priority[token]:
stack.append(token)
else:
while stack:
if priority[stack[-1]] >= priority[token]:
suffix.append(stack.pop())
else:
break
stack.append(token)
suffix.append(temp)
suffix.extend(stack[::-1])
return suffix
def calculate_with_suffix(suffixes):
stack = []
for suffix in suffixes:
if suffix.isdecimal():
stack.append(suffix)
else:
latter = stack.pop()
former = stack.pop()
stack.append(str(eval(former+suffix+latter)))
return stack[-1]
📝 해결 과정에서 만난 문제, 고민들
- 괄호의 존재 여부:
- 일반적으로 인터넷에 구현된 중위표현을 후위표현으로 바꾸는 메소드는 괄호가 존재합니다. 그래서 구현 방식에 차이를 줘야했지만 생각해보면 중위표현은 ISP, ICP로 스택 내에서 우선순위, 스택 바깥에서 우선순위에 괄호가 포함되어 있습니다. 그래서 괄호를 특별 취급하지않고 우선순위만 따져 로직을 작성했습니다.
- 중위 표현식에서 연산자가 나왔을 때 stack의 top과 비교시:
- 의 경우 '-' 연산자의 우선순위가 곱하기 연산보다 낮기 때문에 곱하기 연산자를 pop해야 합니다. 그 다음 '+'의 경우 '-' 연산자와 우선순위가 같은데 이 경우도 '-' 연산자의 우선순위보다 '+' 연산자의 우선순위가 '작지 않기 때문에' pop 합니다. 이것을 생각해보면 stack에서 pop 하는 경우는 토큰 연산자, 이 경우 '-' 연산자보다 먼저 연산되야 하는 경우인데 연산자 우선순위가 같은 경우 먼저 존재하는 연산이 먼저 진행되어야 하므로 pop 하는 것을 알 수 있습니다.
- 인터넷의 예시들은 보통 연산자 종류를 다양하게 만들어 stack의 top과 토큰 연산자의 우선순위가 달랐습니다. 하지만 연산자 우선 순위가 같은 경우는 찾기 힘들었습니다. 이 문제의 경우 연산자 우선순위가 같은 경우가 존재하지 않지만 학습을 위해 생각해보았습니다. 로직을 고민해본 결과 토큰 연산자의 우선순위가 stack의 top보다 클 때에만 stack에 토큰 연산자를 pop 없이 push하므로 같은 경우는 top의 연산자의 우선순위가 더 큰 경우처럼 pop 해줍니다. 예를 들어
반응형
'알고리즘 학습 > 프로그래머스' 카테고리의 다른 글
[Programmers] - 불량 사용자 (2019 카카오 개발자 겨울 인턴십) with Python (0) | 2021.05.08 |
---|---|
[Programmers] - 보석 찾기 (2020 카카오 인턴십) with Python (0) | 2021.05.05 |
[Programmers] - 키패드 누르기 (2020 카카오 인턴십) with Python (0) | 2021.05.01 |
[Programmers] - N으로 표현 (동적계획법) with Python (0) | 2021.04.24 |
[Programmers] - 입국심사 (이분탐색) with Python (0) | 2021.04.23 |
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 병든 나이트#BOJ#탐욕법#Python
- Swift#Tuples#Range
- API#lazy#
- 토마토#백준알고리즘#Python
- PassingCars#Codility#Python
- 종이자르기#분할정복#BOJ#Python
- 파이썬알고리즘인터뷰#4장
- 배열합치기#분할정복#BOJ#Python
- 텀 프로젝트#백준알고리즘#Python
- Brackets#Stacks and Queues#Codility#Python
- filter#isalnum#lower
- 미로 탐색#백준알고리즘#Python
- 백준 알고리즘#BackTracking
- 나무자르기#BOJ#이분탐색#Python
- 공유기 설치#BOJ#이분탐색#Python
- django#slicing
- Distinct#Codility#Python
- N으로 표현#DP#Programmers#Python
- 순열사이클#BOJ#Python
- 쿼드트리#BOJ#분할정복#Python
- 반복수열#백준알고리즘#Python
- 날짜 계산#BOJ#완전탐색#Python
- 랜선자르기#이분탐색#BOJ#Python
- Triangle#Sorting#Codility#Python
- 터틀비치#리콘#xbox#controller
- 섬의개수#백준알고리즘#Python
- NumberofDiscIntersections#Codility#Sort#Python
- django
- 암호코드#dp#BOJ#Python
- 리모컨#완전탐색#BOJ#Python
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
글 보관함