Project Euler 52(1)

Problem 52
125874という数とその倍の251748は同じ数字から成っていて違う順序である。
2x,3x,4x,5x,6xがxと同じ数字から成る最も小さいxを見つけよ。
http://projecteuler.net/index.php?section=problems&id=52

同じ数字から成る、は数字にリストにしてソートして再び数にする。この数が一致するかどうかで判定します。


from itertools import islice, ifilter, ifilterfalse, count

def gen_digits(n):
while n:
yield n % 10
n /= 10

def normalize(n):
return reduce(lambda x, y: x * 10 + y, sorted(gen_digits(n)))

# all True?
def all(f, a):
for e in ifilterfalse(f, a):
return False
return True

def is_valid(n):
m = normalize(n)
return all(lambda k: normalize(n * k) == m, xrange(2, 7))

for n in islice(ifilter(is_valid, count(1)), 1):
print n

よく考えると、6倍しても同じ桁数でなければなりません。だから6桁なら106/6より小さくなければなりません。また、6倍して同じ数字から成り立つということは、各桁の和が3の倍数ということになり、元の数も3の倍数ということになります。さらに、頭の桁は元が1なので、2倍、3倍とすると、頭の桁は変わっていくことになります。つまり最低でも6つ以上の異なる数字から成ることになります。ということは6桁以上でなければなりません。


# 残りは上と同じ
def gen_solution():
for m in count(N):
for n in xrange(10 ** (m - 1) + 2, 10 ** m / N, 3):
if is_valid(n):
yield n

N = 6
for n in islice(gen_solution(), 1):
print n

このコードで10番目の解まで求めたところ、どうやらパターンがあるようです。そのパターンが常に解になることは分かったのですが、これ以外に本当に解が無いのでしょうか。