'Ruby: Accessing array's in arrays
tourney = [
[
[ ["Armando", "P"], ["Dave", "S"] ],
[ ["Richard", "R"], ["Michael", "S"] ]
],
[
[ ["Allen", "S"], ["Omer", "P"] ],
[ ["David E.", "R"], ["Richard X.", "P"] ]
],
]
That is a tournament that needs to be solved by the following code:
def self.winner(player1, player2)
p1c = player1.last.downcase
p2c = player2.last.downcase
unless RPS.include?(p1c) && RPS.include?(p2c)
raise NoSuchStrategyError, "Strategy must be one of R,P,S"
end
if p1c!=p2c
case p1c
when "r"
p2c=="s" ? player1 : player2
when "p"
p2c=="r" ? player1 : player2
when "s"
p2c=="p" ? player1 : player2
end
else
player1
end
end
Now the base case is, of course,
def self.tournament_winner(tournament)
if tournament.size == 2
self.winner(tournament[0], tournament[1])
else
#WORK HERE
end
end
But in the else how can I get the first array set being the array containing "Armando" and "Dave" check who wins then continue, it needs to be used on arbitrary sized arrays. is there a way to go through the elements and filter the wins; i.e., on the first instance of recursion it should return:
tourney = [
[
["Dave", "S"],
[ ["Richard", "R"], ["Michael", "S"] ]
],
[
[ ["Allen", "S"], ["Omer", "P"] ],
[ ["David E.", "R"], ["Richard X.", "P"] ]
],
]
I'm sorry if my wording's bad. I've been trying to solve this for a while and its getting late and I lack sense.
Solution 1:[1]
That base function is not correct. First, let us assume that the tourney array is well-formed with always pairs of either players or arrays. What you want to do is if tournament[0] is a simple player definition then player 1 is tournament[0]. However, if tournament[0] is an array of players, then player 1 is the winner of tournament[0] - this is your recursion. Repeat the same logic for player 2, and return the winner of player 1 versus player 2.
Now, the question becomes "How do I determine if tournament[0] is a simple array or not?" Lets do this the simple way with the interactive shell (I prefer pry over the default irb), using your second example:
[3] pry(main)> tourney.class
=> Array
[4] pry(main)> tourney[0].class
=> Array
[5] pry(main)> tourney[0][0].class
=> Array
[6] pry(main)> tourney[0][0][0].class
=> String
So, we can test the .class method to check if it is an array, leading us to this solution:
def self.tournament_winner(tournament)
if tournament[0][0].class == Array
player1 = self.tournament_winner(tournament[0])
else
player1 = tournament[0]
end
if tournament[1][0].class == Array
player2 = tournament_winner(tournament[1])
else
player2 = tournament[1]
end
self.winner(player1, player2)
end
Note that I need to use tournament[0][0] to stop us recursing one step too deep. Actually, I don't like that, so lets try it another way, using flatten as suggested above. We have reached the bottom of the tree if the flattened array is the same size as the unflattened version:
def self.tournament_winner(tournament)
if tournament[0].flatten(1).size != tournament[0].size
player1 = self.tournament_winner(tournament[0])
else
player1 = tournament[0]
end
if tournament[1].flatten(1).size != tournament[1].size
player2 = tournament_winner(tournament[1])
else
player2 = tournament[1]
end
self.winner(player1, player2)
end
I use flatten(1) as a minor optimisation. Now:
[7] pry(main)> puts "And the winner is #{tournament_winner(tourney)[0]}!"
=> And the winner is Richard!
Further Ruby-fication of the function above might be
def self.tournament_winner(tournament)
player1 = if tournament[0].flatten(1).size != tournament[0].size
self.tournament_winner(tournament[0])
else
tournament[0]
end
player2 = if tournament[1].flatten(1).size != tournament[1].size
tournament_winner(tournament[1])
else
tournament[1]
end
self.winner(player1, player2)
end
Or getting DRYer:
def self.get_competitor(branch)
if branch.flatten(1).size != branch.size
self.tournament_winner(branch)
else
branch
end
end
def self.tournament_winner(tournament)
player1 = self.get_competitor(tournament[0])
player2 = self.get_competitor(tournament[1])
self.winner(player1, player2)
end
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Chris |
