给出了列表对::[a,a]
的列表,我想返回列表的可能组合,其中子列表已合并到下一个匹配的头的最后一个匹配头上。
例如 -如果前后匹配则合并两个列表
merge :: Eq a => [[a]] -> [[a]]
merge (x:y:ys) | last x == head y = merge $ (x ++ (drop 1 y)) : ys
| otherwise = []
merge xs = xs
combinations :: Eq a => [[a]] -> [[a]]
combinations = nub . concatMap merge . permutations
λ= merge [1,2] [2,3]
[1,2,3]
-- there should be no duplicate results
λ= combinations [[1,3],[1,3],[1,3],[1,3],[2,1],[2,1],[2,1],[2,2],[3,2],[3,2],[3,2]]
[[1,3,2,2,1,3,2,1,3,2,1,3],[1,3,2,1,3,2,2,1,3,2,1,3],1,3,2,1,3,2,1,3,2,2,1,3]]
-- the result must be a completely merged list or an empty list
λ= combinations [[1,3], [3,1], [2,2]]
[]
λ= combinations [[1,3], [3, 1]]
[[1,3,1],[3,1,3]]
λ= combinations [[1,3],[3,1],[3,1]]
[[3,1,3,1]]
我无法完全绕开有效执行此操作所需的递归。
答案 0 :(得分:1)
我以这个解决方案结束了,但是它包含重复项(您可以使用lena.jpg
删除它们)。
Data.List(nub)
答案 1 :(得分:0)
我不确定我是否完全了解您想做什么,因此这里仅是一些注意事项和提示。
给出了列表对
的列表::[a,a]
(...)例如
λ= merge [1,2] [2,3]
首先,这些不是成对的列表,列表中的每个元素都是整数而不是成对的。它们只是带有两个元素的列表。因此,您可以说它们的类型为[Int]
或实例类型为[a]
。
子列表已合并到下一个子匹配标题的最后一个。
这表明列表的大小将增加,并且您将不断需要检查它们的第一个和最后一个元素。检查列表的最后一个元素意味着每次都要遍历它。您要避免这种情况。
这建议使用带有易于访问的附加信息的列表表示。您只需要最后一个元素,但出于对称性考虑,我将放在最后。
-- lists together with their last element
data CL a = CL [a] a a
cl :: [a] -> CL a
cl [] = error "CL from empty list"
cl xs = CL xs (head xs) (last xs)
clSafe :: [a] -> Maybe (CL a)
clSafe [] = Nothing
clSafe xs = Just (cl xs)
clFirst (CL _ x _) = x
clLast (CL _ _ x) = x
compatible cs ds = clLast cs == clFirst ds
也许更好,也许您应该拥有
data CL a = CL [a] a a | Nil
并包括一个与所有其他列表兼容的空列表。
要考虑的另一点是,例如,如果您有一个列表xs
并想找到列表ys
合并为ys++xs
,那么您希望它非常简单使用给定的最后一个元素访问所有ys
。这表明您应该将它们存储在适当的结构中。也许是哈希表。