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

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.


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
  • \$\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 like set(str(10525)) == set(str(10525 * 2)). \$\endgroup\$ – Gareth Rees Jun 2 '15 at 9:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy