Posts 프로그래머스 Level 2 - 수식 최대화 (JavaScript)
Post
Cancel

프로그래머스 Level 2 - 수식 최대화 (JavaScript)

프로그래머스 - Level2 수식 최대화

문제 설명

문제 설명 생략

🙋‍♂️나의 풀이

🤔문제 접근

다른 분들의 코드를 참고해서 작성했다.

  1. 연산자의 모든 조합을 생성한다.
    • 연산자는 +, -, * 뿐이고, 생성 가능한 모든 경우의 수는 6가지다.
  2. 정규 표현식으로 연산자와 피연산자를 분리한다.
    • split 함수에 정규 표현식을 전달한다.
  3. 1번에서 생성한 조합의 연산자 우선 순위에 따라 계산 결과를 저장한다.
  4. 연산 결과의 절댓값이 가장 큰 값을 반환한다.

✍️작성 코드

우선, 연산자의 조합 가능한 모든 6가지 경우의 수를 다음과 같이 선언했다.

경우의 수가 적기 때문에 재귀 함수로 모든 조합을 생성하기 보단 직접 선언해주었다.

1
2
3
4
5
6
7
8
const combinations = [
    ['+', '-', '*'],
    ['+', '*', '-'],
    ['*', '+', '-'],
    ['*', '-', '+'],
    ['-', '+', '*'],
    ['-', '*', '+'],
];

그리고 연산자에 따라 계산을 수행할 객체 operators 를 선언했다.

이 객체 안에 함수를 선언한 이유는 eval 함수를 사용하지 않기 위해서다.

eval 함수는 문자열로 표현된 값을 실행문으로 변환하는 함수이다.

하지만, eval 함수는 보안, 성능, 디버깅의 어려움의 이유로 사용을 금지하고 있다.

1
2
3
4
5
const operators = {
    '+': (a, b) => a + b,
    '-': (a, b) => a - b,
    '*': (a, b) => a * b
}

연산자와 피연산자를 구분하기 위한 정규 표현식 객체를 생성했다.

함수에 직접 정규 표현식을 입력하지 않는다면, new RegExp 생성자로 정규 표현식 객체를 생성해서 전달해야 한다.

1
const regex = new RegExp(/(\D)/);

\D 는 숫자가 아닌 것을 의미하고, (\D) 와 같이 소괄호로 묶으면 소괄호 안에 매칭된 결과를 모두 기억한다.

소괄호의 유무에 따른 실행 결과는 다음과 같다.

1
2
3
const string = "12+34"
console.log(string.split(/\D/))    // ["12", "34"]
console.log(string.split(/(\D)/))  // ["12", "+", "34"]

모든 경우의 수에 대해 연산자의 우선 순위대로 연산을 수행한다.

1
2
3
4
5
6
7
8
9
10
11
for (const comb of combinations) {
    const result = expression.split(regex);
    for (const operator of comb) {
        while (result.includes(operator)) {
            const i = result.indexOf(operator);
            const calculation = operators[operator](+result[i - 1], +result[i + 1])
            result.splice(i - 1, 3, calculation)
        }
    }
    answer.push(Math.abs(result));
}

예를 들어, expression123+456-789 이면 result 변수에는 다음과 같이 저장된다.

1
["123", "+", "456", "-", "789"];

현재 확인하고 있는 연산자에 따라 연산자의 앞, 뒤로 놓인 피연산자에 맞는 연산을 수행한다.

1
2
const i = result.indexOf(operator);
const calculation = operators[operator](+result[i - 1], +result[i + 1])

그 다음 result 배열에서 연산을 수행한 연산자와 피연산자는 지우고, 그 자리에 연산을 수행한 결과를 넣는다.

1
result.splice(i - 1, 3, calculation)

모든 연산자에 대해 연산이 끝나면, 절댓값을 붙여서 answer 배열에 추가한다.

1
answer.push(Math.abs(result));

최종적으로 완성한 코드는 다음과 같다.

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
function solution(expression) {
    const answer = []
    const combinations = [
        ['+', '-', '*'],
        ['+', '*', '-'],
        ['*', '+', '-'],
        ['*', '-', '+'],
        ['-', '+', '*'],
        ['-', '*', '+'],
    ];
    const operators = {
        '+': (a, b) => a + b,
        '-': (a, b) => a - b,
        '*': (a, b) => a * b
    }
    const regex = new RegExp(/(\D)/);
    for (const comb of combinations) {
        const result = expression.split(regex);
        for (const operator of comb) {
            while (result.includes(operator)) {
                const i = result.indexOf(operator);
                const calculation = operators[operator](+result[i - 1], +result[i + 1])
                result.splice(i - 1, 3, calculation)
            }
        }
        answer.push(Math.abs(result));
    }
    return Math.max(...answer);
}

참고자료

This post is licensed under CC BY 4.0 by the author.

프로그래머스 Level 2 - 교점에 별 만들기 (JavaScript)

동적 계획법(Dynamic Programming) 개념과 구현 (feat. 2 x n 타일링)