Сначала преобразуйте строку в набор уникальных символов и чисел вхождения, например, BANANA -> (3, A), (1, B), (2, N). (Это можно сделать, отсортировав строку и сгруппировав буквы). Затем для каждой буквы в наборе добавьте эту букву ко всем перестановкам множества на одну единицу меньше этой буквы (обратите внимание на рекурсию). Продолжая пример «BANANA», мы имеем: перестановки ((3, A), (1, B), (2, N)) = A: (перестановки ((2, A), (1, B), (2) , N)) ++ B: (перестановки ((3, A), (2, N)) ++ N: (перестановки ((3, A), (1, B), (1, N))
Вот рабочая реализация на Haskell:
circularPermutations::[a]->[[a]]
circularPermutations xs = helper [] xs []
where helper acc [] _ = acc
helper acc (x:xs) ys =
helper (((x:xs) ++ ys):acc) xs (ys ++ [x])
nrPermutations::[(Int, a)]->[[a]]
nrPermutations x | length x == 1 = [take (fst (head x)) (repeat (snd (head x)))]
nrPermutations xs = concat (map helper (circularPermutations xs))
where helper ((1,x):xs) = map ((:) x)(nrPermutations xs)
helper ((n,x):xs) = map ((:) x)(nrPermutations ((n - 1, x):xs))