H-99问题:#26无法理解解决方案

时间:2014-07-07 15:49:30

标签: haskell

我正在阅读“了解你是一个Haskell”之后,正在研究H-99的问题。到目前为止,我觉得我对这些概念有了很好的把握,而且我在解决或理解以前的问题方面没有太多麻烦。然而,这个让我感到困惑,我不理解解决方案。

问题是:

生成从列表的N个元素中选择的K个不同对象的组合

从12人中选出一个3人委员会的方式有多少?我们都知道存在C(12,3)= 220种可能性(C(N,K)表示众所周知的二项式系数)。对于纯数学家来说,这个结果可能很棒。但我们希望在列表中真正生成所有可能性。

提供的解决方案:

import Data.List    

combinations :: Int -> [a] -> [[a]]
combinations 0 _  = [ [] ]
combinations n xs = [ y:ys | y:xs' <- tails xs, ys <- combinations (n-1) xs']

对我而言,混淆的主要问题是y变量。根据尾部如何工作,它应该在开始时被分配整个列表,然后该列表将在生成之后预先生成。但是,当函数运行时,它返回的列表列表不会超过传入的n值。有人可以帮我理解它是如何工作的吗?

2 个答案:

答案 0 :(得分:4)

变量y未绑定到整个xs列表。例如,假设xs=[1,2,3]。然后:

y:xs' is matched against [1,2,3]  ==> y=1 , xs'=[2,3]
y:xs' is matched against [2,3]    ==> y=2 , xs'=[3]
y:xs' is matched against [3]      ==> y=3 , xs'=[]
y:xs' is matched against []       ==> pattern match failure

请注意,y是上面的整数,而xs'是整数列表。


Haskell代码可以读取非确定性算法,如下所示。要从n生成xs元素的组合,请获取xs的任何尾部(即,从头开始删除任意数量的元素)。如果尾部是空的,请忽略它。否则,让尾部为y:xs',其中y是尾部的第一个元素,xs'是剩余的(可能是空的)部分。取y并将其添加到我们正在生成的组合中(作为第一个元素)。然后递归地从n-1剩余部分中选择其他xs'个参数,并将其添加到组合中。当n降至零时,我们知道只有一个组合,即空组合[],所以请接受它。

答案 1 :(得分:0)

y未附加到ys。这将涉及(++) :: [a] -> [a] -> [a]运营商。

如果您尝试追加yys,则类型不匹配。 y的类型为a,而ys的类型为[a]

相反,y使用ys(cons运算符)与(:) :: a -> [a] -> [a]进行了对比。

返回列表的长度等于n,因为combinationsn递归到0,因此它会生成n内部列表。< / p>