Search code examples
pythongeneratorpython-itertoolsswapenumeration

Generate set of all swap from 2 lists


I use pyhton and would like to create something like a set of lists. I explain. As input, I have a list like this :

s = [[0,4,5,6,8],[1,2,3]]

I want to apply random swap on this s between all s[0] and s[1] elements. The problem is that I want to kind of enumerate (not explicitly) all the possible results of this swap. I have try some itertools stuff but didn't success. In other words, the expected output is an iterable containing all possible swap from s. Any advice is welcome !

s = [[0,4,5,6,8],[1,2,3]]

def swap(s):
    i0 = randint(0,len(s[0])-1)
    i1 = randint(0,len(s[1])-1)
    s[0][i0],s[1][i1] = s[1][i1],s[0][i0]

Edit : I think I did not explain well the problem. If we have as input :

s = [[0,4,5,6,8],[1,2,3]]

The ouput would be something like :

S = [[[1,4,5,6,8],[0,2,3]],
     [[0,1,5,6,8],[4,2,3]],
     [[0,4,1,6,8],[5,2,3]],
     [[0,4,5,1,8],[6,2,3]],
     [[0,4,5,6,1],[8,2,3]],
     [[2,4,5,6,8],[1,0,3]],
     ...

For each element e in S, e must be different from s by only one permutation of 2 elements


Solution

  • Not sure if I get your question right, but you can use itertools.combinations for generating all possible swaps.

    from itertools import combinations
    
    listIn = [[0,4,5,6,8],[1,2,3]]
    
    shortList, longList = sorted(listIn, key=len)
    
    result = []
    
    for longPart in combinations(longList,len(longList)-1):
        for shortPart in combinations(shortList,len(shortList)-2):
            longPart = list(longPart)
            shortPart = list(shortPart)
            p1 = longPart + shortPart
    
            p2 = list(set(longList) - set(longPart)) + list(set(shortList) - set(shortPart))
            result.append([p1, p2])
    

    For your example the result list contains all 15 possible single-swaps.

    Here an extract:

    [[0, 4, 5, 6, 1], [8, 2, 3]]
    [[0, 4, 5, 6, 2], [8, 1, 3]]
    [[0, 4, 5, 6, 3], [8, 1, 2]]
    [[0, 4, 5, 8, 1], [6, 2, 3]]
    [[0, 4, 5, 8, 2], [6, 1, 3]]
    [[0, 4, 5, 8, 3], [6, 1, 2]]
    [[0, 4, 6, 8, 1], [5, 2, 3]]
    [[0, 4, 6, 8, 2], [5, 1, 3]]
    [[0, 4, 6, 8, 3], [5, 1, 2]]
    [[0, 5, 6, 8, 1], [4, 2, 3]]
    [[0, 5, 6, 8, 2], [4, 1, 3]]
    [[0, 5, 6, 8, 3], [4, 1, 2]]
    [[4, 5, 6, 8, 1], [0, 2, 3]]
    [[4, 5, 6, 8, 2], [0, 1, 3]]
    [[4, 5, 6, 8, 3], [0, 1, 2]]