Generate All Possible Trees

南楼画角 提交于 2019-12-06 10:27:44

问题


Given the following data type definition:

data FormTree = Empty | Node FormTree FormTree deriving Show

I want to write a function which generates an infinite list containing all possible trees sorted after length e.g. the amount of nodes.

The following code almost does what I need but it only descends the tree on the right side by inserting additional nodes every time but I need it to alternate between both sides.

allPossibleTrees :: [FormTree]
allPossibleTrees = Empty : [Node x y | x <- recursive, y <- recursive]
    where recursive = allPossibleTrees

Executing

take 5 allPossibleTrees

gives:

[Empty,Node Empty Empty,Node Empty (Node Empty Empty),Node Empty (Node Empty (Nodes Empty Empty)),Node Empty (Node Empty (Node Empty (Node Empty Empty)))]

but it should be something like:

[Empty,Node Empty Empty,Node (Node Empty Empty) Empty,Node Empty (Node Empty Empty),Node (Node Empty Empty) (Node Empty Empty)]

回答1:


Here's a nice trick, reminiscent of the standard Fibonacci numbers trick. We'll build a lazy list; each member of the list will be a list of all trees with a given number of nodes. There's just one tree with no nodes, Empty, and that will serve as our base case. To build all the trees with n nodes, we'll assume we already know how to build trees with 0, 1, 2, ..., n-1 nodes. Then we'll just non-deterministically choose a pairing of those that sums to n-1 and stuck a Node on top.

In code:

import Control.Monad
import Data.List

sizes :: [[FormTree]]
sizes = [Empty] : (map go . drop 1 . inits) sizes where
    go smaller = do
      (ls, rs) <- zip smaller (reverse smaller)
      liftM2 Node ls rs

Then we can simply define allPossibleTrees = concat sizes if that's wanted. The first few entries:

*Main> mapM_ print (take 4 sizes)
[Empty]
[Node Empty Empty]
[Node Empty (Node Empty Empty),Node (Node Empty Empty) Empty]
[Node Empty (Node Empty (Node Empty Empty)),Node Empty (Node (Node Empty Empty) Empty),Node (Node Empty Empty) (Node Empty Empty),Node (Node Empty (Node Empty Empty)) Empty,Node (Node (Node Empty Empty) Empty) Empty]

We can do a quick sanity check:

*Main> take 10 (map length sizes)
[1,1,2,5,14,42,132,429,1430,4862]

...which is indeed the first ten Catalan numbers, so we probably got it right!




回答2:


The list comprehension

[ (x,y) | x<-[1..] , y<-[1..] ]

starts by considering x=1 and building all the pairs (1,y) for all the possible ys. Then follows with x=2 and all the (2,y) pairs. and so on.

However, there are infinitely many (1,y) pairs, so x=2 will only be considered after an infinite amount of time -- that is, not at all.

Your code suffers from the same problem.

To see a possible solution, you can refer to this related question exploiting the Omega monad to achieve a fair scheduling among all the cases.




回答3:


One way is to keep track of the size of the tree (i.e. the number of Node constructors used.)

Suppose you had a function like this which returned the trees using exactly n Node constructors:

treesOfSize :: Int -> [FormTree]

Then allTrees could be defined as:

allTrees = concatMap treesOfSize [0..]

The definition of treesOfSize can be recursively defined which I'll let you figure out:

treesOfSize 0 = [Empty]
treesOfSize n = [ Node t1 t2 | ... ]



回答4:


control-monad-omega library seems to do the trick with your original code:

{-# LANGUAGE MonadComprehensions #-}

import Control.Monad.Omega

data Empty = Empty | Node Empty Empty deriving Show

allPossibleTrees :: [Empty]
allPossibleTrees = Empty : 
    runOmega [Node x y | x <- each allPossibleTrees, y <- each allPossibleTrees]

First 10 trees look good to me:

*Main> mapM_ print $ take 10 allPossibleTrees 
Empty
Node Empty Empty
Node Empty (Node Empty Empty)
Node (Node Empty Empty) Empty
Node Empty (Node Empty (Node Empty Empty))
Node (Node Empty Empty) (Node Empty Empty)
Node (Node Empty (Node Empty Empty)) Empty
Node Empty (Node (Node Empty Empty) Empty)
Node (Node Empty Empty) (Node Empty (Node Empty Empty))
Node (Node Empty (Node Empty Empty)) (Node Empty Empty)


来源:https://stackoverflow.com/questions/28100650/generate-all-possible-trees

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!