1

課題は、次の最小の整数を見つけることfooです。

foo % 1..20 == 0

私の現在の試みはブルートフォースです

until foo % 1.upto(20) == 0 do
    foo++
end

これはエラーを出力しますunexpected keyword end。しかし、キーワードを irb に入れないendと、ブロックが閉じられていないため、コードは実行されません。

エラーがどこにあるのかを確認するために空のテストケースを作成しました

until foo % 1.upto(20) == 0 do
end

これにより、新しいエラーがスローされます: enumerator can't be coerced to a fixnum. これは、範囲に対してモジュラスを直接実行できず、範囲全体に対してきちんとしたブール値の結果を期待できないことを意味すると思います。しかし、私はここからどこへ行くべきかわかりません。

私の最初の試みは、より効率的/エレガント/的を射たものへの試みを支持して、ブルートフォースを先取りし、次のようになりました:

foo = 1
1.upto(20) {|bar| foo *= bar unless foo % i == 0}

間違った答えをした。理由はわかりませんが、理由にも興味があります

foo = 1
20.downto(1) {|bar| foo *= bar unless foo % i == 0}

別の答えを出力します。

編集: for ループを使用していたでしょう (ActionScript でのプログラミングに慣れていません) が、Ruby では期待どおりに動作しません。

4

4 に答える 4

3

最初の解決策は間違っています。これ1.upto(20)は、列挙子、つまり、本質的に値1〜20の反復子であり、それ自体が数値ではないため、モジュロまたは別の数値との比較のための数値として使用できないためです。

ここには本当に2つの「ループ」が必要です。

foo = 1
foo += 1 until (1..20).all? { |i| foo % i == 0 }

最初のループは、untilであり、次に別の種類のループであり、ブロック( )が呼び出された範囲()の各要素に対して真でall?あることを保証します。1行の「後方」構文を使用していることに注意してください(これは、、、、…でも機能します)。上記は次と同等です。{ |i| foo % i == 0 }(1..20)ifunlesswhile

foo = 1
until (1..20).all? { |i| foo % i == 0 } do
  foo += 1
end
# foo => 232792560

また、これは非常に非効率的であり、プロジェクトオイラーはプログラミングよりも少し多くの数学を必要とすることが多く、力ずくのないソリューションはおそらくより多くの数学を必要としますが、はるかに高速です。

于 2012-05-18T02:37:48.937 に答える
2

OPの質問ではないことはわかっていますが、これは次の方法で簡単に達成できます。

puts (1..20).reduce(:lcm)

とても単純なので、このように解決するのはフェアではないように思えますが、それこそが、私が Project Euler の言語として Ruby を選んだ理由です。

この質問も参照してください

于 2013-05-16T18:48:44.037 に答える
2

これを試して:

until 1.upto(20).reject{|i| foo % i == 0 }.empty? do
  foo += 1
end
于 2012-05-18T02:34:08.047 に答える
0

これが私なら、条件をテストする関数を定義します。

def mod_test(num)
  test = (1..20).map {|i| num % i == 0}
  test.all? # all are true
end

次に、さまざまな値を試すためのループ:

foo = 20
until mod_test(foo) do
  foo += 20
end

(スピードアップしてくれたDylanに感謝します。)+= 20

foo % 10 == 0の知識を使用して、とを暗示し、foo % 5 == 0foo % 2 == 0の間の素数に対してのみテストを実行し120おそらくその情報を使用して数値を直接作成する賢い方法があると確信していますが、私のコードは十分に高速に実行されました。

于 2012-05-18T02:41:40.757 に答える