1
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.

2
  • Looks like EdX or Coursera exercise. My hint would be to flatten it to some extent. Commented Oct 23, 2013 at 6:48
  • EdX it is, i've been stuck on this for a while i took a course based on recursion and the language allowed .first .rest which helped a lot but i dont know how to do this. Its a specification that it uses recursion Commented Oct 23, 2013 at 7:00

1 Answer 1

2

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
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for helping me to understand the recursive functionality here I was really struggling on this
How long did it take you to come up with this algorithm?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.