From: "KISHIMOTO, Makoto" Date: 2011-10-10T12:29:53+09:00 Subject: [ruby-list:48457] Re: 1.8.7と1.9.2の挙動の違いについて > で、蛇足の本題?ですが > > > のようにscanとjoinが必要な理由を初心者に説明するのはきついです。 > > これだと、自信を持って「Rubyの方がいいよ」とは言いづらいです。 > > の所です。 > 「期待値 10」と言うことは、これらの例題は > 1234 → 1+2+3+4 =10 > を再帰を使って解く という事を(PHPと比較して?)示す > というのを意図されているのかと拝察します。 > > それって相手の土俵に乗ってる様な気がします。 > たしか ruby は再帰はあまり得意ではなかった(最適化の点で) > とも思いますし。 > 「1234 → 10 を解く」 > にまで戻って、NARUSEさんが示された inject を使うとかするとか、 > それがハイレベルすぎるようだと避けるにしても、 >   PHPのアルゴリズムをrubyに置き換える > のではなく、 >   ruby ならこう(簡単に)書けるよ、 > ということを示されるのが良いのではないでしょうか。 ええと、この件については、別の枝で岩月さんが示されてる通り、 n.to_s[a, b] か n.to_s[c .. d] を使うのが良いように思います。 以上で本題終了で、 以下、蛇足を書いてたらどんどん長くなったのですが、蛇足事項。 組み込みプログラミングとか、Windows版rubyでも(前は?)そんな話があったと 思いますが、スタックが小さい環境ですぐ溢れるとか、この計算の例なら 10**100まで対応できるようにしなければならない、とかでない限り、再帰を 避ける理由はないように思います。Schemeなら正しく書いた再帰は非常に 効率的ですが、それと比べた場合、rubyとPHPは再帰に関してはたぶん 50歩100歩ではないかと思います。(そんなにPHPを知らないので間違ってる かもしれません) 文が長くなっても「期待値」という言葉には、「たくさん試行した として平均してありそうな値」という意味があるので、こういう場合は、 「期待される値」と言ったほうが良いでしょう。 私ならこう書く、という話になりますが、とりあえず下の桁から足すような形に 展開してもいいならこんな感じに、 def calc(prm) if prm < 10 then prm else prm % 10 + calc(prm / 10) end end どうしても上の桁からならこうでしょうか def calc(prm) if prm < 10 then prm else prm.to_s[0, 1].to_i + calc(prm.to_s[1 .. -1].to_i) end end もちろんこんな解もありますが、 prm.to_s.each_char.map {|c| c.to_i }.inject(:+) それからprintfに渡す式をリテラル式以外にするのはやめましょう。 printfの第一引数は、フォーマットを指定する文字列ですから、うっかり % が入っている文字列を渡すと変なことになります。 改行がいらなければprintを、また、わざわざ + "\n" と書くぐらいなら putsを使いましょう。 デバッグとか簡単な確認だけなら p でも。p なら to_s もいらなくなります。 prmという引数名も、パラメータ、かと思いますが、よくありません。 argなら、慣用的によく使われているという理由で使う理由がありますが、 prmはそういうこともないし、「パラメータ」だけではその中身の意味を、 ほとんどあらわしてないからです。 一文字変数はよくない、などと言われますが、数を意味する n 、文字列を 意味する s などは立派に意味があり、このくらいの短いまとまった部分で あれば、むしろ使うほうが良い、と私は考えます。 こんな解も。ちょっとパズルし過ぎかな。 ↓ def calc s calc_ s.each_char.to_a end def calc_ arr if arr.empty? then 0 else n = arr.shift.to_i n + calc_(arr) end end