[Algorithm]Toy Problem 01

안정태·2021년 4월 22일
0

Algorithm

목록 보기
1/50
post-thumbnail

문제 : rockPaperScissors

한 사람이 세 판의 가위바위보를 한다 할 때, 세 번의 선택을 할 수 있습니다. 세 번의 선택으로 가능한 모든 경우의 수를 2차원 배열로 나타 내는 함수를 구현하세요.(단, 'rock', 'paper', 'scissors' 순의 중요도를 가지는 '가중치 적용 정렬'을 따릅니다.)

let output = rockPaperScissors();

console.log(output);
/*
    [
      ["rock", "rock", "rock"],
      ["rock", "rock", "paper"],
      ["rock", "rock", "scissors"],
      ["rock", "paper", "rock"],
      // ...etc ...
    ]
  */

Advanced : 가위바위보의 round가 주어 질 때, 해당 round 동안 선택 가능한 경우의 수를 리턴하세요.

let output = rockPaperScissors(5);

console.log(output);
/*
    [
      ["rock", "rock", "rock", "rock", "rock"],
      ["rock", "rock", , "rock", "rock", "paper"],
      ["rock", "rock", , "rock", "rock", "scissors"],
      ["rock", "rock", "rock", "paper", "rock"],
      ["rock", "rock", "rock", "paper", "paper"],
      ["rock", "rock", "rock", "paper", "scissors"],
      ["rock", "rock", "rock", "scissors", "rock"],
      // ...etc ...
    ]
  */

문제의 접근

이 문제는 Advanced를 무시하고 푼다면 쉽게 접근이 가능하다. '가중치 적용 정렬'이 무엇인지 몰라서 구글링을 해본 결과 말 그대로 중요도를 산정해서 먼저 오게 하는 정렬을 뜻한다. 이 부분은 먼저 소스가 될 배열을 위 중요도 순서대로 선언해 준 뒤, 어차피 라운드가 고정되어 있으니 그 횟수 만큼 가능한 경우의 수를 모두 넣어주면 될 것이라 생각했다.

for문을 3번 이용하면 문제가 무난하게 해결 될 것이라 생각했다.

const rockPaperScissors = function () {
  // TODO: 여기에 코드를 작성합니다.
  let rps = ['rock','paper','scissors'];
  let result = [];

  for(let i = 0; i < rps.length; i++){ 
    for(let j = 0; j < rps.length; j++){
      for(let z = 0; z < rps.length; z++){
        let cnt = [rps[i], rps[j], rps[z]]
        result.push(cnt);
      }
    }
  }
  return result;
};

위 코드를 실행시켜 보면 무난하게 한 사람이 3번의 가위바위보를 진행하면서 할 수 있는 모든 선택이 담긴 길이 27개의 배열이 리턴된다.

Advanced

하지만 문제가 Advanced로 넘어가면 조금 복잡해진다. 만약 위와 같은 방식으로 코드를 작성하려면 입력받는 round의 숫자만큼 반복문을 써줘야하기 때문이다. 그렇다면 어떻게 입력받은 숫자만큼 반복문을 실행시킬 수 있을까?를 고민했다.

입력받은 수 만큼 for문을 반복 실행할 수 있는 재귀함수를 만들어야 겠다고 생각했다.

const rockPaperScissors = function (round = 3) {
  // TODO: 여기에 코드를 작성합니다.
  let rps = ['rock','paper','scissors'];
  let result = [];

  function paly(m=[]){
    if(m.length === round){
      result.push(m);
    }// 재귀함수의 탈출조건
    for(let i = 0; i < rps.length; i++){
      m.push(rps[i]);
      play(m);
    }
  }

  paly();

  return result;
};

위 코드는 내가 처음 작성한 코드이다. 당연하게도 테스트는 하나도 통과하지 못하는 코드이다. 하지만 찬찬히 틀린 부분의 오류와 테스트케이스를 확인하며 수정작업에 나섰다. 아래는 그 과정을 나열했다.

  • 재귀함수가 무한호출 된다고 오류가 표시되었다.
    -> 재귀함수 탈출 조건 안에 return을 넣어줬다.
    -> m을 복사해준 뒤에 복사한 값을 재귀함수에 넣어줬다. (해결)

  • 판수를 전달 받지 않고 있다고 표시되었다.
    -> 구글링을 통해서 인자를 어떻게 받게 하는지 찾아보았다.
    -> let round = num || 3을 넣어주고 인자로 num을 주었다. (해결)

const rockPaperScissors = function (num) {
  // TODO: 여기에 코드를 작성합니다.
  let round = num || 3
  let rps = ['rock','paper','scissors'];
  let result = [];

  function paly(m=[]){
    if(m.length === round){
      result.push(m);
      return;
    }// 재귀함수의 탈출조건
    for(let i = 0; i < rps.length; i++){
      let copy = m.slice();
      copy.push(rps[i]);
      paly(copy);
    }
  }

  paly();

  return result;
};

위 코드는 무사히 모든 테스트를 마칠 수 있는 코드였다.

문제를 통해 생각해 볼 것

제일 자신 없는 재귀함수를 이렇게 혼자 힘으로 작성했다는 사실이 너무 기뻣다. 그래도 공부한 보람이 아예 없는 것 같지는 않아서 기쁘다. 이렇게 차근차근 하나씩 해결해 나가다보면 재귀함수도 충분히 자유자재로 활용 할 수 있을 것 같다. 하지만 한가지 풀리지 않는 궁금증이 생겼다.

  • 인자로 round = 3을 주는 경우
  • 인자로 num을 주고 let round = num || 3을 선언하는 경우

둘 다 콘솔창에 실행시켜 본 결과 같은 실행결과를 얻을 수 있었다. 하지만 위의 경우에는 인자를 전달받지 않고 있다고 나오는데 그 이유를 한번 곰곰히 생각해보고 찾아봐야 겠다.

profile
코딩하는 펭귄

0개의 댓글