There is no combinatorics
module in the standard distribution, but this is easy to do regardless. For example,
def guess(smudged_numbers):
from itertools import product
num_smudges = len(smudged_numbers)
for raw in product(smudged_numbers, repeat=4):
if len(set(raw)) == num_smudges:
yield raw
count = 0
for nums in guess([1, 8]):
print nums
count += 1
print "total", count
That prints:
(1, 1, 1, 8)
(1, 1, 8, 1)
(1, 1, 8, 8)
(1, 8, 1, 1)
(1, 8, 1, 8)
(1, 8, 8, 1)
(1, 8, 8, 8)
(8, 1, 1, 1)
(8, 1, 1, 8)
(8, 1, 8, 1)
(8, 1, 8, 8)
(8, 8, 1, 1)
(8, 8, 1, 8)
(8, 8, 8, 1)
total 14
The search space is very small (len(num_smudges)**4
, which as at most 4**4 = 256), so no point to doing anything fancier ;-)
How it works: it generates all possible (product
) 4-tuples (repeat=4
) containing the passed-in sequence of smudged numbers. So for [1, 8]
, it generates all 2**4 = len(smudged_numbers)**4
= 16 possibilities for a 4-tuple containing nothing but 1's and 8's.
Converting a raw possibility to a set
then tells us how many (len
) different numbers appear in the raw 4-tuple. We only want those containing all the smudged numbers. That's all there is to it. In the [1, 8]
case, this step only weeds out 2 of the 16 raw 4-tuples: (1, 1, 1, 1)
and (8, 8, 8, 8)
.