✏️

rockPaperScissors

Question

가위바위보 게임은 2인 이상의 사람이 동시에 '가위, 바위, 보'를 외치고 동시에 가위, 바위 또는 보 중에서 한 가지를 의미하는 손 모양을 내밀어 승부를 결정짓는 게임입니다. 세 판의 가위바위보 게임을 할 경우, 한 사람은 세 번의 선택(예. 가위, 가위, 보)을 할 수 있습니다. 세 번의 선택으로 가능한 모든 경우의 수를 구하는 함수를 작성합니다.

입력

없음

출력

2차원 배열(arr[i])을 리턴해야 합니다.
arr[i]는 전체 경우의 수 중 한 가지 경우(총 세 번의 선택)를 의미하는 배열입니다.
arr[i]'rock', 'paper', 'scissors' 중 한 가지 이상을 요소로 갖는 배열입니다.
arr[i].length는 3

주의사항

최종적으로 리턴되는 배열의 순서는 가중치 적용 정렬(Weighted Sort)을 따릅니다.
중요도는 'rock', 'paper', 'scissors' 순으로 높습니다.
쉽게 생각해 올림픽 순위 결정 방식을 참고하면 됩니다.
금메달('rock')이 은메달('paper')보다 우선하고, 은메달('paper')이 동메달('scissors')보다 우선합니다.

Test Case 1

let output = rockPaperScissors(); console.log(output); /* [ ["rock", "rock", "rock"], ["rock", "rock", "paper"], ["rock", "rock", "scissors"], ["rock", "paper", "rock"], // ...etc ... ] */
Shell
복사

Test Case 2

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 ... ] */
Shell
복사

Solve

const rockPaperScissors = function (rounds) { // rounds 매개변수를 임의로 넣습니다. // rounds 변수가 있을 경우 그대로 사용하고, 없다면 3(기본)을 사용합니다. rounds = rounds || 3; const rps = ['rock', 'paper', 'scissors']; // 결과를 담을 배열 선언 const outcomes = []; // 재귀를 사용할 함수 선언 // rounds를 넣을 변수 roundsToGo, 일회용 배열인 playedSoFar 변수를 선언합니다. // 재귀를 사용하는 이유는, 배열의 모든 요소의 경우의 수를 훑기 위한 적절한 방법이기 때문입니다. // 간단히 말하자면, 이 함수는 rounds 숫자를 기준으로, 일회용 배열에 rps 요소를 rounds 숫자만큼 넣게 됩니다. // 이 로직을 잘 이해할 수 있을 때까지 하단의 함수 로직을 연구해야 합니다. let permutate = function (roundsToGo, playedSoFar) { // rounds가 0일 경우 outcones 배열에 삽입하고, 재귀에서 빠져나옵니다. if (roundsToGo === 0) { outcomes.push(playedSoFar); return; } // rps 배열을 한 번씩 순회합니다. for (let i = 0; i < rps.length; i++) { // rps의 i번째 요소를 변수에 담아서 let currentPlay = rps[i]; // permutate(본인)에 기존 rounds에서 하나 뺀 숫자와, 일회용 배열 playedSoFar에 currentPlay를 삽입하여 재귀를 실행합니다. // rounds에서 하나를 빼는 이유는, 일회용 배열의 크기를 rounds만큼 맞춰주기 위함입니다. [rock, rock, rock] // Q. playedSoFar.push(currentPlay)로 할 수 있을 텐데, 왜 concat을 사용할까요? permutate(roundsToGo - 1, playedSoFar.concat(currentPlay)); /** * 이 재귀의 로직은 이렇습니다. 처음 실행된 반복문은 rps를 전부 순회해야 끝이 납니다. * 그러나 한 번 반복할 때마다 permutate 함수가 실행되고, rounds의 숫자는 짧아지며, playedSoFar에 요소가 계속 쌓일 것입니다. * 결국, roundsToGo가 0이 될 때까지 이 반복문은 rps[i]가 0일 것이며, playedSoFar에는 [rock, rock, rock]이 되어 outcones에 Push하고, 종료하게 됩니다. * return이 되었으니, 한 번의 재귀 호출이 끝났습니다. 마지막 호출 바로 전으로 돌아가, * for문은 i = 1을 가리키게 될 것이고, [rock, rock, paper]을 삽입한 뒤 호출을 하게 됩니다. * roundsToGo가 0이 되어, 해당 배열은 outcomes 배열에 삽입됩니다. * 이런 식으로 모든 호출의 반복문이 끝날 때까지 반복하며 outcomes에 경우의 수 요소들이 담기게 됩니다. */ } }; // 함수를 실행합니다. permutate(rounds, []); // outcomes를 반환합니다. return outcomes; };
JavaScript
복사
실행시간 : ms
function rockPaperScissors (round = 3) { const input = ['rock', 'paper', 'scissors']; function permutation(input, round) { const result = []; if (round === 1) return input.map((el) => [el]); const pArr = permutation(input, round - 1); for (let i = 0; i < input.length; i++) { const addArr = pArr.map((el) => [input[i], ...el]) result.push(...addArr); } return result; } return permutation(input, round); };
JavaScript
복사