본문으로 바로가기

programmers. 수식 최대화

category Algorithm/문제 2021. 4. 11. 14:23

문제

문제는 여기서

 

코딩테스트 연습 - 수식 최대화

IT 벤처 회사를 운영하고 있는 라이언은 매년 사내 해커톤 대회를 개최하여 우승자에게 상금을 지급하고 있습니다. 이번 대회에서는 우승자에게 지급되는 상금을 이전 대회와는 다르게 다음과

programmers.co.kr

풀이

문제는 길고 조건이 있어서 거창해보이지만 사실 보면 해야할 것은 세 가지다

  1. 문자열 파싱하기
  2. 연산자 순서 정하기
  3. 정한 순서로 계산하기

1번 과정에서 split에 정규 표현식을 사용할 수 있다는 것을 알았다.. 삽질 몇번하니 연산자와 숫자를 나눈 배열을 얻을 수 있었고

2번은 순열 구하듯이 재귀를 이용해서 만들어서 구해도 되고

곱하기, 더하기, 빼기 3가지의 연산자만 사용하고 있기 때문에 손으로 6가지 경우를 하드코딩해도된다

문제는 3번째였는데

계산하는 것을 어떻게 할까 곰곰히 생각하다가

2번에서 구한 우선 순위로 연산자를 1번에서 구한 배열에서 찾은 뒤 연산 후 배열을 압축.. 반복하기로 했다

1st

    function solution(expression) {
        var answer = [];
        let arr = expression.split(/(\-|\+|\*)/g);
        const cycle = per(['*','+','-'],3);
        arr = arr.map(v=>Number(v)? Number(v): v);


        cycle.forEach(operator=>{
           answer.push(operation(operator,arr));
        });

        console.log(answer);

        return Math.max(...answer);
    }

    function operate(elem1, elem2, op) {
        const functionObj = {
            '*' : (a,b)=> a*b,
            '+' : (a,b)=> a+b,
            '-' : (a,b)=> a-b,
        };
        return functionObj[op](elem1,elem2);
    }

    function operation(operator, originalArr) {
        const arr = [...originalArr];
        for(let j=0; j<operator.length;j++){
            let i = 1;
            while (i<arr.length){
                console.log(arr)
                console.log(arr[i]);
                if(arr[i]===operator[j]){
                    const temp = operate(arr[i-1],arr[i+1],operator[j]);
                    arr.splice(i,1);
                    arr.splice(i,1);
                    arr[i-1] = temp;
                    continue;
                }
                i+=2;
            }
        }
        return Math.abs(arr[0]);
    }

    function per(arr, selected){
        const result = [];
        if(selected ===1) return  arr.map(v=>[v]);

        arr.forEach((value,index,array)=>{
            let rest = [...array.slice(0,index),...array.slice(index+1)];
            let combinations = per(rest,selected-1);
            let combineArr = combinations.map(v=>[value,...v]);
            result.push(...combineArr);
        });
        return result;
    }

6가지 경우의 모든 값을 구해서 answer 배열에 넣고 최대값을 리턴하는 solution을 만들었는데..

3,4,8번 케이스가 틀리면서 90점으로 나왔다

질문하기에는 반례도 없고 다른 사람 풀이를 보기에는 자존심이 상해서 혼자 이것 저것 넣으면서 보고있는데

0+0+0을 넣고 나서 파싱한 arr를 숫자로 바꿔주는 부분에 문제가 있음을 알게되었다

        arr = arr.map(v=>Number(v)? Number(v): v);

Number(str)은 str에 숫자로 변환할 수 있는 값이 오면 숫자로 변환하고 그렇지 않으면 NaN을 반환한다

그 점을 이용해서 숫자는 숫자로 문자열은 그대로 놔두는 변환을 시도했는데

수식에 숫자 0이 들어가면 Number(0)은 0으로 반환되고 이 값이 false로 처리되기 때문에 숫자임에도 불구, 문자 "0"으로 arr배열에 들어간다

계산 과정에서 0+0은 0이 아닌 "00"이 되는 것을 보고 알아차렸다

정답 코드

    function solution(expression) {
        var answer = [];
        let arr = expression.split(/(\-|\+|\*)/g);
        const cycle = per(['*','+','-'],3);
        arr = arr.map(v=>{
            if(v==='-'||v==='+'||v==='*') return v;
            return Number(v);
        });

        cycle.forEach(operator=>{
           answer.push(operation(operator,arr));
        });

        console.log(answer);

        return Math.max(...answer);
    }

    function operate(elem1, elem2, op) {
        const functionObj = {
            '*' : (a,b)=> a*b,
            '+' : (a,b)=> a+b,
            '-' : (a,b)=> a-b,
        };
        return functionObj[op](elem1,elem2);
    }

    function operation(operator, originalArr) {
        const arr = [...originalArr];
        for(let j=0; j<operator.length;j++){
            let i = 1;
            while (i<arr.length){
                console.log(arr)
                console.log(arr[i]);
                if(arr[i]===operator[j]){
                    const temp = operate(arr[i-1],arr[i+1],operator[j]);
                    arr.splice(i,1);
                    arr.splice(i,1);
                    arr[i-1] = temp;
                    continue;
                }
                i+=2;
            }
        }
        return Math.abs(arr[0]);
    }

    function per(arr, selected){
        const result = [];
        if(selected ===1) return  arr.map(v=>[v]);

        arr.forEach((value,index,array)=>{
            let rest = [...array.slice(0,index),...array.slice(index+1)];
            let combinations = per(rest,selected-1);
            let combineArr = combinations.map(v=>[value,...v]);
            result.push(...combineArr);
        });
        return result;
    }

성공!

'Algorithm > 문제' 카테고리의 다른 글

programmers. 뉴스클러스터링  (0) 2021.04.13
programmers. 게임 맵 최단거리  (0) 2021.04.12
baekjoon. 큐 2  (0) 2021.03.08
baekjoon. 괄호  (0) 2021.03.07
baekjoon. 주유소  (0) 2021.01.29