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 's+ 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の回答の行で、列挙子を使用した別の怠惰な解決策:

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 に答える