Haskell - 选择l n函数

时间:2017-02-28 07:50:53

标签: haskell functional-programming

我必须编写一个函数choose l n,打印所有可能组合的列表,以选择列表n的{​​{1}}个元素。

例如,通话l会返回choose [1,2,3] 2[[1,2], [1,3], [2,3]]

不幸的是我不明白解决方案:

[[2,1], [3,1], [3,2]]

我理解前两个陈述。最后一行对我来说并不清楚。

有人可以解释一下吗?

2 个答案:

答案 0 :(得分:6)

可以通过两种方式从n中选择x:xs个元素:选择x,或者不选择。{/ p>

如果选择了x,我们将从n-1中选择xs个元素。因此,我们递归执行choose xs (n-1),然后在x的顶部添加map (\ys -> x:ys)

如果未选择x,我们将从尾n中选择所有xs元素。因此,我们考虑choose xs n

最后,我们将所有这些选择与++组合在一起。

答案 1 :(得分:4)

该功能在给定组合的列表和元素数量的情况下打印所有可能的组合。最后一行的作用是给定一个非空列表和一个正整数来递归地应用它。

首先,让我们看一下这部分:

(map (\ys -> x:ys) (choose xs (n-1)))

这使用第一个元素作为一种常数'。它首先以递归方式生成其他元素的组合,然后将“常量”设置为“常量”。结果生成的每个列表头部的元素

e.g。如果输入为[1,2,3]并且需要2个元素组合,则将按如下方式评估该函数:

 choose [1,2,3] 2
= choose (1:[2,3]) 2
= (map (\ys -> 1:ys) (choose [2,3] 1)) ++ (choose [2,3] 2)

choose (2:[3]) 1
= (map (\ys -> 2:ys) (choose [3] 0)) ++ (choose [3] 1)

= [[2]] ++ [[3]]
= [[2],[3]]

由于

choose 3:[] 1
= (map (\ys -> 3:ys) (choose [] 0)) ++ (choose [] 1)
= [[3]]

所以,

 choose (2:[3]) 1
= (map (\ys -> 2:ys) ([[]])) ++ ([[3]])
= [[2],[3]]

因此,

 choose (1:[2,3]) 2
= (map (\ys -> 1:ys) ([[2],[3]])) ++ (choose [2,3] 2)
= [[1,2],[1,3]] ++ (choose [2,3] 2)

上述表达式中的第二部分只是原始定义中的++ (choose xs n)。它所做的只是用原始列表的较小子列表重复上述过程。

继续上面的例子,choose [2,3] 2评估为[[2,3]]

总而言之,你得到的是[[1,2],[1,3],[2,3]],这是你得到的输出。