生成6个元素列表的所有组合,并将函数应用于每个组合

时间:2016-05-13 01:45:20

标签: list haskell combinations

我想生成6个元素列表[x1,x2,x3,x4,x5,x6]的所有可能组合,每个xi是0到20之间的数字。

我想生成此类列表的所有可能组合,应用函数(将列表作为输入并输出神奇的Int)到每个列表,然后将结果输出到元组列表。所以元组列表看起来像

[([x11,x21,x31,x41,x51,x61],Int1), ([x12,x22,x32,x42,x52,x62],Int2), ...]

我亲手试图通过快速意识到组合太多而且实际上不可能手工完成。

组合如[0,0,0,0,0,0],[1,7,0,10,11,6],[7,7,7,7,6,6],[ [20,20,20,20,20,20]等等。

我知道如何生成列表的所有组合并将它们放在列表列表中(因为我之前已经问过这个)

foo [] = [[]]
foo (x:xs) = foo xs ++ map (x:) (foo xs)

这次我想要实现的是不同的,因为我不想在特定列表中生成不同的组合,我正在尝试生成所有6个元素列表。

2 个答案:

答案 0 :(得分:2)

据我所知,你想要一个笛卡尔积(用×表示)6个列表[0..20]

基本上,就像这样:

[0..20]×[0..20]×[0..20]×[0..20]×[0..20]×[0..20]

这是元素的很多(确切地说是85,766,121)。但是,它可以做到。

或许更容易理解的版本如下。

让我们定义一个函数cart,它可以像列表中的笛卡尔积和列表一样:

let cart xs ls = [x:l | x <- xs, l <- ls]

此函数将获取xs中的所有元素以及ls中的所有元素,并构建包含所有可能连接的列表列表。

现在,我们需要一个基本案例。假设您需要一个单个元素列表的列表,而不是六个。您将如何应用我们的cart功能?好吧,因为它将第一个参数中的每个元素添加到第二个参数中的每个元素,我们可以将一个空列表的列表作为第二个参数传递,并将[0..20]作为第一个参数传递:

cart [0..20] [[]]

我们得到了

[[0],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20]]

大。现在我们只将它应用于自己的结果6次,从[[]]开始:

foldr ($) [[]] $ replicate 6 (cart [0..20])

($)是功能应用程序。

来自replicateM的{​​{1}}(定义为Control.Monad sequence monadic操作:n)在应用于列表时基本相同(请参阅例如{{ 3}}为什么正是如此)所以较短的答案是这样的:

replicateM n x = sequence (replicate n x)

您可以在此之后映射,例如

replicateM 6 [0..20]

答案 1 :(得分:1)

foo f xs = map (\ys -> (ys,f ys)) (replicateM (length xs) xs)

此处replicateM (length xs) xs将生成xs中所有元素的组合。然后你只需要映射它。

GHCI的结果:

>import Control.Monad
>let foo f xs = map (\ys -> (ys,f ys)) (replicateM (length xs) xs)
>foo sum [1,2]
[([1,1],2),([1,2],3),([2,1],3),([2,2],4)]