Перемешать все буквы в строке во всех возможных вариацих

Пользователь вводит строку, нужно перемешать буквы в ней во всех возможных вариациях и вывести их в списке, и удалить дубликаты, если они есть, например:

('a');  ['a']

('ab');  ['ab', 'ba']

('aabb');  ['aabb', 'abab', 'abba', 'baab', 'baba', 'bbaa']

я написал такой код, но он работает только при маленькой длине строки, а при большой ответы не совпадают с нужными.

import math
import random
def permutations(string):
    lst=[]
    for i in range(0,math.factorial(len(string))):
        lst.append(''.join(random.sample(string,len(string))))
    asm=set()
    for i in lst:
        asm.add(''.join(i))
    return sorted(asm)

пожалуйста, объясните решение задачи, вопрос взял отсюда: https://www.codewars.com/kata/5254ca2719453dcc0b00027d/train/python


Ответы (1 шт):

Автор решения: MiniMax

Предлагаю два варианта:

1) С помощью модуля itertools.

from itertools import permutations as perm

def permutations(string):
    return list(''.join(tup) for tup in set(perm(string)))

2) Рекурсивный.

def perm(string, accum):
    if len(string) == 0:
        return [accum]  

    res = []
    for i, letter in enumerate(string):
        res += perm(string[:i] + string[i + 1:], accum + letter)

    return res

def permutations(string):
    return list(set(perm(string, '')))

Объяснение

Имеем набор из трёх букв abc. Начинаем собирать все возможные перестановки:

  1. Первой буквой может быть любая из набора, соответственно строка может иметь три разных начала: a, b, c. Выбирая какую-либо букву, мы должны удалить её из набора, так как она уже использована.
  2. Вторую букву выбираем из оставшихся в наборе, в данном случае их две. Добавляем её к уже имеющейся строке (аккумулятору) и удаляем её из набора.
  3. Третья буква автоматом идёт в аккумулятор, так как последняя в наборе.
'a', в наборе остаётся 'bc'.
    'ab' в наборе остаётся 'c'
        'abc', набор пустой
    'ac' в наборе остаётся 'b'
        'acb', набор пустой

'b', в наборе остаётся 'ac'.
    'ba' в наборе остаётся 'c'
        'bac', набор пустой
    'bc' в наборе остаётся 'a'
        'bca', набор пустой     

'c', в наборе остаётся 'ab'.
    'ca' в наборе остаётся 'b'
        'cab', набор пустой
    'cb' в наборе остаётся 'a'
        'cba', набор пустой
  1. Для удаления дубликатов все полученные перестановки прогоняем через set() .
→ Ссылка