条件:
a + b + c = 100
a,b,c positive integers or 0
期望的输出:
[
[0,0,100],
[0,1,99 ],
... # all other permutations
[99,1,0 ],
[100,0,0]
]
条件:
a + b + c = 100
a,b,c positive integers or 0
期望的输出:
[
[0,0,100],
[0,1,99 ],
... # all other permutations
[99,1,0 ],
[100,0,0]
]
我会写:
(0..100).flat_map { |x| (0..100-x).map { |y| [x, y, 100-x-y] } }
#=> [[0, 0, 100], [0, 1, 99]], ..., [99, 1, 0], [100, 0, 0]]
站点注释 1:这是一个经典示例,列表理解大放异彩(如果某处有条件,则更是如此)。由于 Ruby 没有 LC,我们必须对 OOP 进行典型的转换:N-1 flat_map
的 + 1 map
。在 Ruby 中拥有 LC 会很棒(检查此功能请求),Scala 已经证明,即使是纯 OOP 语言也能从这种语法糖中受益匪浅(尽管由于隐式的可迭代协议/方法,我可以理解开发人员的预防措施)。在一个支持它们的想象中的 Ruby 上,你会写:
[[x, y, 100-x-y] for x in 0..100 for y in 0..100-x] # imaginary Ruby
旁注 2:假设您更喜欢内存消耗较少的解决方案(您可能不需要整个数组)。Ruby 2.0 的惰性解决方案只需要添加几个[lazy][2]
代理:
(0..100).lazy.flat_map { |x| (0..100-x).lazy.map { |y| [x, y, 100-x-y] } }
旁注3:为了完整起见,在@akuhn answer的行中,另一个使用枚举器的惰性解决方案:
Enumerator.new do |e|
(0..100).each { |x| (0..100-x).each { |y| e.yield([x, y, 100-x-y]) } }
end
这是我的解决方案
for a in 0..100; for b in 0..100-a; p [a,b,100-a-b]; end; end
我发现这读起来几乎像@tokland 的列表理解。如果您想在下游使用这些值而不是打印它们,请将代码放在生成器方法中
def generate
return enum_for(:generate) unless block_given?
for a in 0..100
for b in 0..100-a
yield [a,b,100-a-b]
end
end
end
然后将其用作
generate { |a,b,c| puts [a,b,c] }
或如
generate { |each| p each }
或如
p generate.to_a
全部打印所有生成的元组。
我想说最像 Ruby 的方式(这绝不是最有效的方式)是这样的:
(0..100).to_a.repeated_permutation(3).find_all{|triplet|triplet.inject(:+)==100}
该链中唯一不透明的部分是to_a
,它将 (0..100) 给出的范围对象转换为数组(范围是惰性的,不适用于repeated_permutation
)。