This is my solution to Project Euler Problem 52 - Permuted Multiples. In the problem I'm searching for the smallest value of x such that x, 2x, 3x, 4x, 5x, and 6x use the same digits.
x = 125874
while True:
x += 1
if sorted(set(str(x))) == sorted(set(str(x * 2))) == \
sorted(set(str(x * 3))) == sorted(set(str(x * 4))) == \
sorted(set(str(x * 5))) == sorted(set(str(x * 6))):
print x
break
Is this bad Python? Is there a better way to write this instead of using a while True
loop? I've tried adding the if condition to the while
loop, but keep getting an infinite loop.
1 Answer 1
Python lacks C-style techniques like side-effect assignments (while (++x) { ... }
) and counting for-loops (for (int x = 125874; ; x++) { ... }
). When you find yourself needing a counting loop in Python, a better formulation is nearly always available using either xrange()
, itertools
, or a generator. In this case, I recommend itertools.count()
.
There's nothing in the problem statement that implies that the answer exceeds 125874. The only logical limit I can see is that the answer needs to have at least six digits. (The problem is probably designed to make you think about the decimal representation of \$\frac{1}{7}\$.)
Furthermore, manually writing all of the tests for 2, 3, 4, 5, and 6 is poor style.
There is no need to transform each set into a sorted list. Skipping that transformation nearly doubles the speed of the code.
from itertools import count
for n in count(100000):
digits = set(str(n))
if all(set(str(mult * n)) == digits for mult in xrange(2, 7)):
print n
break
-
\$\begingroup\$ Can you explain why the answer has to have at least six digits? Also, the
set
test looks dodgy to me: although it happens to get the correct answer for this problem, it risks false positives. Consider something likeset(str(10525)) == set(str(10525 * 2))
. \$\endgroup\$Gareth Rees– Gareth Rees2015年06月02日 09:49:51 +00:00Commented Jun 2, 2015 at 9:49