Let us first discuss what you are doing right now and then we build a similar solution. As you clarified in a comment, your end goal is to
compute all possible ways you could replace exactly three characters in string
with characters in char
Outer Loop
You do combinations(tuple(range(len(string))), 2)
. So first you make a tuple containing all the values from 0
to len(string)
and then you generate all the possible combinations consisting of two values from that tuple. It's not necessary to use tuple()
here. According to the docs the second parameter of combinations
is how many times it should pick a value for building one single result. Also in the docs we can find the information that combinations
will not reuse values for the resulting tuples.
So we can modify this to
for i, j, k in combinations(range(len(string)), 3)
# generates tuples like this:
# >>> list(combinations(range(4), 3))
# [(0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3)]
Inner Loop
You pick two characters from char
. This time, according to the docs it's equivalent to ((x,y) for x in A for y in B)
. Notice that the docs show that there is a second, optional, parameter:
To compute the product of an iterable with itself, specify the number of repetitions with the optional repeat keyword argument. For example, product(A, repeat=4)
means the same as product(A, A, A, A)
.
So we can use for char1, char2, char3 in product(char, repeat=3)
. As you can see in the following example, this time there are repetitions.
list(product([1,2,3,4], repeat=3))
[(1, 1, 1), (1, 1, 2), (1, 1, 3), (1, 1, 4), (1, 2, 1), (1, 2, 2), (1, 2, 3), (1, 2, 4), (1, 3, 1), (1, 3, 2), (1, 3, 3), (1, 3, 4), (1, 4, 1), (1, 4, 2), (1, 4, 3), (1, 4, 4), (2, 1, 1), (2, 1, 2), (2, 1, 3), (2, 1, 4), (2, 2, 1), (2, 2, 2), (2, 2, 3), (2, 2, 4), (2, 3, 1), (2, 3, 2), (2, 3, 3), (2, 3, 4), (2, 4, 1), (2, 4, 2), (2, 4, 3), (2, 4, 4), (3, 1, 1), (3, 1, 2), (3, 1, 3), (3, 1, 4), (3, 2, 1), (3, 2, 2), (3, 2, 3), (3, 2, 4), (3, 3, 1), (3, 3, 2), (3, 3, 3), (3, 3, 4), (3, 4, 1), (3, 4, 2), (3, 4, 3), (3, 4, 4), (4, 1, 1), (4, 1, 2), (4, 1, 3), (4, 1, 4), (4, 2, 1), (4, 2, 2), (4, 2, 3), (4, 2, 4), (4, 3, 1), (4, 3, 2), (4, 3, 3), (4, 3, 4), (4, 4, 1), (4, 4, 2), (4, 4, 3), (4, 4, 4)]
Loop Content
What you finally do here is printing the string
except for the positions where you want to replace characters. You use the characters from the inner loop and the positions from the outer loop. So effectively, for every two characters (including repetitions) you print a string for every possible way of positioning them (without repetitions, because you can't place them both at the same place).
Since we have now modified the loops to generate three positions and three characters, we only need to add the third modification.
It seems like we're in luck: combinations
only generates the position tuples in ascending order. So we can assume that i < j < k
.
print(string[:i] + char1 + string[i+1:j] + char2 + string[j+1:k] + char3 + string[k+1:])
Putting It All Together
# same as before
from itertools import combinations, product
string = "abcd012345"
char = "01268abc"
# modified as explained above
for i, j, k in combinations(range(len(string)), 3):
for char1, char2, char3 in product(char, repeat=3):
print(string[:i] + char1 + string[i+1:j] + char2 + string[j+1:k] + char3 + string[k+1:])