Python って Scheme なの?
プロジェクト・オイラー問題 1 の解答が Scheme で書かれているのを眺めていたら、ふと、これって Python でもまったくおなじように書けるんじゃないか!? と気がついた。
その前にまず、プロジェクト・オイラーとはなにか。以下のサイトを見てもらえばわかるだろう。プログラミングのお題。ぼくも取り組んでいるよ。
本家サイト : https://projecteuler.net/
日本語訳サイト: http://odz.sakura.ne.jp/projecteuler/
プロジェクト・オイラー問題 1。
『10未満の自然数のうち, 3 もしくは 5 の倍数になっているものは 3, 5, 6, 9 の4つがあり, これらの合計は 23 になる. 同じようにして, 1000 未満の 3 か 5 の倍数になっている数字の合計を求めよ.』
で、まずは Scheme だとどう解けるのか。
; in scheme
(display
(reduce + 0
(filter
(lambda (x)
(or (= (remainder x 3) 0) (= (remainder x 5) 0)))
(iota 1000))))
(newline)
いかがだろう。
これを Python で書いてみると以下のようにる。
from functools import reduce
print(
reduce(
lambda a, b: a+b,
filter(
lambda x: x%3==0 or x%5==0,
range(1000))))
print()
Scheme と Python の 2つの構造はまったくおなじ。display → print、reduce → reduce、filter → filter、lambda → lambda、iota → range と対応している。最初の import が必要なのは Guido(Python の発明者)が reduce は醜いと functools のなかに追いやったためとどこかに書いてあったような。
初心者の人向けに少し説明しよう。まずは、Python の lambda に注目。lambda ってなにか? Python では関数は def で作ってから使うが、lambda を使えば、使いたいその場で名前を定めることなく使うことができる。たとえば、def nantoka(x, y): return x*y+2y という関数は lambda x, y: x*y+2y などと書いて関数名は無名のまま使える。
さて、Pythonコードの下から説明してみよう。まずは、お馴染み range で、0 から 999 までの数列を作る。「filter(lambda x: x%3==0 or x%5==0,」によって 0 から 999 の数列にまさにフィルターを掛け、これで 3 または 5 で割り切れる数だけの数列になる。
つぎに「reduce(lambda a, b: a+b,」によってその数列の数すべてを足し併せる。そして結果を print 。Scheme とおなじだね。上の Python のコードはそのまま動いて正しい答えを出力してくれるが、もっと簡単に print(sum(x for x in range(1000) if x%3==0 or x%5==0)) こう書いてもおなじように動く。
ちなみに Ruby だとこんな感じ。
sum=0
1000.times do |i|
if i%3==0 or i%5==0
sum+=i
end
end
puts sum
えっ、こっちがいい? ならば Python だって。
sum=0
for i in range(1000):
if i%3==0 or i%5==0:
sum+=i
print(sum)
さらに、ぼくならいつもこう書くんだ。賛否はあると思うが、とくに単純な1行 if ならこう書いたほうが読みやすいと思う。
sum=0
for i in range(1000):
if i%3==0 or i%5==0: sum+=i
print(sum)
こうやって見てみると、これが素朴で一番わかりやすい。
で、ことはついでに、プロジェクト・オイラー問題 2。
『フィボナッチ数列の項は前の2つの項の和である. 最初の2項を 1, 2 とすれば, 最初の10項は以下の通りである.
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
数列の項の値が400万以下の, 偶数値の項の総和を求めよ.』
ぼくの解答はこう。
折り曲がっているだろうけど、これ 1行。 で、ただしこれ、 機械伯爵さん(http://blog.livedoor.jp/kikwai/)から基本的なアイデアをいただいた。
ちょっと、裏技的過ぎて読みにくいかも知れない。