# n!(nの階乗)を求めるプログラムを1行で書いてみる。 _published: 2007/09/18_ ![alt](http://b.hatena.ne.jp/entry/image/http://d.hatena.ne.jp/shunsuk/20070918/1190106920) 「[数検(数学検定)の完全対策 1~3級](http://d.hatena.ne.jp/asin/4534022964/helloworld0f-22)」の準1級2次の問題です。 > 0以上の整数nの値を入力させ、n !を計算するプログラムをつくりなさい。 というわけで、Rubyで書いてみました。まずは、普通に。 ```ruby n = gets.to_i k = 1 n.times do |i| k *= i.next end puts k ``` Ruby初心者なので、書き方がスマートでないかもしれません。 `times` にたどり着くのすら、時間がかかってしまいました。でも、アルゴリズムは正しいですよね。(数値以外を入力されたときのエラー処理は考えなくてもいいようです。) で、これを1行で書けるのではないかと思い、チャレンジしてみました。ちょっと、考えてみてください。 ```ruby k = 1 gets.to_i.times { |i| k *= i.next } puts k ``` ここまでは、楽勝ですよね。次は、表示のところを工夫して。 ```ruby 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」を読んでいたのですが(日本語版だと内容がカットされているので英語版)、「block」の部分を読んでいて思いつきました。ブロックを使えば、いけるのでは? ```ruby 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初心者なので、もっとスマートな書き方がありそうな気がします。どうでしょうか?