본문 바로가기
코딩테스트/프로그래머스

[프로그래머스] 2020 KAKAO 인턴십 > 수식 최대화 - 자바스크립트

by 핸디(Handy) 2021. 4. 7.

문제 설명

programmers.co.kr/learn/courses/30/lessons/67257

 

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

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

programmers.co.kr


[ 아이디어 ]

순열조합을 사용하여 가능한 조합을 모두 뽑아온다음 하나씩 제거하면서 계산함

문제에서 3가지 연산자(+,-,*)만 사용한다고 제한을 두어 조합은 최대 6개밖에 안나와서 순열조합을 쓰지않고 일일히 조합을 만드는 방법도 있지만 연습이니깐 순열조합을 사용해봤음

[ 코드 ]

function solution(expression) {
  let answer = 0;
  let operator = expression.replace(/[0-9]/g,""); //계산해야할 연산자들만 가져옴
  let uniqueOperator = Array.from(new Set(operator)); // 우선순위를 계산하기 위해 유니크한 연산자만 가져옴
  let permuList = permutator(uniqueOperator); // 순열조합으로 우선순위별로 가능한 조합 가져옴
  let numberList = expression.split(/[\+\-\*\/]/); // 연산자를 제외한 숫자들만 들고옴

  permuList.forEach((item)=> { // 조합가능한 우선순위별로 하나씩 가져와서
    let tempOperator = operator; // 재사용하기 위해 복사하고
    let tempNumberList = [...numberList];
      for(let i =0; i< item.length ; i++){
        while(tempOperator.includes(item[i])){ //우선순위가 앞에 있는 연산자가 더 있나 확인하고 없으면 해당 연산자 끝
          let currentCalIndex = tempOperator.indexOf(item[i]); //계산해야할 연산자의 인덱스 위치앚고
          let test = tempNumberList[currentCalIndex] + item[i] + tempNumberList[currentCalIndex+1]; //해당 앞뒤로 number을 가져와서
          tempNumberList.splice(currentCalIndex,2,eval(test)); //계산된 숫자들을 없애고 새롭게 계산된 값을 넣고
          tempOperator =tempOperator.replace(item[i],"") // 계산왼료된 연산자 1개는 없앤다
        }
      }
      if(answer < Math.abs(tempNumberList[0])) answer = Math.abs(tempNumberList[0]); // 절대값 비교해서 큰수처리
  })
  return answer;
}

function permutator(inputArr) {
  var results = [];
  function permute(arr, memo) {
    var cur, memo = memo || [];
    for (var i = 0; i < arr.length; i++) {
      cur = arr.splice(i, 1);
      if (arr.length === 0) {
        results.push(memo.concat(cur));
      }
      permute(arr.slice(), memo.concat(cur));
      arr.splice(i, 0, cur[0]);
    }
    return results;
  }

  return permute(inputArr);
}

 

[ 팁 ]

팁보다는 원래 소스코드 상에서 eval() 하는 행동은 무적이나 위험합니다. 들어온 인수를 코드로 그대로 실행하기 때문에 어떤 문제를 발생시킬지 모르기 때문입니다.

따라서 코드에서

// 위험
eval(test)
// 그나마 안전
eval(test.toString())

test를 toString()으로 하여 문자열로 강제로 치환한후에 하는 편이 안전합니다.

또한 그것보다 안전한 건 "2 + 2"가 들어오면 문자열을 파싱한후 해당 연산자에 맞춰 계산해주는 별도의 로직을 돌려서 처리하는게 가장 좋습니다.

하지만 코딩테스트에서는 스피드 중요하기 때문에 일단 eval로 간단히 처리했습니다.

댓글