[Algorithm] 가위 바위 보 (중복 순열)

Yalstrax·2021년 7월 25일
2

Algorithm

목록 보기
5/17
post-thumbnail
post-custom-banner

가위 바위 보 rockPaperScissors (중복순열)

문제

가위바위보 게임은 2인 이상의 사람이 동시에 '가위, 바위, 보'를 외치고 동시에 가위, 바위 또는 보 중에서 한 가지를 의미하는 손 모양을 내밀어 승부를 결정짓는 게임입니다.

세 판의 가위바위보 게임을 할 경우, 한 사람은 세 번의 선택(예. 가위, 바위, 보)을 할 수 있습니다. 세 번의 선택으로 가능한 모든 경우의 수를 구하는 함수를 작성합니다.

입력

  • 없음

출력

  • 2차원 배열(arr[i])을 리턴해야 합니다.

  • arr[i]는 전체 경우의 수 중 한 가지 경우(총 세 번의 선택)를 의미하는 배열입니다.

  • arr[i]는 'rock', 'paper', 'scissors' 중 한 가지 이상을 요소로 갖는 배열입니다.

  • arr[i].length는 3

주의사항

  • 최종적으로 리턴되는 배열의 순서는 가중치 적용 정렬(Weighted Sort)을 따릅니다.

  • 중요도는 'rock', 'paper', 'scissors' 순으로 높습니다.

  • 쉽게 생각해 올림픽 순위 결정 방식을 참고하면 됩니다.
    금메달('rock')이 은메달('paper')보다 우선하고, 은메달('paper')이 동메달('scissors')보다 우선합니다.

입출력 예시

Advanced

  • 가위바위보 게임의 수를 나타내는 양의 정수 rounds가 주어질 경우, 해당 rounds 동안 선택할 수 있는 모든 경우의 수를 리턴하도록 함수를 작성해 보세요.

나의 코드

가위 바위 보는 매 판당 낼 수 있는 경우의 수가 3개입니다. 여러 판이 진행될 경우, 중복된 패를 낼 수 있습니다. 그렇기 때문에 중복 순열입니다.

순열, 조합은 어느정도 틀이 잡힌 탬플릿에서 일정 부분만 바꾸면 무리없이 작동됩니다.

결과

소스코드

function rockPaperScissors(rounds) {
  const rps = ["rock", "paper", "scissors"];
  // 가위 바위 보를 담은 배열을 생성합니다.
  // 배열의 모든 요소의 경우의 수를 훑기 위해
  // 재귀함수를 작성합니다.
  let recur = (rps, selectNum) => {
    let output = [];
    // 재귀 탈출은 인자로 들어온 판수만큼 재귀를 수행했을 때가 됩니다.
    // 주어진 판수를 모두 수행했을 때,
    // 인자로 들어온 배열의 요소에 bracket을 씌워 리턴합니다.
    if (selectNum === 1) return rps.map((hand) => [hand]);
    // 가위바위보 배열의 요소 각각 아래 로직을 수행합니다.
    rps.forEach((hand, idx, rps) => {
      // 현재 요소를 current에 할당합니다.
      const current = hand;
      // 배열의 나머지 요소를 restArr에 할당합니다.
      // 중복순열이므로, 현재 요소를 포함합니다.
      const restArr = rps;
      // 판수를 줄여가며 재귀를 수행합니다.
      // 재귀의 로직은 다음과 같습니다.
      // 처음 실행된 rock을 갖고 판수를 소모합니다.
      // 주어진 판수를 모두 수행하면 output에 push합니다.
      // 한 번의 재귀가 끝났습니다. 마지막 호출 전으로 돌아갑니다.
      // 이제 paper가 current가 됩니다.
      // 마지막 호출 바로 전으로 돌아갔으므로
      // rock, rock, paper가 output에 push됩니다.
      // 이런 식으로 가위바위보 배열의 모든 요소에 재귀를 수행하며
      // output에 경우의 수가 담기게 됩니다.
      const permArr = recur(restArr, selectNum - 1);
      // 재귀의 결과를 이전 값과 합칩니다.
      const combineFix = permArr.map((el) => [current, ...el]);
      output.push(...combineFix);
    });
    return output;
  };
  // 입력인자로 판수가 주어지지 않으면,
  // 기본값인 3판을 수행합니다.
  return recur(rps, rounds || 3);
}

console.log(rockPaperScissors());
console.log(rockPaperScissors(2));
profile
즐겁다면 그것만으로 만만세!
post-custom-banner

0개의 댓글