6

条件:

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]
]
4

3 回答 3

13

我会写:

(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
于 2012-12-06T22:54:02.647 回答
4

这是我的解决方案

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

全部打印所有生成的元组。

于 2012-12-07T01:30:30.753 回答
3

我想说最像 Ruby 的方式(这绝不是最有效的方式)是这样的:

(0..100).to_a.repeated_permutation(3).find_all{|triplet|triplet.inject(:+)==100}

该链中唯一不透明的部分是to_a,它将 (0..100) 给出的范围对象转换为数组(范围是惰性的,不适用于repeated_permutation)。

于 2012-12-07T22:37:39.557 回答