我必须编写一个函数choose l n
,打印所有可能组合的列表,以选择列表n
的{{1}}个元素。
例如,通话l
会返回choose [1,2,3] 2
或[[1,2], [1,3], [2,3]]
不幸的是我不明白解决方案:
[[2,1], [3,1], [3,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]],这是你得到的输出。