Haskell 99问题#27

时间:2018-12-29 02:46:34

标签: haskell recursion functional-programming

我很难在Haskell的99个问题https://wiki.haskell.org/99_questions/Solutions/27中将问题27的给定答案概念化。

问题: ” 将集合中的元素分组为不相交的子集。

a)一个9人小组可以在2个,3个和4个小组的3个不相交的小组中以几种方式工作?编写一个函数,生成所有可能性并将其返回到列表中。

示例:

* (group3 '(aldo beat carla david evi flip gary hugo ida))
( ( (ALDO BEAT) (CARLA DAVID EVI) (FLIP GARY HUGO IDA) )
... )

b)以可以指定组大小的列表的方式来概括上述谓词,该谓词将返回一个组列表。 “

他们给出的答案是这样的:

combination :: Int -> [a] -> [([a],[a])]
combination 0 xs     = [([],xs)]
combination n []     = []
combination n (x:xs) = ts ++ ds
  where
    ts = [ (x:ys,zs) | (ys,zs) <- combination (n-1) xs ]
    ds = [ (ys,x:zs) | (ys,zs) <- combination  n    xs ]


group :: [Int] -> [a] -> [[[a]]]
group [] _ = [[]]
group (n:ns) xs =
    [ g:gs | (g,rs) <- combination n xs
           ,  gs    <- group ns rs ]

我很难理解第一部分(定义函数“组合”的部分)的工作方式。 我也对Haskell还是很陌生,所以像我在五年级一样向我解释。

任何反馈表示赞赏。

2 个答案:

答案 0 :(得分:1)

combination 0 xs     = [([],xs)]

如果我们要从xs中选择0个元素,则只有一种方法。没有元素[]被占用,所有元素xs都留在那里。

combination n []     = []

否则,我们要选择n(> 0)个元素。如果我们想从空白列表[]中选择它们,那么就没有办法-不可能。

combination n (x:xs) = ts ++ ds
  where
    ts = [ (x:ys,zs) | (ys,zs) <- combination (n-1) xs ]
    ds = [ (ys,x:zs) | (ys,zs) <- combination  n    xs ]

否则,我们要从非空列表n中选择x:xs(> 0)个元素。有很多方法可以做到这一点,我们将其分为以下两组:

  • 我们决定在所选元素中采用元素x,然后从n-1中选择xs。该操作在ts中完成,该方法考虑了从n-1中选择xs个元素的所有方法,然后将x添加到“选择的”元素{{1}的列表中}。

  • 我们决定从输入列表中删除元素ys,然后从x中选择n。该操作在xs中完成,该方法考虑了从ds中选择n个元素的所有方法,然后将xs添加到“已删除”元素{{1}的列表中}。

然后我们使用x输出所有此类组合。

答案 1 :(得分:0)

功能组合有一个列表和一个数字。考虑到列表仅需分为两部分,它会创建列表的组合。这只是原来的问题,仅用2个数字k和n-k简化了。

它使用ts和ds列表执行此操作。

ts是第一个元素在第一部分中,然后使用剩余列表和k-1进行递归。 ds是第一个元素在第二部分中的位置,递归与k和其余部分一起发生。一旦计算出剩余部分,就会向其中添加第一个元素。