-2

I have a list of a = [5,6,7,9] I want all the possible permutations, with one or more entry fixed.

e.g. If I want to fix third element 7, then in all permutations I want to see 7 in the third place of the list.

The code I wrote works well.

from itertools import permutations

a = [5,6,7,9]

fixed_element_index =  2 # I want to keep 7 at the same location and permutate only [5,6, ,9]

a_moveable = a[:fixed_element_index]+a[fixed_element_index+1:]

perm = permutations(a_moveable)

perm_list = []

for x in perm:
    perm_list.append(list(x))


for y in perm_list:
    y.insert(fixed_element_index,a[fixed_element_index])
print(perm_list)

My main problem is if the list one is long and I want multiple indexes to be fixed then what is the best way to do that.

the output is like this [[5, 6, 7, 9], [5, 9, 7, 6], [6, 5, 7, 9], [6, 9, 7, 5], [9, 5, 7, 6], [9, 6, 7, 5]]

0

2 Answers 2

1

I would propose the following pragmatic approach:

from itertools import permutations
 
def fixed_permutations(values: list, fixed_pos: list[int] | None = None) -> list[list]:
    """
    Produces a list of lists with all possible permutations of the given values,
    except for those at the given fixed positions, which remain at their indices.
    
    :param values: list of values to be permuted
    :param fixed_pos: optional list of positions/indices to remain unpermuted
    :return: list of lists of the resulting permutations
    """
    fixed_pos = [] if fixed_pos is None else fixed_pos
    # Collect the values that are *not* to be kept at a fixed position
    permuted_values = [v for i, v in enumerate(values) if i not in fixed_pos]
    # Calculate all permutations
    all_permutations = [list(p) for p in permutations(permuted_values)]
    # Add fixed positions back in (in-place)
    for current_permutation in all_permutations:
        for fixed_position in fixed_pos:
            current_permutation.insert(fixed_position, values[fixed_position])
    return all_permutations
 
print(fixed_permutations(["a", "b", "c", "d", "e"], fixed_pos=[1, 3]))
# [['a', 'b', 'c', 'd', 'e'], ['a', 'b', 'e', 'd', 'c'], ['c', 'b', 'a', 'd', 'e'],
#  ['c', 'b', 'e', 'd', 'a'], ['e', 'b', 'a', 'd', 'c'], ['e', 'b', 'c', 'd', 'a']]

The basic idea: Put aside the values that are not supposed to be part of the permutation, permute the others (using itertools.permutations()), then reinsert the unpermuted values.

As it is currently written, the proposed fixed_permutations() function consumes all results of itertools.permutations() eagerly. We could adjust that by not creating the all_permutations list but adding the values back into each individual permutation on-the-fly and then yielding the individual results rather than returning all at once. Also, as it is currently implemented, it might not be the most efficient approach, given that we have to add values back in for each individual result of itertools.permutations(). I do not see an easy solution to the latter, other than completely implementing the permutation approach from scratch.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks @simon much appreciated for the help, I will also share my beginner code.
0

Here is my approach much beginner level

def sud_perm(ListForPerm,FixedIndex):
    ListForPermutation = ListForPerm
    Fixed_index = FixedIndex
    
    moveable_list = []
    for i , v in enumerate(ListForPermutation):
        if i in Fixed_index:
            continue
        else:
            moveable_list.append(v)
    
    perm = permutations(moveable_list)
    perm_list = []
    
    for x in perm:
        perm_list.append(list(x))
        
    
    for y in perm_list:
        for z in Fixed_index:
            y.insert(z,ListForPermutation[z])
            
    return perm_list

1 Comment

Regarding your first for loop, I would suggest: rather than writing if i in Fixed_index: continue else: moveable_list.append(v), I would simply write: if i not in Fixed_index: moveable_list.append(v). It is equivalent but shorter. Remember, not every if clause needs an else clause (the continue is implicit in the second version). But that's just "cosmetics", your version is totally fine.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.