生成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-1flat\u map
's+1map
。在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}