가위바위보 게임은 2인 이상의 사람이 동시에 '가위, 바위, 보'를 외치고 동시에 가위, 바위 또는 보 중에서 한 가지를 의미하는 손 모양을 내밀어 승부를 결정짓는 게임입니다.
세 판의 가위바위보 게임을 할 경우, 한 사람은 세 번의 선택(예. 가위, 바위, 보)을 할 수 있습니다. 세 번의 선택으로 가능한 모든 경우의 수를 구하는 함수를 작성합니다.
2차원 배열(arr[i])을 리턴해야 합니다.
arr[i]는 전체 경우의 수 중 한 가지 경우(총 세 번의 선택)를 의미하는 배열입니다.
arr[i]는 'rock', 'paper', 'scissors' 중 한 가지 이상을 요소로 갖는 배열입니다.
arr[i].length는 3
최종적으로 리턴되는 배열의 순서는 가중치 적용 정렬(Weighted Sort)을 따릅니다.
중요도는 'rock', 'paper', 'scissors' 순으로 높습니다.
쉽게 생각해 올림픽 순위 결정 방식을 참고하면 됩니다.
금메달('rock')이 은메달('paper')보다 우선하고, 은메달('paper')이 동메달('scissors')보다 우선합니다.
가위 바위 보는 매 판당 낼 수 있는 경우의 수가 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));