Problem 34

しばらく時間かかるんだよなぁ.けどこの問題に気合を入れる気合が….

def factorial(n):
    if n < 0:return None
    if n == 0:return 1
    return n*factorial(n-1)

def sumfacto(a):
    return sum([factorial(int(x)) for x in str(a)])

print sum([x for x in xrange(10**5/2) if sumfacto(x) == x]) - 3

フォーラムにワンライナーがあった.

print sum([int(reduce(lambda x, y: int(x) + int(y), [str(reduce(lambda x, y: x * y, range(1, int(i) + 1) + [1])) for i in str(j)])) for j in range(100000) if (j == int(reduce(lambda x, y: int(x) + int(y), [str(reduce(lambda x, y: x * y, range(1, int(i) + 1) + [1])) for i in str(j)])))])-3

無駄に長くしている印象を受けたので短くした.

print sum([j for j in range(5*10**4) if j == sum([(reduce(lambda x, y: x * y, range(1, int(i) + 1) + [1])) for i in str(j)])])-3

reduceってこう使うのかーって思ったけど,python3.0からは無くなっていると聞いた.勿体無いなぁ.reduce無し(import無し)だとYコンビネーターを使えばワンライナー無理やり出来そうだったけどあまりに複雑になるのでやめました.

追記

ワンライナーの方をもう少し綺麗にした.というかジェネレータに置き換えて,
operatorを使ってみた.importは邪道?

import operator as t; print sum(j for j in xrange(5*10**4) if j == sum((reduce(t.mul, xrange(1, int(i) + 1) or [1])) for i in str(j)))-3

実行速度の比較

import timeit

ori = timeit.Timer(stmt = 
"sum([int(reduce(lambda x, y: int(x) + int(y), [str(reduce(lambda x, y: x * y, range(1, int(i) + 1) + [1])) for i in str(j)])) for j in range(100000) if (j == int(reduce(lambda x, y: int(x) + int(y), [str(reduce(lambda x, y: x * y, range(1, int(i) + 1) + [1])) for i in str(j)])))])-3")

change = timeit.Timer(stmt = "sum([j for j in range(5*10**4) if j == sum([(reduce(lambda x, y: x * y, range(1, int(i) + 1) + [1])) for i in str(j)])])-3")

lamb = timeit.Timer(stmt = "sum(j for j in xrange(5*10**4) if j == sum((reduce(lambda x,y:x * y, xrange(1, int(i) + 1) or [1])) for i in str(j)))-3")

final = timeit.Timer(setup = "import operator as t", stmt = "sum(j for j in xrange(5*10**4) if j == sum((reduce(t.mul, xrange(1, int(i) + 1) or [1])) for i in str(j)))-3")

print "orginal",ori.timeit(number = 10)
print "changed",change.timeit(number = 10)
print "lamb",lamb.timeit(number = 10)
print "final",final.timeit(number = 10)

実行結果
orginal 38.4732050896
changed 13.8680729866
lambda 8.99447011948
final 7.6372821331

一番早かったのでよしとする.