生成一个 6 元素列表的所有组合并对每个组合应用一个函数
Generate all combinations of a 6 element list and apply a function to each combination
我想生成一个 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 个元素列表。
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)]
据我所知,您想要 6 个列表的笛卡尔积(此处用 × 表示)[0..20]
。
所以基本上是这样的:
[0..20]×[0..20]×[0..20]×[0..20]×[0..20]×[0..20]
那是 lot 个元素(准确地说是 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
from Control.Monad
(定义为 sequence
of n
monadic actions: replicateM n x = sequence (replicate n x)
)在应用于列表时基本上做同样的事情(参见例如Why does application of `sequence` on List of Lists lead to computation of its Cartesian Product? 为什么会这样)所以更短的答案是这样的:
replicateM 6 [0..20]
你可以在这之后映射,例如
map (\x -> (x, magicFunction x)) $ replicateM 6 [0..20]
我想生成一个 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 个元素列表。
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)]
据我所知,您想要 6 个列表的笛卡尔积(此处用 × 表示)[0..20]
。
所以基本上是这样的:
[0..20]×[0..20]×[0..20]×[0..20]×[0..20]×[0..20]
那是 lot 个元素(准确地说是 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
from Control.Monad
(定义为 sequence
of n
monadic actions: replicateM n x = sequence (replicate n x)
)在应用于列表时基本上做同样的事情(参见例如Why does application of `sequence` on List of Lists lead to computation of its Cartesian Product? 为什么会这样)所以更短的答案是这样的:
replicateM 6 [0..20]
你可以在这之后映射,例如
map (\x -> (x, magicFunction x)) $ replicateM 6 [0..20]