한 사람이 세 판의 가위바위보를 한다 할 때, 세 번의 선택을 할 수 있습니다. 세 번의 선택으로 가능한 모든 경우의 수를 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로 넘어가면 조금 복잡해진다. 만약 위와 같은 방식으로 코드를 작성하려면 입력받는 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
을 선언하는 경우둘 다 콘솔창에 실행시켜 본 결과 같은 실행결과를 얻을 수 있었다. 하지만 위의 경우에는 인자를 전달받지 않고 있다고 나오는데 그 이유를 한번 곰곰히 생각해보고 찾아봐야 겠다.