Rock Paper Scissors

round 0 => []
round 1 => ['r', 'p', 's']
round 2 => ['rr', 'rp', 'rs',
'pr', 'pp', 'ps',
'sr', 'sp', 'ss']
round 3 => ['r +rr', 'r +rp', 'r +rs', 
'r +pr', 'r +pp', 'r +ps',
'r +sr', 'r +sp', 'r +ss',
'p +rr', 'p +rp', 'p +rs',
'p +pr', 'p +pp', 'p +ps',
'p +sr', 'p +sp', 'p +ss',
's +rr', 's +rp', 's +rs',
's +pr', 's +pp', 's +ps',
's +sr', 's +sp', 's +ss']

We can write that as:

if (rounds === 0) {
return [];
} else if (rounds === 1) {
return ['r', 'p', 's'];
} else if (rounds === 2) {
return ['rr', 'rp', 'rs', 'pr', 'pp', 'ps', 'sr', 'sp', 'ss']
}

So that will handle the first 3 cases. Its not very Dry and but its a start

round 0 => []
round 1 => ['r', 'p', 's']
round 2 => ['rr', 'rp', 'rs',
'pr', 'pp', 'ps',
'sr', 'sp', 'ss']
round 3 => ['r +rr', 'r +rp', 'r +rs', 
'r +pr', 'r +pp', 'r +ps',
'r +sr', 'r +sp', 'r +ss',
'p +rr', 'p +rp', 'p +rs',
'p +pr', 'p +pp', 'p +ps',
'p +sr', 'p +sp', 'p +ss',
's +rr', 's +rp', 's +rs',
's +pr', 's +pp', 's +ps',
's +sr', 's +sp', 's +ss']

Looking at the outputs again what will be round 4?

Just add an ‘r’ to every element in the round3 array, then an ‘p’, then an ‘s’.

So this problem just becomes, in an array of an arbitrary number of strings… add an ‘r’, a ‘p’, and an ‘s’ to each of them.

You can break that down even further into a smaller problem of add a string to the beginning of each string in an array

var round1 = ['rock', 'paper', 'scissors'];
var save = [];
round1.forEach(function(item, i, arr) {
save.push('rock' + ' ' + item);
});
// save => ["rock rock", "rock paper", "rock scissors"]
// round1 is left unchanged

So we are trying to reproduce something for three rounds

now we want to try to add on ‘paper’ and ‘scissors

We have the rock part handled now, so we can move on to ‘paper’ and ‘scissors’

var round1 = ['rock', 'paper', 'scissors'];
var save = [];
round1.forEach(function(item, i, arr) {
save.push('rock' + ' ' + item);
});
round1.forEach(function(item, i, arr) {
save.push('paper' + ' ' + item);
});
round1.forEach(function(item, i, arr) {
save.push('scissors' + ' ' + item);
});
// save => ["rock rock", "rock paper", "rock scissors", 
"paper rock", "paper paper", "paper scissors",
"scissors rock", "scissors paper", "scissors scissors"]

Great now that you see pattern, its a great time to try the recursive solution out for yourself.

So what if we wanted to clean this up a bit? It works, it turns a base case round 1 into a round 2. That pattern is repeated any number of rounds. How would repeat the same process for changing round 3 to round 4, round 4 to round 5 and so on and so fourth.

// We can do a little code cleanup 
var choices = ['rock', 'paper', 'scissors'];
var round1 = ['rock', 'paper', 'scissors'];
var save1 = [];
choices.forEach(function(item) {
round1.forEach(function(r1) {
save.push(item + ' '+ r1)
});
});
// save1 => ["rock rock", "rock paper", "rock scissors", 
"paper rock", "paper paper", "paper scissors",
"scissors rock", "scissors paper", "scissors scissors"]

Same output as before, just refactored so we dont repeat ourselves. Although Choices looks the same, they represent different things. Let me demonstrate with moving on to round 2.

// for the sake of space I'm using the initials 
var choices = ['r', 'p', 's'];
var round2 = ["r r", "r p", "r s",
"p r", "p p", "p s",
"s r", "s p", "s s"]
var save2 = [];
choices.forEach(function(item) {
round2.forEach(function(r2) {
save.push(item + ' '+ r2)
});
});
// save2 => ["r r r", "r r p", "r r s", 
"r p r", "r p p", "r p s",
"r s r", "r s p", "r s s",
"p r r", "p r p", "p r s",
"p p r", "p p p", "p p s",
"p s r", "p s p", "p s s",
"s r r", "s r p", "s r s",
"s p r", "s p p", "s p s",
"s s r", "s s p", "s s s"]

So lets try to implement this into a function

var rockPaperScissors = function(rounds) {
if (rounds === 0) {
return [];
} else if (rounds === 1) {
return ['rock', 'paper', 'scissors'];
} else {
// just try to solve for 2 rounds here
}
}
var rockPaperScissors = function(rounds) {
// adding in our choices and save that we had earlier
var choices = ['rock', 'paper', 'scissors'];
var save = [];
if (rounds === 0) {
return [];
} else if (rounds === 1) {
return ['rock', 'paper', 'scissors'];
} else {
// fill me in
}
}
var rockPaperScissors = function(rounds) {
var choices = ['rock', 'paper', 'scissors'];
var round1 = ['rock', 'paper', 'scissors'];
var save1 = [];
if (rounds === 0) {
return [];
} else if (rounds === 1) {
return round1;
} else {
choices.forEach(function(item) {
round1.forEach(function(r2) {
save1.push(item + ' ' + r2)
});
});
}
return save1;
}

great we took all of our code and put it in a function. it handles cases with Zero, One and Two rounds

rockPaperScissors(0) // => [];
rockPaperScissors(1) // => ["rock", "paper", "scissors"]
rockPaperScissors(2) // =>["rock rock", "rock paper", "rock scissors", "paper rock", "paper paper", "paper scissors", "scissors rock", "scissors paper", "scissors scissors"]
//rockPaperScissors(3) outputs the same thing as 2

So now we have our base cases and our start of our recursive pattern. Now we need to do the actual recursing!

Well we got the hard part over with. Now all we have to do is do a recursive call and let recursion do the rest.

var rockPaperScissors = function(rounds) {
var choices = ['rock', 'paper', 'scissors'];
var round1;
var save1 = [];
if (rounds === 0) {
return [];
} else if (rounds === 1) {
return choices;
} else {
round1 = rockPaperScissors(rounds - 1);
choices.forEach(function(item) {
round1.forEach(function(r2) {
save1.push(item + ' ' + r2)
      });
});
}
return save1;
}