1

I want to generate all possible trees from an int list [Int] -> [T] but I generate only one tree.

1           1
2           2
3           5
4          14
5          42

like these Catalan numbers. If my list size is 3, I want to generate 5 possible trees, if 4 — 14 possible trees.

Code:

data T = N T T | L Int deriving (Show)
toT :: [Int] -> T
toT [] = L 0
toT [n] = L n
toT ns = T (toT (take mid ns)) (toT (drop (mid+1) ns))
where
mid = length ns div 2

for example: toT [1..3]

output: N (L 1) (N (L 2) (L 3)) and N (N (L 1) (L 2)) (L 3).

now ı did like this

     toTree [] = error "!!"
     toTree [n] = Leaf n
     toTree ns = Node leftTree rightTree
     where 
     leftTree = toTree $ take (length(ns)-1) ns
     rightTree = toTree $ drop (length(ns)-1) ns` ı want ns length contiue descend one point recursive but ı didnt

How can ı do that ? in recursive ı will send same list but length wil be descend ı sent [1,2,3] size 3 again ı sent [1,2,3] length 2

Guy Coder
  • 24,501
  • 8
  • 71
  • 136
samcuk
  • 21
  • 4
  • There are actually n!*C(n-1) distinct trees with n leaves; C(n-1) shapes, and n! ways to place n integers in the leaves. – chepner Apr 15 '16 at 01:58
  • It's also not as simple as splitting your list in half; there are shapes with k=1,...,n-1 leaves in each subtree, not just n/2 leaves in each. – chepner Apr 15 '16 at 02:26
  • @chepner the numbers shown of possible tree shapes correspond to binary tree which stores values in nodes and has empty leaves: `data Tree a = Branch a (Tree a) (Tree a) | Empty`. – Will Ness Apr 15 '16 at 07:59
  • 1
    in your example you show 2 possible tree shapes for 3 ints, with your data type, but earlier you speak of 5 (and the table shows 5 as well). which is correct, the data type, or the table? – Will Ness Apr 15 '16 at 08:16
  • table like this size 1 tree 1,size 2 tree 1,size 3 tree 2,size 4 tree 5 size 5 tree 14 sory for msitake – samcuk Apr 15 '16 at 08:30
  • So you only want trees whose leaves are in the same order as the input list? That's not all possible trees. – chepner Apr 15 '16 at 11:24
  • yes you are right ı will change it.can you help for this problem – samcuk Apr 15 '16 at 11:34

2 Answers2

1

What needs to happen is that the list needs to be split at each possible point where doing so makes the list smaller. The trees of the sublists need to be accumulated, and then everything gets combined.

data Tree
  = L {-# UNPACK #-} !Int
  | N !Tree !Tree
  deriving (Eq, Ord, Read, Show)

-- Convert a list of Ints into a list of Trees containing the given list.
toTrees :: [Int] -> [Tree]

-- We start with the base cases: 0 and 1 elements. Because there are no
-- trees of 0 length, it returns the empty list in that case.
toTrees [] = []
toTrees [x] = [L x]

-- There is at least two elements in this list, so the split into nonempty
-- lists contains at least one element.
toTrees (x:xs@(y:ys)) = let
  -- splitWith uses a difference list to accumulate the left end of the
  -- split list.
  splitWith :: ([a] -> [a]) -> [a] -> [([a], [a])]
  splitWith fn [] = []
  splitWith fn as@(a:as') = (fn [], as):splitWith (fn . (:) a) as'

  -- Now we use a list comprehension to take the list of trees from each
  -- split sublist.
  in [
    N tl tr |
    (ll, lr) <- ([x], xs):splitWith ((:) x . (:) y) ys,
    tl <- toTrees ll,
    tr <- toTrees lr
  ]

This gives the desired results:

GHCi> toTrees [1, 2, 3, 4, 5]
[N (L 1) (N (L 2) (N (L 3) (N (L 4) (L 5)))),N (L 1) (N (L 2) (N (N (L 3) (L 4)) (L 5))),
 N (L 1) (N (N (L 2) (L 3)) (N (L 4) (L 5))),N (L 1) (N (N (L 2) (N (L 3) (L 4))) (L 5)),
 N (L 1) (N (N (N (L 2) (L 3)) (L 4)) (L 5)),N (N (L 1) (L 2)) (N (L 3) (N (L 4) (L 5))),
 N (N (L 1) (L 2)) (N (N (L 3) (L 4)) (L 5)),N (N (L 1) (N (L 2) (L 3))) (N (L 4) (L 5)),
 N (N (N (L 1) (L 2)) (L 3)) (N (L 4) (L 5)),N (N (L 1) (N (L 2) (N (L 3) (L 4)))) (L 5),
 N (N (L 1) (N (N (L 2) (L 3)) (L 4))) (L 5),N (N (N (L 1) (L 2)) (N (L 3) (L 4))) (L 5),
 N (N (N (L 1) (N (L 2) (L 3))) (L 4)) (L 5),N (N (N (N (L 1) (L 2)) (L 3)) (L 4)) (L 5)]
GHCi> length it
14
Zemyla
  • 468
  • 3
  • 7
-2

I updated your code and it seems to work for me. Can you check to see if this meets your expectations?

import Data.List

data Tree = Node Tree Tree | Leaf Int deriving (Show)

toTree :: [Int] -> Tree
toTree [] = Leaf 0
toTree [n] = Leaf n
toTree ns = Node leftTree rightTree
    where midIndex = (length ns) `div` 2
          leftTree = toTree $ take midIndex ns
          rightTree = toTree $ drop (midIndex+1) ns

allTrees :: [Int] -> [Tree]
allTrees xs = map toTree $ permutations xs

main = print $ allTrees [1..4]
Garrett M
  • 103
  • 2
  • 10
  • 3
    Just looking at the type of `toTree` it's clear it can't meet the expectations of "generate all possible trees". – Daniel Wagner Apr 14 '16 at 18:04
  • thanks but this produce for [1..3] 6 tree but ı want ex for [1..3] (N L1) (N (L2) (L3)) and N(N (L1) (L2)) (L3) – samcuk Apr 15 '16 at 07:05