코딩테스트/Programmers

[JS] 수식 최대화

hxx_1 2024. 12. 30. 21:53

https://school.programmers.co.kr/learn/courses/30/lessons/67257

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

< 풀이 >

function solution(expression) {
    var answer = 0;
    let number = '';
    let set = new Set();
    let arr = new Array();
    
    for(let i = 0; i < expression.length; i++){
        if(expression[i] == '-' || expression[i] == '+' || expression[i] == '*'){
            set.add(expression[i]);
            arr.push(number);
            arr.push(expression[i]);
            number = '';
        }
        else {
            number += expression[i];
        }
    }
    arr.push(number);
    
    let setToArray = Array.from(set);
    let sequence = permutation(setToArray);
    
    for(let i = 0; i < sequence.length; i++){
        let copyArr = [...arr]; // 배열 복사
        for(let j = 0; j < sequence[i].length; j++){
            let index = copyArr.indexOf(sequence[i][j]);
            while(index !== -1) {
                let result = calculate(Number(copyArr[index-1]), Number(copyArr[index+1]), sequence[i][j]);
                copyArr.splice(index-1, 3, result);
                index = copyArr.indexOf(sequence[i][j]);
            }
        }
        answer = Math.max(answer, Math.abs(copyArr[0]));
    }
    
    return answer;
}

function permutation(arr) { // 순열 
    if(arr.length === 1)
        return [arr];
    const result =[];
    
    for(let i=0;i<arr.length;i++){
        const current = arr[i];
        // 현재 선택한 원소를 제외한 나머지 배열
        const others = arr.slice(0,i).concat((arr.slice(i+1)));
        // 나머지 배열로 순열을 구함
        const perms = permutation(others);
        // 현재 원소를 맨 앞에 추가
        perms.forEach(perm => {
            result.push([current,...perm]);
        })
    }
    
    return result;
}

function calculate(a, b, operator) {
        if (operator === '+') return a + b;
        if (operator === '-') return a - b;
        if (operator === '*') return a * b;
}

✏️ 풀이 방법

1. 수식을 돌면서, 연산자일 경우 set에 저장을 한다. (중복을 제거하기 위함) , arr 배열에 숫자와 연산자를 분리하여 저장한다.

ex) arr = [100, - , 200 , * , 300 ...]

 

2. set 을 배열로 변환하여 순열을 구한다. 

=> 모든 연산자 경우의 수를 구하여 sequence 라는 변수에 저장한다.

[
  [ '-', '*', '+' ],
  [ '-', '+', '*' ],
  [ '*', '-', '+' ],
  [ '*', '+', '-' ],
  [ '+', '-', '*' ],
  [ '+', '*', '-' ]
]

 

3. 각각의 경우의 수를 돌 때마다 원본 배열을 복사하여 계산을 수행한다. 

① 우선, indexOf 를 통해 해당 연산자가 있는 위치를 찾는다.

② index 가 -1 일 때까지 ( 즉 해당 연산자가 없을 때까지)

: 현재 index(연산자의 위치) 의 양 옆에 있는 숫자를 계산하여 result 라는 변수에 저장한다.

: 계산이 완료된 부분( 연산자와 피연산자) 는 splice 를 이용해 배열에서 제거하고, 제거한 자리에 계산된 값(result)을 삽입한다. 

: 변환된 배열 내에서 indexOf 를 통해 또 해당 연산자가 있는지 확인하여 index 에 저장한다.

( 없으면 -1 이 저장되고, 있으면 해당 인덱스가 저장됨)

③ 다음 경우의 수로 넘어가기 전에 answer에 계산이 완료된 값의 절대값과 answer 중에 최대값을 저장한다. 

④ answer 을 return 한다. 

 

🌟 배운 점

1. indexOf 메소드

:  배열이나 문자열에서 특정 요소의 첫 번째 위치(인덱스) 를 찾는 메서드

// 배열에서 사용
array.indexOf(searchElement, fromIndex)

// 문자열에서 사용
string.indexOf(searchValue, fromIndex)
  • 찾는 요소가 없으면 -1을 반환
  • 대소문자를 구분
  • fromIndex는 선택사항(생략 가능)
  • 첫 번째 일치하는 요소의 인덱스만 반환

2. splice 메소드

: 배열의 특정 인덱스 값을 지움

const array = [1, 2, 3, 4, 5];
array.splice(2, 1); // 인덱스 2의 값을 1개 삭제
console.log(array); // [1, 2, 4, 5]
  • splice 메소드는 원본 배열을 직접 수정함
  • 첫 번째 매개변수: 삭제를 시작할 인덱스
  • 두 번째 매개변수: 삭제할 요소의 개수
  • 삭제된 요소들은 새 배열로 반환됨

+ 응용

const numbers = [1, 2, 3, 4, 5];
const idx = 1;
const result = 10;

numbers.splice(idx, 2, result);
console.log(numbers); // [1, 10, 4, 5]

: 인덱스 1부터 시작해서 2개의 요소(2,3) 을 제거하고 그 자리에 result 값(10) 을 넣음

 

3. 순열( permutation )

: n 개의 서로 다른 원소를 순서대로 나열하는 방법

function permutation(arr) { // 순열 
    if(arr.length === 1)
        return [arr];
    const result =[];
    
    for(let i=0;i<arr.length;i++){
        const current = arr[i];
        // 현재 선택한 원소를 제외한 나머지 배열
        const others = arr.slice(0,i).concat((arr.slice(i+1));
        // 나머지 배열로 순열을 구함
        const perms = permutation(others);
        // 현재 원소를 맨 앞에 추가
        perms.forEach(perm => {
            result.push([current,...perm]);
        })
    }
    
    return result;
}

 

ex) arr = [1,2,3] 일 경우 

 

① 첫 번째 반복 (i=0, current =1)

current = 1
others = [2,3] // slice(0,0).concat(slice(1)) = [].concat([2,3])
perms = permutation([2,3]) 호출
    // [2,3] 순열 구하기
    current = 2
    others = [3] // slice(0,0).concat(slice(1)) = [].concat([3])
    perms = permutation([3]) // [[3]] 반환 (길이가 1이므로)
    result = [[2,3]]

    current = 3
    others = [2]
    perms = permutation([2]) // [[2]] 반환
    result = [[2,3], [3,2]]

최종적으로 result에 [1,2,3], [1,3,2] 추가

 

② 두 번째 반복 (i=1, current=2)

current = 2
others = [1,3] // slice(0,1).concat(slice(2)) = [1].concat([3])
perms = permutation([1,3]) 호출
    // [1,3] 순열 구하기
    current = 1
    others = [3]
    perms = permutation([3]) // [[3]] 반환
    result = [[1,3]]

    current = 3
    others = [1]
    perms = permutation([1]) // [[1]] 반환
    result = [[1,3], [3,1]]

최종적으로 result에 [2,1,3], [2,3,1] 추가

 

③ 세 번째 반복 (i=2, current =3)

current = 3
others = [1,2] // slice(0,2).concat(slice(3)) = [1,2].concat([])
perms = permutation([1,2]) 호출
    // [1,2] 순열 구하기
    current = 1
    others = [2]
    perms = permutation([2]) // [[2]] 반환
    result = [[1,2]]

    current = 2
    others = [1]
    perms = permutation([1]) // [[1]] 반환
    result = [[1,2], [2,1]]

최종적으로 result에 [3,1,2], [3,2,1] 추가

 

➡️ 최종 결과: [[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]]