Haskell leftmost deepest node of tree - list

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.

Related

Haskell problem with potential workaround for empty lists

I defined a function that receives a data type and a list.
getAux :: (Ord a) => SparseArray a -> [Bool] -> (Value a)
getAux (Node x left right) index
| length(index) == 0 = x
| head(index) == False = getAux (left) (tail(index))
| head(index) == True = getAux (right) (tail(index))
I iterate through this function passing the tail of index
There are 3 possible returns: If the length of the list is less that or equal to 1 it returns x (the value stored in the node) If not it check the head of index and it calls getAux with the tail of index.
I tried to do a simple workaround to this issue by adding an extra element to the end of index when I call getAux. Instead of comparing if the length of index is equal to 0 I compare it with 1.
When I call the function I have:
getAux (Nodo x iz de) (num2bin(index) ++ [True])
The new getAux is:
getAux :: (Ord a) => SparseArray a -> [Bool] -> (Value a)
getAux (Node x left right) index
| length(index) == 1 = x
| head(index) == False = getAux (left) (tail(index))
| head(index) == True = getAux (right) (tail(index))
In both cases I get an error indicating that I can't do the head of an empty list
You call this with tail index, hence eventually you reach the empty list, hence that explains why for the latter, if length index == 1 fails, it will try to access head index and thus error.
But using length is not a good idea since it runs in O(n) with n the length of the list, and usually it is better to perform pattern matching on the list than to use head and tail, since then it is guaranteed that the list has a head and tail.
You can thus implement this as:
getAux :: SparseArray a -> [Bool] -> Value a
getAux (Node x _ _) [] = x
getAux (Node _ left right) (x:xs)
| x = getAux right xs
| otherwise = getAux left xs
By turining -Wincomplete-patterns [Haskell-docs] on for the compiler, it will warn you for patterns that the function does not cover. For example if your SparseArray has an extra data constructor, then these cases are not covered (yet).

Constructor not in Scope / Pattern matching parse error

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

Reverse Monkey Puzzle sort (Haskell)

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

Filling a normal binary tree in ML with values

Where let's say:
datatype bin_tree = Empty |
Node of value * bin_tree * bin_tree
How would I go about filling a binary tree (not a binary search tree where left is smaller than root and right bigger). Just values from a list inserted at each node in a binary tree.
You use the value constructors you've declared.
If we assume for a moment that value is int instead, then we for instance have that the tree
1
/ \
2 4
/
3
is represented by:
Node (1,
Node (2,
Node (3, Empty, Empty),
Empty
),
Node (4, Empty, Empty)
)
Or, equivalently, on one line:
Node (1, Node (2, Node (3, Empty, Empty), Empty), Node (4, Empty, Empty))
It's not really possible to help you, without knowing more about how you wan't your tree constructed from a given list. However here is an example that creates a balanced tree. It takes the first element and uses it as the node value, and then it splits the rest of the list into two sub lists of equal size (if possible), by taking all "even" element in the "left" list and all "odd" elements in the "right" list:
datatype 'a bin_tree = Empty
| Node of 'a * 'a bin_tree * 'a bin_tree
fun list_split xs =
let
fun loop [] (left, right) = (rev left, rev right)
| loop (x::y::xs) (left, right) = loop xs (x :: left, y :: right)
| loop (x :: xs) (left, right) = loop xs (x :: left, right)
in
loop xs ([], [])
end
fun built_tree [] = Empty
| built_tree (x :: xs) =
let
val (left, right) = list_split xs
val left_tree = built_tree left
val right_tree = built_tree right
in
Node (x, left_tree, right_tree)
end
The result:
- built_tree [1,2,3,4,5,6,7,8,9];
val it =
Node
(1,Node (2,Node (4,Node (8,Empty,Empty),Empty),Node (6,Empty,Empty)),
Node (3,Node (5,Node (9,Empty,Empty),Empty),Node (7,Empty,Empty)))
: int bin_tree
Here is an answer to the same question done in Java. This will probably help a good bit :).

Sorting a list in OCaml

Here is the code on sorting any given list:
let rec sort lst =
match lst with
[] -> []
| head :: tail -> insert head (sort tail)
and insert elt lst =
match lst with
[] -> [elt]
| head :: tail -> if elt <= head then elt :: lst else head :: insert elt tail;;
[Source: Code
However, I am getting an Unbound error:
Unbound value tail
# let rec sort lst =
match lst with
[] -> []
| head :: tail -> insert head (sort tail)
and insert elt lst =
match lst with
[] -> [elt]
| head :: tail -> if elt <= head then elt :: lst else head :: insert elt tail;;
Characters 28-29:
| head :: tail -> if elt <= head then elt :: lst else head :: insert elt tail;;
^
Error: Syntax error
Can anyone please help me understand the issue here?? I did not find head or tail to be predefined anywhere nor in the code
Your code seems correct, and compiles for me:
Objective Caml version 3.11.1
# let rec sort lst = ...
val sort : 'a list -> 'a list = <fun>
val insert : 'a -> 'a list -> 'a list = <fun>
# sort [ 1 ; 3 ; 9 ; 2 ; 5 ; 4; 4; 8 ; 4 ] ;;
- : int list = [1; 2; 3; 4; 4; 4; 5; 8; 9]
Adding to what Pascal said, the list type is defined as:
type 'a list = [] | :: of 'a * 'a list
and that's what you are matching your list lst against.
The symbol “|“ is the horizontal line symbol, it is not l character and the -> are the minus symbol and the bigger symbol. I think you copied and pasted the segment of code in the website of Inria. Please check and rewrite the special symbols. I tested it and it works well.
Head and tail need not to be defined. They are matched from 'list' you give.