tourney = [
[
[ ["Armando", "P"], ["Dave", "S"] ],
[ ["Richard", "R"], ["Michael", "S"] ]
],
[
[ ["Allen", "S"], ["Omer", "P"] ],
[ ["David E.", "R"], ["Richard X.", "P"] ]
],
]
这是一场需要通过以下代码解决的锦标赛:
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
现在基本情况是
def self.tournament_winner(tournament)
if tournament.size == 2
self.winner(tournament[0], tournament[1])
else
#WORK HERE
end
end
但是在 else 中如何让第一个数组成为包含“Armando”和“Dave”的数组,检查谁赢了然后继续,它需要在任意大小的数组上使用。 有没有办法通过元素并过滤胜利;即, 在第一个递归实例上它应该返回:
tourney = [
[
["Dave", "S"],
[ ["Richard", "R"], ["Michael", "S"] ]
],
[
[ ["Allen", "S"], ["Omer", "P"] ],
[ ["David E.", "R"], ["Richard X.", "P"] ]
],
]
如果我的措辞不好,我很抱歉。我一直试图解决这个问题一段时间,而且迟到了,我缺乏感觉。
答案 0 :(得分:2)
该基本功能不正确。首先,让我们假设tourney
数组是格式良好的,总是成对的玩家或阵列。你想要做的是如果tournament[0]
是一个简单的玩家定义,那么玩家1是tournament[0]
。但是,如果tournament[0]
是一系列玩家,则玩家1是tournament[0]
的赢家 - 这是您的递归。对玩家2重复相同的逻辑,并返回玩家1与玩家2的获胜者。
现在,问题变成“我如何确定tournament[0]
是否是一个简单的数组?”让我们使用交互式shell(我更喜欢pry
而非默认irb
),使用您的第二个示例执行此操作:
[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
因此,我们可以测试.class
方法来检查它是否是一个数组,从而引导我们找到这个解决方案:
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
请注意,我需要使用tournament[0][0]
来阻止我们过一步递归。实际上,我不喜欢这样,所以让我们以另一种方式尝试,使用上面建议的flatten。如果扁平化阵列与未展开版本的大小相同,我们已到达树的底部:
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
我使用flatten(1)
作为次要优化。现在:
[7] pry(main)> puts "And the winner is #{tournament_winner(tourney)[0]}!"
=> And the winner is Richard!
上述函数的进一步Ruby-fication可能是
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
或者让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