What is the most Ruby-like way to generate each unique combination of 3 positive integers that are up to 100

Conditions

a + b + c = 100 a,b,c positive integers or 0 

Required Conclusion:

 [ [0,0,100], [0,1,99 ], ... # all other permutations [99,1,0 ], [100,0,0] ] 

Stackoverflow says that my post does not have much context for explaining sections of code. Do you agree? (This is the text of the filler to meet its requirements)

+6
source share
3 answers

I would write:

 (0..100).flat_map { |x| (0..100-x).map { |y| [x, y, 100-xy] } } #=> [[0, 0, 100], [0, 1, 99]], ..., [99, 1, 0], [100, 0, 0]] 

Site Note 1: This is a classic example in which the list shines (and even more if there is some condition). Since Ruby does not have LC, we have to do a typical conversion to OOP: N-1 flat_map + 1 map . It would be great to have LC in Ruby (check this feature request ), Scala proved that even a clean OOP language is very beneficial from this syntactic sugar (although I can understand that the prevention from the developers is due to the implicit iterable protocol / method). On an imaginary Ruby that supported them, you should write:

 [[x, y, 100-xy] for x in 0..100 for y in 0..100-x] # imaginary Ruby 

Side Note 2: Imagine you prefer a less time-consuming solution (you probably don't need the whole array). For a lazy solution with Ruby 2.0, you just need to add a couple of proxies [lazy][2] :

 (0..100).lazy.flat_map { |x| (0..100-x).lazy.map { |y| [x, y, 100-xy] } } 

Side Note 3: For completeness only, in @akuhn's answer line, another lazy solution using counters:

 Enumerator.new do |e| (0..100).each { |x| (0..100-x).each { |y| e.yield([x, y, 100-xy]) } } end 
+13
source

Here is my solution

 for a in 0..100; for b in 0..100-a; p [a,b,100-ab]; end; end 

which I find reads almost like understanding @toklands list. If you like to use the values โ€‹โ€‹downstream rather than printing them, put the code in the generator method

 def generate return enum_for(:generate) unless block_given? for a in 0..100 for b in 0..100-a yield [a,b,100-ab] end end end 

which is then used as in

 generate { |a,b,c| puts [a,b,c] } 

or as in

 generate { |each| p each } 

or as in

 p generate.to_a 

which all print all generated tuples.

+4
source

I would say the most Ruby-ish path (which is by no means the most efficient way):

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

The only opaque part of this chain is to_a , which converts the range object specified (0..100) to an array (ranges are lazy, which does not work with repeated_permutation ).

+3
source

All Articles