Sus*_*ded 3 tree haskell permutation
正如标题所说,我需要这个:
getAllTrees :: [Int] -> [Tree Int]
getAllTrees xs = undefined
Run Code Online (Sandbox Code Playgroud)
树在哪里
data Tree x
= Null
| Leaf x
| Node (Tree x) x (Tree x)
Run Code Online (Sandbox Code Playgroud)
我会感激任何帮助,即使是最小的线索:)谢谢
ham*_*mar 11
我通常发现使用list monad来解决这些问题最容易.我们可以getAllTrees通过推理来定义如下:
唯一的零项目树是Null:
getAllTrees [] = return Null
Run Code Online (Sandbox Code Playgroud)
一个元素中只有一棵树,即Leaf:
getAllTrees [x] = return $ Leaf x
Run Code Online (Sandbox Code Playgroud)
当我们有多个元素时,我们可以用所有可能的方式拆分列表以确定我们应该如何分支,然后从每个列表递归生成子树.假设我们有一个函数splits :: [a] -> [([a], [a])]返回分割列表的所有方法,例如:
> splits [1..3]
[([],[1,2,3]),([1],[2,3]),([1,2],[3]),([1,2,3],[])]
Run Code Online (Sandbox Code Playgroud)
然后我们可以getAllTrees使用list monad 定义最终的情况.这允许我们编写类似于我们只关注一个案例的代码,monad将为我们提供所有组合.
getAllTrees xs = do
(left, x : right) <- splits xs
Node <$> getAllTrees left <*> pure x <*> getAllTrees right
Run Code Online (Sandbox Code Playgroud)
第一行拆分输入列表,并将第二部分中的第一项作为中间元素.第二部分为空时的情况与模式不匹配,因此它被丢弃,因为列表monad处理模式匹配失败的方式.
第二行使用应用语法来说我们希望结果是一个节点列表,由列表中的子树的所有组合left,固定的中间元素x和right列表中的所有子树组成.
剩下的就是实施splits.看看上面的例子中,可以很容易地看到,我们可以只取inits和tails名单和zip他们在一起:
splits xs = zip (inits xs) (tails xs)
Run Code Online (Sandbox Code Playgroud)
是时候在口译员中进行快速的健全检查:
> mapM_ print $ getAllTrees [1..3]
Node Null 1 (Node Null 2 (Leaf 3))
Node Null 1 (Node (Leaf 2) 3 Null)
Node (Leaf 1) 2 (Leaf 3)
Node (Node Null 1 (Leaf 2)) 3 Null
Node (Node (Leaf 1) 2 Null) 3 Null
> length $ getAllTrees [1..5]
42
Run Code Online (Sandbox Code Playgroud)
看起来我们已经完成了!一些重要的经验: