I have a repeat in Haskell in Augest so I'm trying to practice my Haskell.
One of the questions is:
"A reverse monkey puzzle sort of a list is performed by storing the elements of the list into a binary tree and then traversing the tree so that the nodes of a subtree are visited in the order right child, parent and then left child. Write a reverse monkey puzzle sort in Haskell"
The question confuses me.
I know I have to write a function to go xr Node xl.
But does this have to output a list from the traversed tree? Or do I repopulate the binary tree with the list or what?
Also, would I start down in the farthest right element and go to that's parent then go left, or start at the very first root node at the top of the tree and go that way?
Also how would I go about writing it, Haskell is one of my weak points.
Appreciate any help with this!
Here is code I have
module Data.BTree where
data Tree a = Tip | Node a (Tree a) (Tree a) deriving (Show,Eq)
leaf x = Node x Tip Tip
t1 = Node 10 Tip Tip
t2 = Node 17 (Node 12 (Node 5 Tip(leaf 8)) (leaf 15))
(Node 115
(Node 32 (leaf 30) (Node 46 Tip (leaf 57)))
(leaf 163))
t3 = Node 172 (Node 143 (Node 92 (Node 76 (leaf 32) (leaf 45)) (Node 58 (leaf 39) (leaf 52))) (Node 107 (Node 92 (leaf 64) (leaf 35)) (Node 86 (leaf 69) (leaf 70))))
(Node 155 (Node 127 (leaf 83) (leaf 97)) (Node 138 (leaf 107) (leaf 91)))
You can write
data Tree a = Empty | Tree (Tree a) a (Tree a)
ins :: Ord a => Tree a -> a -> Tree a
ins Empty x = Tree Empty x Empty
ins (Tree l y r) x = if x < y then Tree (ins l x) y r else Tree l y (ins r x)
fromList :: Ord a => [a] -> Tree a
fromList = foldl ins Empty -- <<< FOLDABLE
toList :: Ord a => Tree a -> [a]
toList Empty = []
toList (Tree l x r) = (toList l) ++ [x] ++ (toList r) -- <<< MONOID
-- (change order if you wish)
sort :: Ord a => [a] -> [a]
sort = toList . fromList
to solve directly your problem.
In general is useful use more abstract structures like monoid, foldable, ... you can (must) read Learn You Haskell for Great Good!
:)
Example
*Main> sort [6, 3, 7, 8, 3, 6]
[3,3,6,6,7,8]
As commented (into code), one more general way to do it, is to define some useful structs into Tree: Foldable, Monoid and others.
Suppose we have that two structs implemented:
import Data.Foldable
import Data.Monoid
data Tree a = Empty | Tree (Tree a) a (Tree a) deriving Show
-- Shortcut
leaf :: Ord a => a -> Tree a
leaf x = Tree Empty x Empty
instance Foldable Tree where
foldMap f Empty = mempty
foldMap f (Tree l k r) = foldMap f l `mappend` f k `mappend` foldMap f r
-- WARNING: in that monoid only traverse result (ordered list) is invariant!
instance Ord a => Monoid (Tree a) where
mempty = Empty
mappend Empty tree = tree
mappend tree Empty = tree
mappend (Tree l x r) tree = ins (l `mappend` r `mappend` tree) x
where ins Empty x = leaf x
ins (Tree l y r) x = if x < y then Tree (ins l x) y r else Tree l y (ins r x)
that are usual in Haskell.
Now, your problem (define sort on lists using load/unload a tree) is simply:
sort :: Ord a => [a] -> [a]
sort = foldMap return . foldMap leaf
A more general way (struct) was detailed by #m0nhawk, #tel and #petr-pudlak in this question
Related
I have an inductive type tree defined as follow:
type 'a tree1 = Leaf of 'a
|Branch of 'a tree1 * 'a tree1
I want to have a function that takes in this tree as an input, finds a min value in this tree, doubles it (let's call the result as a) and then reproduces another tree of the same type which all of its leaves are replaced by a.
I have a couple of functions to help me do this:
let rec findmin (mytree: int tree1) : int = match mytree with
|Leaf a -> a
|Branch(Leaf x, Leaf y) -> min x y
|Branch(left, right) -> min (findmin left) (findmin right)
let rec repdoublemin (mytree: int tree1) : int tree1 = match mytree with
|Leaf a -> Leaf (2*a)
|Branch(Leaf x, Leaf y) -> let result = 2 * findmin (Branch(Leaf x, Leaf y))
in Branch (Leaf result, Leaf result)
|Branch(left,right) -> Branch(repdoublemin left, repdoublemin right)
My result is not what I expected.
repdoublemin Branch (Leaf 5, Branch (Leaf 3, Leaf 10));;
- : int tree1 = Branch (Leaf 10, Branch (Leaf 6, Leaf 6))
and I am supposed to get :
- : int tree1 = Branch (Leaf 6, Branch (Leaf 6, Leaf 6))
My suggestion would be to write a helper function
replace_all_values : 'a -> 'b tree1 -> 'a tree1
I have this data structure for a tree:
data Tree a = NodeT a (Tree a) ( Tree a) | EmptyT
I need to create a function that returns a list of lists where each element of the list represents a level of the tree. For instance, from this:
1
/ \
2 3
/ \ / \
4 5 6 7
to this: [[1],[2,3],[4,5,6,7]]
The function must have the following form:
f :: Tree a -> [[a]]
How to do it using recursion?
anyone?
Thanks
Answer
levels :: Tree a -> [[a]]
levels t = levels' t []
levels' :: Tree a -> [[a]] -> [[a]]
levels' EmptyT rest = rest
levels' (NodeT a l r) [] = [a] : levels' l (levels r)
levels' (NodeT a l r) (x : xs) = (a : x) : levels' l (levels' r xs)
A slightly more complicated, but lazier, implementation of levels':
levels' EmptyT rest = rest
levels' (NodeT a l r) rest = (a : front) : levels' l (levels' r back)
where
(front, back) = case rest of
[] -> ([], [])
(x : xs) -> (x, xs)
Fans of folds will note that these are structured as catamorphisms:
cata :: (a -> b -> b -> b) -> b -> Tree a -> b
cata n e = go
where
go EmptyT = e
go (NodeT a l r) = n a (go l) (go r)
levels t = cata br id t []
where
br a l r rest = (a : front) : l (r back)
where
(front, back) = case rest of
[] -> ([], [])
(x : xs) -> (x, xs)
As chi points out, there seems to be some connection between this general approach and the result of using Jakub Daniel's solution with difference lists as intermediate forms. This could look something like
import Data.Monoid
levels :: Tree a -> [[a]]
levels = map (flip appEndo []) . (cata br [])
where
br :: a -> [Endo [a]] -> [Endo [a]] -> [Endo [a]]
br a l r = Endo (a :) : merge l r
merge :: Monoid a => [a] -> [a] -> [a]
merge [] ys = ys
merge (x : xs) ys = (x <> y) : merge xs ys'
where
(y,ys') =
case ys of
[] -> (mempty, [])
p : ps -> (p, ps)
I'm not entirely sure just how this compares with the more direct approaches.
Discussion
Kostiantyn Rybnikov's answer cites Okasaki's Breadth-First Numbering: Lessons from a Small Exercise in Algorithm Design, an excellent paper that highlights many functional programmers' "blind spots" and offers good arguments for making abstract data types easy enough to use that they won't be missed. However, the problem that paper describes is significantly more complex than this one; not so much machinery is required here. Also, the paper notes that level-oriented solutions are actually slightly faster than queue-based ones in ML; I'd expect to see a larger difference in a lazy language like Haskell.
Jakub Daniel's answer attempts a level-oriented solution, but unfortunately has an efficiency problem. It builds each level by repeatedly appending one list to another, and those lists may all be of equal length. Thus in the worst case, if I am calculating this correctly, it takes O(n log n) to process a tree with n elements.
The approach I chose is level-oriented, but avoids the pain of concatenation by passing each left subtree the levels of its right sibling and cousins. Each node/leaf of the tree is processed exactly once. That processing involves O(1) work: pattern matching on that node/leaf, and, if it is a node, pattern matching on the list derived from the right sibling and cousins. Thus the total time is O(n) to process a tree with n elements.
You recursively compute the levels and always merge lists from two subtrees point-wise (thus all the slices in the same depth get merged together).
f :: Tree a -> [[a]]
f EmptyT = []
f (NodeT a t1 t2) = [a] : merge (f t1) (f t2)
merge :: [[a]] -> [[a]] -> [[a]]
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys) = (x ++ y) : merge xs ys
If the tree were complete (all the paths from the root to a list are of the same length) then you could use zipWith (++) as merge.
Slightly more complicated solution, than the one which was accepted, but I think mine might be better in terms of memory consumption (it's a bit late, so please check yourself).
Intuition goes from a wonderful paper of Chris Okasaki "Breadth-First Numbering: Lessons from a Small Exercise in Algorithm Design". You can get general intuition on breadth-first tree traversals of trees in functional languages in detail.
I did somewhat ugly addition to add the "list of lists" splitting, there might be a better way:
module Main where
data Tree a = NodeT a (Tree a) (Tree a) | EmptyT
-- 1
-- / \
-- 2 3
-- / \ / \
-- 4 5 6 7
f :: Tree a -> [[a]]
f t = joinBack (f' [(t, True)])
type UpLevel = Bool
f' :: [(Tree a, UpLevel)] -> [(a, UpLevel)]
f' [] = []
f' ((EmptyT, _) : ts) = f' ts
f' ((NodeT a t1 t2, up) : ts) = (a, up) : f' (ts ++ [(t1, up)] ++ [(t2, False)])
joinBack :: [(a, UpLevel)] -> [[a]]
joinBack = go []
where
go acc [] = [reverse acc]
go acc ((x, False) : xs) = go (x : acc) xs
go acc ((x, True) : xs) = reverse acc : go [] ((x, False):xs)
main :: IO ()
main = do
let tree = NodeT 1 (NodeT 2 (NodeT 4 EmptyT EmptyT) (NodeT 5 EmptyT EmptyT))
(NodeT 3 (NodeT 6 EmptyT EmptyT) (NodeT 7 EmptyT EmptyT))
:: Tree Int
print (tail (f tree))
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).