Consider all lists of length n where the values are integers from the range 0 to n-1. I would like to iterate as quickly as possible over every possible such list that has exactly one duplicate. If n = 2 then the possible lists are:
00
11
If n = 3 they are:
001
002
110
112
220
221
100
200
011
211
022
122
010
020
101
121
202
212
The total number of such lists is n! * (n choose 2) so I would like to avoid storing them all in memory if at all possible.
For each list I want to call a function that calculates a function of the list.
What’s a good way to do this?
Benchmarks On my computer I get the following benchmark results
timeit all(one_duplicate(6))
100 loops, best of 3: 6.87 ms per loops
timeit all(one_duplicate(7))
10 loops, best of 3: 59 ms per loop
timeit all(one_duplicate(8))
1 loops, best of 3: 690 ms per loop
timeit all(one_duplicate(9))
1 loops, best of 3: 7.58 s per loop
and
timeit all(duplicates(range(6)))
10 loops, best of 3: 22.8 ms per loop
timeit all(duplicates(range(7)))
1 loops, best of 3: 416 ms per loop
timeit all(duplicates(range(8)))
1 loops, best of 3: 9.78 s per loop
and
timeit all(all_doublet_tuples(6))
100 loops, best of 3: 6.36 ms per loop
timeit all(all_doublet_tuples(7))
10 loops, best of 3: 60 ms per loop
timeit all(all_doublet_tuples(8))
1 loops, best of 3: 542 ms per loop
timeit all(all_doublet_tuples(9))
1 loops, best of 3: 7.27 s per loop
I declare all_doublet_tuples and one_duplicate to be equal first at the moment (allowing for noise in the tests).
Think of any of the desired output tuples in this way: It was derived by duplicating the first (lets say from the left) doublet elem and inserting it at the position of the second doublet.
Therefore my solution is basically this two-step process:
n-1permutations ofrange(n)take each single element and insert it at each position ahead (to avoid duplicates) including at the very end
I do not print the output here cause its kind of lenghty … and the case for n=3 is boring.