Finding 10-unique-digit number with i-first-digits divisible by i
Style (and related tools)

A few things are wrong concerning the style (mostly matter of whitespace). Python has a coding guideline called PEP 8. You can use pep8 (or its online version) to check it automatically and autopep8 to try to fix this automatically. You'll find various other convenient tools to check your code such as pylint, pyflakes or pychecker.

Making things more concise

You can use string.digits to have all digits.

Also, you are using more variables that you actually need.

Finally, you don't need to precise 0 in your string slicing and all your permutations will have 10 characters so you don't have to try to take the fist 10 :

Your code becomes :

# join the permutation lists into single numbers by joining each into a string
nums = [''.join(item) for item in itertools.permutations(string.digits)]

for i in range(10, 1, -1):
    nums = [x for x in nums if int(x[:i]) % i == 0]
    print "%-10d # of result can be divided by %d" % (len(nums), i)

print nums


Solution - algorithm, math, etc

Your solution looks interesting in that sense that you iterate through less and less numbers (also, starting from 10 to remove many solutions from the very beginning is a nice touch). However, the issue is that you have to check all iterations at the very beginning and this is quite costly. Also, you keep a list of them in memory.

Let's try to do things differently.

For a start, we know that the number has to be divisible by 10. Therefore, we know that the 0 will be in last position.

&gt;&gt;&gt; print(len(list(itertools.permutations(['1','2','3','4','5','6','7','8','9','0']))))
3628800
&gt;&gt;&gt; print(len(list(itertools.permutations(['1','2','3','4','5','6','7','8','9']))))
362880


Your first iteration should be 10 times faster and your code is indeed roughly 10 times faster.

# join the permutation lists into single numbers by joining each into a string
nums = [''.join(item) for item in itertools.permutations(['1','2','3','4','5','6','7','8','9'])]

for i in range(9, 1, -1):
    nums = [x for x in nums if int(x[:i]) % i == 0]
    print "%-10d # of result can be divided by %d" % (len(nums), i)

print [n + '0' for n in nums]


Simimarly, the divisibility by 9 does not need to be checked because of the following rule (and the fact that the sum of the first 10 numbers is divisible by 9) : remove that check and you have yet another performance gain.

However, for an actual gain, you could go the other wat round : trying to build number by looking at the different candidates of length 1, 2, and so on.

Here is how I did it and it seems to be really fast :

cand = {0}
for i in range(1, 10):
    cand = { n for n in (10 * c + d for c in cand for d in range(1, 10) if str(d) not in str(c)) if n % i == 0}
print [n * 10 for n in cand]


Also, if you were to do things manually, after notificing that 0 has to be in 10th position so that the number is divisible by 10, you can notice that it leaves only 5 to be in 5th position so that the number is divisible by 5. You have 2, 4, 6, 8 left for 2, 4, 6 and 8th position and 1, 3, 7, 9 for 1, 3, 7 and 9th position. You can do this programmatically for yet another performance optimisation.

cand = {0}
for i in range(1, 10+1):
    r = [0] if i == 10 else \
        [5] if i == 5 else \
        [1, 3, 7, 9] if i % 2 else \
        [2, 4, 6, 8]
    cand = { n for n in (10 * c + d for c in cand for d in r if (str(d) not in str(c))) if n % i == 0}
    print(i, len(cand), cand)
print cand