I have the following datatype:
data Tree a = Node [Tree a]
and I want to count how many nodes are in such a tree so I defined the following:
count:: Tree a -> Integer
count [] = 0
count Node label [childrenTree a] = 1 + count a
which gives me an error saying "Parse error in pattern: true". If I change childrenTree a to Tree a it says that the data constructor is not in scope.
How do I solve this?
This specifies that function count has three arguments, which is not what you want:
count Node label [childrenTree a] = ...
-- ^1 ^2 ^3
Further,
count [] = ...
specifies that there is a single argument, which must be a list (an empty list, to be exact). You want count to take trees as argument, not lists.
The right way to write the code is:
count:: Tree a -> Integer
count (Node subtrees) = ... -- here, we have subtrees :: [Tree a]
Alternatively:
count:: Tree a -> Integer
count (Node []) = ...
count (Node (t:ts)) = ...
--here t is the first tree in the list, ts is the list of remaining ones
Here's a complete working program:
data Tree a = Node [Tree a]
count:: Tree a -> Integer
count (Node []) = 1
count (Node (t:ts)) = count t + count (Node ts)
-- a little test
main :: IO ()
main = print (count (Node [Node [], Node [Node[], Node[]]]))
The output is 5, which is the number of Nodes in the input.
There is a tricky part in General Trees to take account, you have the function in the Tree itself, and you have the recursion over the list of tree so.
Another thing is, you tree as it is, doesn't save any valuable information, you can change it a little bit as:
data Tree a = Node a [Tree a] deriving (Show)
and the two functions will be like:
count:: Tree a -> Integer
count (Node _ trees) = 1 + countLs trees
countLs [] = 0
countLs (t:ts) = (count t) + (countLs ts)
and a little demo:
genTree1 = NodeG "1" [NodeG "2" [],
NodeG "3" [NodeG "4" [],
NodeG "5" [NodeG "6" [],
NodeG "7" [],
NodeG "8" []
]
]
]
runing example:
$> count genTree1
8
Related
Suppose I have a binary tree structure defined as
data IntTree = Empty | Node Int IntTree IntTree
and the tree
Node 0 (Node 1 Empty Empty)(Node 2 (Node 3 Empty Empty)(Node 4 Empty Empty))
How can I extract the leftmost deepest node (ie Node 3 Empty Empty)?
You should make use of recursion and define a helper function that returns the depth of the node, then for each innode, you select the deepest child. Such function thus looks like:
leftmostDeep : IntTree -> IntTree
leftmostDeep = fst . go
where go n#(Node _ Empty Empty) = (n, 0)
go n#(Node _ Empty r) = let (nr, dr) = go r in (nr, dr+1)
go n#(Node _ l Empty) = let (nl, dl) = go l in (nl, dl+1)
go (Node l r) = …
where (na, da) = go l
where (nb, db) = go r
where … is left as an exercise. This should determine which item is the deepest, and as tiebreaker, return the left subtree. You should also increment the depth of that node with one.
[Node 0 (Node 1 Empty Empty)(Node 2 (Node 3 Empty Empty)(Node 4 Empty Empty))]
[ Node 1 Empty Empty, Node 2 (Node 3 Empty Empty)(Node 4 Empty Empty) ]
[ Empty,Empty, Node 3 Empty Empty, Node 4 Empty Empty ]
[ Empty,Empty, Empty,Empty ]
[ ]
suggests
deepest :: IntTree -> [Int]
deepest = pure >>> iterate (>>= g) >>> takeWhile (not . null)
>>> reverse >>> drop 1 >>> take 1
>>> (>>= \ xs -> [i | Node i _ _ <- xs])
where
g (Node _ lt rt) = [lt, rt]
g Empty = []
and then we get
> deepest $ Node 0 (Node 1 Empty Empty)
(Node 2 (Node 3 Empty Empty) (Node 4 Empty Empty))
[3,4]
so all that's left is to take 1 from that, if you want to.
I have the following data type
data Tree a -> Node a [Tree a]
and would like to find the labels of all the Nodes and height of the tree.
Here is what I did:
height:: Tree a -> Integer height
(Node _ (x:xs)) = 1 + maximum height' (x:xs)
height' (x:xs) = map height (x:xs)
I was hoping that height' would return a list of height mapped over x:xs and try to find the max of that value but ghci does not approve of the map function here.
You can write this in a one liner with:
height :: Integral i => Tree a -> i
height (Node _ cs) = 1 + maximum (0 : map height cs)
Here for every node, we thus return 1 + … where … is the maximum of 0 and the heights of the children of these nodes. We here use 0 to prevent that, if the Node hase no children, the maximum will work over an empty list, and thus raise an error.
Taking in account I defined the Tree as:
data GenTree a = NodeG a [GenTree a] deriving (Show)
Well, in this one you where a little closer:
height:: GenTree a -> Integer
height (NodeG _ []) = 0 -- Deep 0
height (NodeG _ trees) = 1 + (maximum $ heightLs trees) -- take the max
-- (maximum $ heightLs trees) == (maximum (heightLs trees))
heightLs (x:xs) = map height (x:xs) -- here is perfect
genTree1 = NodeG "1" [NodeG "2" [],
NodeG "3" [NodeG "4" [],
NodeG "5" [NodeG "6" [],
NodeG "7" [],
NodeG "8" [
NodeG "9" []
]
]
]
]
Example
$> height genTree1
=> 4
I have the following type:
data NestedList a = Elem a | List [NestedList a]
I'm trying to write a function that returns the most nested list within a given list, but I don't know where to start. Any help appreciated!
Example:
input of function is something like:
(List [List [List [List [Elem 1, Elem 2, Elem 3], Elem 5, Elem 6], List [Elem 5, Elem 6]], List [Elem 5, Elem 6]])
desired output of function:
(List [Elem 1, Elem 2, Elem 3])
I'll give an example using binary trees instead, which are very similar to your structure. You'll have the exercise of converting it to work with your data type.
Say I have a binary tree
data Tree a
= Leaf a
| Node (Tree a) (Tree a)
deriving (Eq, Show)
and I want to find the values that have the maximum depth (there can be more than one!). How I would solve this would be to traverse down each branch recursively, recording the depth as I go, and then return back the value(s) at the bottom along with their depth.
First, I'll define my function structure
import Data.List (sortBy, groupBy)
import Data.Ord (comparing)
import Data.Function (on)
getDeepest :: Tree a -> [a]
getDeepest tree
= map fst -- Strip the depth from the values
. head -- Get just the ones with the largest depth
. groupBy ((==) `on` snd) -- Group by the depth
. sortBy (flip (comparing snd)) -- Reverse sort by the depth (largest first)
$ go tree 0 -- Find all the "bottom" nodes
where
go :: Tree a -> Int -> [(a, Int)]
go (Leaf a) n = undefined
go (Node l r) n = undefined
This is a common recursion format you'll see in Haskell. I have a local helper function that carries an additional value that I want to initialize at a particular value, in this case the depth 0. I've already included the logic that I know I want in order to get the output in a nice format. The flip (comparing snd) will do a reverse sort, so the largest depth will come first. We then group by the depth, extract the first group, then strip the depth from the values.
Now we just have to define what go does. We know that when we hit the bottom, we want to add the value to our accumulator with the depth that we found, so
go (Leaf a) n = [(a, n)]
That case is pretty easy, we just make a tuple from the value and the depth and wrap it as a list. For the other case, we want to traverse down each branch, find the deepest elements, and return the deepest from both branches
go (Node l r) n = go l (n + 1) ++ go r (n + 1)
This is where the recursion happens. While this is certainly not the most efficient algorithm (Haskell lists aren't great for this, but we'll use them for simplicity), it is pretty simple still. All we do is go down each side and increase our depth by 1. So the whole algorithm together:
getDeepest :: Tree a -> [a]
getDeepest tree
= map fst -- Strip the depth from the values
. head -- Get just the ones with the largest depth
. groupBy ((==) `on` snd) -- Group by the depth
. sortBy (flip (comparing snd)) -- Reverse sort by the depth (largest first)
$ go tree 0 -- Find all the "bottom" nodes
where
go :: Tree a -> Int -> [(a, Int)]
go (Leaf a) n = [(a, n)]
go (Node l r) n = go l (n + 1) ++ go r (n + 1)
So as an example:
myTree :: Tree Int
myTree =
Node
(Node
(Leaf 1)
(Node
(Leaf 2)
(Leaf 3)))
(Leaf 4)
Which can be visualized as
Node
/ \
Node Leaf 4
/ \
Leaf 1 Node
/ \
Leaf 2 Leaf 3
Then by applying getDeepest to it returns [2, 3]. I encourage you to drop the type signature from getDeepest and try deleting the various functions before go tree 0 (starting at the top) so that you can see what it looks like at each step, it should help you visualize the algorithm a bit better.
Consider the following definition of trees:
Data Tree a = Empty | Node a (Tree a) (Tree a)
Define the function smallerbigger :: Float -> Tree Float -> ([Float],[Float]) that given a number n and a tree, produces a pair of lists whose elements are smaller and bigger than n.
(the question initially stated that the tree is a search tree, which was done in error).
For a list, you could implement a similar algorithm as
smallerbigger :: Ord a => a -> [a] -> ([a], [a])
smallerbigger x xs = go x xs [] []
where
go y [] lt gt = (lt, gt)
go y (z:zs) lt gt
| z < y = go y zs (z:lt) gt
| z >= y = go y zs lt (z:gt)
The basic shape of the algorithm will remain the same for a Tree, but the biggest difference will be how you recurse. You'll need to recurse down both branches, then once you get the result from each branch concatenate them together along with the result from the current node.
If you get stuck implementing this for a tree, feel free to comment and let me know what problem you're experiencing and include a link to your code in a gist/pastebin/whatever.
Here little set of utilities leading to simple solution. Assuming you need lazy function.
Here your data defition with addition of only show ability for debug
data Tree a = Empty | Node a (Tree a) (Tree a) deriving Show
Next we need to a little utility for easy tree creating. Following code is building a very unbalanced tree that is very similar to original list.
fromList:: [a] -> Tree a
fromList [] = Empty
fromList (x:xs) = Node x Empty (fromList xs)
Simple and obvious representation of tree in list form. Order of elements is preserved.
asList:: Tree a -> [a]
asList Empty = []
asList (Node x left right) = asList left ++ x: asList right
Next we assume we'll need pair of lists that could be lazy regardless of our destination.
We are keeping ability to work with tree that has infinite structure somewhere in the middle, but not at the last or end element.
This definition to walk our tree in opposite direction in lazy manner.
reverseTree:: Tree a -> Tree a
reverseTree Empty = Empty
reverseTree (Node x left right) = Node x (reverseTree right) (reverseTree left)
Next we finally building our procedure. It could create two possible infinite list of elements smaller and bigger than first argument.
smallerbigger::Ord a => a-> Tree a -> ([a],[a])
smallerbigger p t = (takeWhile (<p) $ asList t, takeWhile (>p) $ asList $ reverseTree t)
main = let t = fromList [1..10]
in do
print t
print $ smallerbigger 7 t
But in other hand we may want to preserve order in second list, while we are sure that we never hit bottom building first list. So we could drop elements that are equal to target separator and just span out list at it.
smallerbigger p = span (<p) . filter(/=p) . asList
Thanks for all the help and suggestions.
I managed to find a different solution:
smallerbigger :: Ord a => a -> Tree a -> ([a], [a])
smallerbigger n (Node r e d) =
let (e1,e2) = smallerbigger n e
(d1,d2) = smallerbigger n d
in if r>n then ( e1++d1, r:(e2++d2))
else if r<n then (r:(e1++d1), e2++d2 )
else ( e1++d1, e2++d2 )
Consider the following type to represent trees:
data Tree a = Empty
| Leaf a
| Fork (Tree a) (Tree a)
I need help definig the function removeRandom' :: Tree a -> IO (Tree a) that receives a tree with at least a leaf and returns the result of removing a random leaf from the tree (replacing it with Empty). The exercise had a suggestion: use the function randomRIO :: Random a => (a,a) -> IO a to generate the order of the element to remove
EDIT: trying method 2 of user Thomas
removeRandom' :: Tree a -> IO (Tree a)
removeRandom' t = let lengthTree = numbelems t
in do x <- randomRIO (0,lengthTree -1)
return (remove x t)
numbelems :: Tree a -> Int
numbelems Empty = 0
numbelems Leaf x = 1
numbelems Fork l r = (numbelems l) + (numbelems r)
remove :: Int -> Tree a -> Tree a
remove _ (Leaf x) = Empty
remove n (Fork l r) = let lengthLeft = numbelems l
in if (n>lengthLeft) then Fork l (remove (n-lengthLeft r)
else Fork (remove n l) r
There are 2 ways to approach this problem
Convert to a list, remove the element, and convert back to a tree.
Pros: Simple to implement, you already have toList, all you need is fromList, and you can implement your solution simply as
removeAt :: Int -> [a] -> [a]
removeAt n as = a ++ tail s where (a, s) = splitAt n
removeRandom' tree = do
element <- randomRIO (0, length tree)
return $ fromList $ removeAt element $ toList tree
Cons: This method is not "True" to the problem statement removing a random leaf from the tree (replacing it with Empty) and will likely give you a brand new tree with no Empty values in it. I have only provided this as an option in an attempt to show where your toList method ends up.
Descend into the tree, until you hit the element to be removed, then rebuild the tree on the way back up
Pros: The meat of the algorithm is "Pure" as in, does not touch IO. You only actually need IO for a moment within removeRandom'. You can likely write a solution that looks a bit like this (interesting parts left blank ;).
removeAt :: Int -> Tree a -> Tree a
removeAt n tree = walk 0 tree
where
walk i Empty = ...
walk i (Fork l r) = ...
walk i l#(Leaf _)
| i == n = ...
| otherwise = ...
removeRandom' tree = do
element <- randomRIO (0, length tree)
return $ removeAt element tree
Cons: More complicated to implement, you need to know how to traverse back "up" a tree, rebuilding in your wake, and you will need to know how to write a recursive function with an accumulator such that you can track your position in the tree.
Either way you decide to go, you will need to write a function length :: Tree a -> Int that counts the number of leaves to use as input to randomRIO (which is an action that simply produces a random value in a given range).