我很难在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还是很陌生,所以像我在五年级一样向我解释。
任何反馈表示赞赏。
答案 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和其余部分一起发生。一旦计算出剩余部分,就会向其中添加第一个元素。