[프로그래머스] 수식 최대화

joon_1592·2022년 1월 19일

알고리즘

목록 보기
21/51

풀이 전 셀프 제한조건

파이썬은 여러 모듈들이 굉장히 편리하게 사용이 가능하다.
자료구조를 제외하고 가급적 사용하지 않으려고 한다.
이번에는 정규표현식과 permutation을 사용하지 않고 구현한다.

나의 첫 풀이

  1. expression을 숫자와 연산자를 분리한다.
  2. 가능한 연산자의 순열을 만든다.
  3. 순열의 우선순위대로 연산한 결과의 절댓값을 저장한다.
  4. 저장한 결괏값의 최댓값이 정답

나의 고민들

1. 숫자와 연산자 분리

split()으로 좌라락 하고싶었지만 안타깝게도 파라미터는 하나의 문자열만 가능하다.
정규표현식을 이용하면 numbers = re.split(r'(\D)',expression) 로 숫자만 추출하는것이 가능하다.
+ - *만 등장하는 것이므로 약간의 노가다로 해결했다

expression = expression.replace('+', ' + ')
expression = expression.replace('-', ' - ')
expression = expression.replace('*', ' * ')
expression = expression.split()

2. 순열

우선 필요없는 연산자를 빼고 필요한 연사자만 모으고 싶었다.

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개밖에 없으니 그냥 노가다로 구현하기로 했다

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

다른 사람의 풀이

1. eval()

파이썬에는 기본적으로 eval()함수가 내장되어있는데, 문자열 형태로 연산형태를 주면 알아서 계산해서 결과를 반해준다. 이를 이용하면 나처럼 calc()함수를 정의하지 않아도 된다.

profile
공부용 벨로그

0개의 댓글