JuliaでProject Euler(1)
JuilaというPython対抗っぽい言語があるらしいので試してみる。
PyPyより速いらしい。
Problem 1
https://projecteuler.net/problem=1
まず、Pythonで次のように書く。
import sys
N = int(sys.argv[1])
s = 0
for n in xrange(1, N):
if n%3 == 0 or n%5 == 0:
s += n
print s
これをPython2とPyPyで実行すると、
$ time python2 e001.py 1000000000
233333333166666668
real 1m25.532s
user 1m25.484s
sys 0m0.016s
$ time pypy e001.py 1000000000
233333333166666668
real 0m2.928s
user 0m2.891s
sys 0m0.031s
Juliaに翻訳するとこうなる。
N = parse(Int, ARGS[1])
s = 0
for n in 1:(N-1)
if n%3 == 0 || n%5 == 0
global s += n
end
end
println(s)
まず、parseは文字列を数値に変換する。Intは環境依存で、ここではInt64。
ループや関数にはコロン(:)をつけずに(いつも間違える)、最後にendをつける。
1:N-1はPython2のxrangeみたいなもの。ただし、これで1からN-1まで排出する。
論理演算子のorは||に。こういう記号は排除するのがプログラミング言語の流れだと思っていたのだが。今どきはC++にもand/orが導入されているのに(Microsoftは知らない)。
globalはなくすとs not definedとなってしまう。forの中は別のスコープらしい。globalをつければ、グローバルスコープのsだと解釈されるらしい。
これを実行すると、
$ time julia e001.jl 1000000000
233333333166666668
real 1m41.669s
user 1m41.938s
sys 0m0.313s
Python並みなのだが。
そういえば、Pythonでもglobal変数を参照すると時間がかかるという話があるので、関数化してみた。
import sys
def e001a(N):
s = 0
for n in xrange(1, N):
if n%3 == 0 or n%5 == 0:
s += n
return s
N = int(sys.argv[1])
print e001a(N)
function e001a(N)
s = 0
for n in 1:(N-1)
if n%3 == 0 || n%5 == 0
s += n
end
end
return s
end
N = parse(Int, ARGS[1])
println(e001a(N))
実行すると、
time python2 e001a.py 1000000000
233333333166666668
real 0m53.546s
user 0m53.438s
sys 0m0.031s
time pypy e001a.py 1000000000
233333333166666668
real 0m3.143s
user 0m3.109s
sys 0m0.031s
time julia e001a.jl 1000000000
233333333166666668
real 0m1.642s
user 0m1.797s
sys 0m0.344s
PyPyよりも速くなった。
関数型っぽい書き方もできる。
import sys
def e001(N):
return sum(n for n in xrange(1, N) if n%3 == 0 or n%5 == 0)
N = int(sys.argv[1])
print e001(N)
同様に、
function e001(N)
return sum(n for n in 1:N-1 if n%3 == 0 || n%5 == 0)
end
N = parse(Int, ARGS[1])
println(e001(N))
実行すると、
$ time pypy e001b.py 1000000000
233333333166666668
real 0m8.691s
user 0m8.641s
sys 0m0.047s
time julia e001b.jl 1000000000
233333333166666668
real 0m2.305s
user 0m2.375s
sys 0m0.516s
遅くなる。