生成3个加起来等于100的正整数的唯一组合的最像Ruby的方法是什么

生成3个加起来等于100的正整数的唯一组合的最像Ruby的方法是什么,ruby,function,combinations,permutation,Ruby,Function,Combinations,Permutation,条件 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] ] Stackoverflow说我的文章没有太多的上下文来解释代码部分。你同意吗?(这是满足其要求的填充文本)我要写: (0..100).flat_map { |x| (0..100-x).map { |y| [x, y

条件

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]
]
Stackoverflow说我的文章没有太多的上下文来解释代码部分。你同意吗?(这是满足其要求的填充文本)

我要写:

(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\u map
's+1
map
。在Ruby中使用LCs是非常棒的(检查),Scala已经证明,即使是纯OOP语言也能从这种语法糖中获益匪浅(尽管我可以理解开发人员的预防措施,因为隐式iterable协议/方法)。在一个支持它们的假想红宝石上,你会写道:

[[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

打印所有生成的元组。

我认为最简单的方法(这并不是最有效的方法)是:


这个链中唯一不透明的部分是
到a
,它将(0..100)给出的range对象转换为数组(range是惰性的,它不适用于
重复排列
)。

这不是一个坏方法,但我只会生成a,b,和c,然后做一个
查找所有组合的
。@andrewgrim你的方法所做的工作大约是tokland的500000倍。@dbenhur是的,但这是Ruby会做的工作,而不是我会做的工作!我的第一个解决方案是:“output=[];(0..100).to|a.each{a | a |(0..100).to|a.each{b |(0..100).to|a.each{c | outputI.我现在正在考虑如何编写一个有效的方法作为参数:-一个指定整数数量的整数(即每个数组的大小[a,b,c…,zzz])-所需的总数(此处为100)。但这可能值得提出另一个问题。感谢您指导我提出Ruby功能请求。有时我也会使用类似Python生成器的方法,尽管它感觉不太实用(FP-sense)。无论如何,不要在枚举中插入
保护(核心Ruby方法做了哪些才能更通用),您还可以决定始终返回枚举数,这对于可能较大的输出是有意义的:
enumerator.new{| yielder |…yielder.yield x}
@tokland to_enum
和枚举器之间有什么区别?只是风格问题,还是有实现上的区别?我想他们都使用光纤进行协程。@tokland问题是关于“Ruby风格”而不是严格意义上的“函数式编程风格”“:)没有区别,但您不会被迫使用枚举器块编写单独的方法。我知道这不是一个FP问题,这只是一个个人评论(意味着我倾向于尽可能支持函数式解决方案).Gotcha//是的,不必编写方法有时会派上用场。记住选择一些答案我喜欢!虽然它看起来最像红宝石(即魔法、简洁和自然语言),但在这种情况下,我会接受@tokland的答案。不过,我愿意争论。毫无疑问,这更容易理解(我不会说更多的Ruby sh,为什么会这样?),如果我知道N总是很小,我可能会选择它。然而,从计算的角度来看,将一个O(N^2)问题转化为一个O(N^3)至少可以说是有点可疑。稍微增加N,你会遇到大麻烦。这很好,但它没有找到所有的组合。它包括
[0,0100]
,但不是
[100,0,0]
,例如。@Adam:说得好;我误读了规范。我将把
重复组合
更改为
重复排列
(0..100).to_a.repeated_permutation(3).find_all{|triplet|triplet.inject(:+)==100}