Комбинации и перестановка Haskell
У меня есть три слова в списке [ "a" , "b", "c" ]. я хочу найти все возможные комбинации в наборе 5,6 и т.д.
например, для набора из 5 я было бы
**[ [aaaaa],[aaaab],[aaaac], [aaabc] , ..... ]** etc 3 ^ 5 = 243 combinations
aaaaaa выше будет в основном "a" , "a" , "a" , "a" , "a" ....
Ответы
Ответ 1
replicateM
делает то, что вы хотите:
> import Control.Monad
> replicateM 5 ["a", "b", "c"]
[["a","a","a","a","a"],["a","a","a","a","b"],["a","a","a","a","c"],["a","a","a","b","a"],["a","a","a","b","b"],["a","a","a","b","c"],["a","a","a","c","a"],["a","a","a","c","b"],["a","a","a","c","c"],["a","a","b","a","a"],["a","a","b","a","b"],["a","a","b","a","c"],["a","a","b","b","a"],["a","a","b","b","b"],["a","a","b","b","c"]...]
Ответ 2
Конечно, ответ на nanothief дает кратчайшее решение, но это может быть поучительно и забавно сделать это самостоятельно.
Существует множество способов написать функцию для декартова произведения. Например. вы можете использовать списки:
prod :: [[a]] -> [[a]] -> [[a]]
prod as bs = [a ++ b | a <- as, b <- bs]
Где (++) :: [a] -> [a] -> [a]
- см. Data.List. Другая возможность - использовать экземпляр Applicative
списка:
import Control.Applicative
prod as bs = (++) <$> as <*> bs
Теперь вам нужно применить эту операцию повторно. Сгиб может сделать это, например:
rep :: Int -> [[a]] -> [[a]]
rep n as = foldr1 prod $ replicate n as
rep 3 ['a','b','c']
--["aaa","aab","aac","aba","abb","abc","aca","acb","acc","baa","bab",
--"bac","bba","bbb","bbc","bca","bcb","bcc","caa","cab","cac","cba",
--"cbb","cbc","cca","ccb","ccc"]
Понимание этого решения может быть более ценным, чем сжатие replicateM
. Тем не менее, вы могли бы найти последнее легко, используя Hoogle.
-
Подробнее о функторах и аппликациях см. определения fmap (<$>
) и ap (<*>
). Функторы, Применения и Monads In Pictures также могут быть хорошим ресурсом.