Hatena::ブログ(Diary)

このブログは証明できない。

2007-09-18

[][]n!(nの階乗)を求めるプログラムを1行で書いてみる。

数検(数学検定)の完全対策 1~3級」の準1級2次の問題です。

0以上の整数nの値を入力させ、n !を計算するプログラムをつくりなさい。


というわけで、Rubyで書いてみました。まずは、普通に。

n = gets.to_i
k = 1
n.times do |i|
  k *= i.next
end
puts k

Ruby初心者なので、書き方がスマートでないかもしれません。timesにたどり着くのすら、時間がかかってしまいました。でも、アルゴリズムは正しいですよね。(数値以外を入力されたときのエラー処理は考えなくてもいいようです。)


で、これを1行で書けるのではないかと思い、チャレンジしてみました。ちょっと、考えてみてください。


k = 1
gets.to_i.times { |i| k *= i.next }
puts k

ここまでは、楽勝ですよね。次は、表示のところを工夫して。

k = 1
puts k if gets.to_i.times { |i| k *= i.next }

Rubyのifはnilとfalse以外はすべて真になるのでしたね。そして、timesメソッドはself(ここではgets.to_iの値)を返します。ですから、必ずkが表示されることになります。


ここまではOK。問題は、「k = 1」の部分です。ここでハマりました。timesに渡したブロックのスコープ外でkを1で初期化しなければなりません。C言語系なら「;(セミコロン)」で区切れば、どんな処理でも1行で書けます。でも、それでは面白くありません。

そんな時、「Ruby Cookbook (Cookbooks (O'Reilly))」を読んでいたのですが(日本語版だと内容がカットされているので英語版)、「block」の部分を読んでいて思いつきました。ブロックを使えば、いけるのでは?

lambda { |k| puts k if gets.to_i.times { |i| k *= i.next }}.call(1)

lambdaで匿名メソッド(Rubyでもこう呼ぶんですか?)を定義して、いきなりcallします。kを引数にして、1を入れればOKです。無事に動きました。「n!(nの階乗)を求めるプログラムを1行で書いてみる」プロジェクト、達成!


なにしろ、Ruby初心者なので、もっとスマートな書き方がありそうな気がします。どうでしょうか?


数検(数学検定)の完全対策 1~3級

数検(数学検定)の完全対策 1~3級

Ruby Cookbook (Cookbooks (O'Reilly))

Ruby Cookbook (Cookbooks (O'Reilly))

nokturnalmortumnokturnalmortum 2007/10/06 18:55 トラックバック何個もやってしまいました。
ごめんなさい。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証