Search code examples
pythonpython-3.xcombinationspython-itertools

All combinations by changing 3 places


Here's the code

from itertools import combinations, product

string = "abcd012345"

char = "01268abc"

for i, j in combinations(tuple(range(len(string))), 2):
    for char1, char2 in product(char, char):
        print(string[:i] + char1 + string[i+1:j] + char2 + string[j+1:])

We have a string abcd012345 , we change two places in order to get all possible combinations. In this example we use char a set of characters that can be used.

The goal is to change 2 for 3 in order to replace 3 places with replacement and find all possible combinations by changing 3 places.

Will enjoy to learn from your solution, thank you.


Solution

  • 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:])