I recently just started learning Haskell and I am trying to implement a function for searching for a specific value in a tri tree which returns true if the value is present and false otherwise. This is how my type looks:
data TriTree a
= Empty
| NodeOne a (TriTree a) (TriTree a) (TriTree a)
| NodeTwo a a (TriTree a) (TriTree a) (TriTree a)
deriving (Show)
This tree basically is empty or which contains at least one Internal Node. In which each Internal Nodes store one or two data values as well as have max three child nodes (left, middle, right).
It's not clear to me how to proceed with the search function to traverse through the tree and return the value.
Since you defined a recursive data structure, it makes sense to have a recursive function to parse it. To do that I'd start with anchoring the recursion in the trivial case. Since an empty tree doesn't contain anything, the check will always be false:
elem' _ Empty = False
Now to the recursive part: In the case of a NodeOne, we need to check if the value is inside that node or in any of the subtrees of that node, so we check if
elem' x (NodeOne v a b c) = x == v || x `elem'` a || x `elem'` b || x `elem'` c
The remaining case is for NodeTwo and I leave that for you to figure out, which shouldn't be difficult to as it is just a generalization of the line above:
elem' x _ = undefined -- remaining case
Try it online!
I have the following Haskell polymorphic data type:
data Tree a = Leaf Int a | Node Int (Tree a) (Tree a)
The tree will be compressed in a bitstring of 0s and 1s. A '0' signifies a Node and it is followed by the encoding of the left subtree, then the encoding of the right subtree. A '1' signifies a Leaf and is followed by 7 bits of information (for example it might be a char). Each node/leaf is supposed to also contain the frequency of the information stored, but this is not important for this problem (so we can put anything there).
For example, starting from this encoded tree
[0,0,0,1,1,1,0,1,0,1,1,1,1,1,1,0,1,0,0,0,0,1,1,1,1,0,0,0,1,1,1,
1,0,0,1,1,1,1,1,1,1,0,0,1,0,0,1,1,1,1,0,1,1,1,1,1,1,0,0,0,0,1]
it is supposed to give back something like this
Node 0 (Node 0 (Node 0 (Leaf 0 'k') (Leaf 0 't'))
(Node 0 (Node 0 (Leaf 0 'q') (Leaf 0 'g')) (Leaf 0 'r')))
(Node 0 (Leaf 0 'w') (Leaf 0 'a'))
(spacing is not important, but it did not fit on one line).
I have little experience working with trees, especially when implementing code. I have a vague idea about how I'd solve this on paper (using something similar to a stack to deal with the depth/levels) but I am still a bit lost.
Any help or ideas are appreciated!
Well, you're trying to parse a tree of bytes from a bit-stream. Parsing's one of those cases where it pays to set up some structure: we're going to write a miniature parser combinator library in the style of How to Replace Failure by a List of Successes, which will allow us to write our code in an idiomatic functional style and delegate a lot of the work to the machine.
Translating the old rhyme into the language of monad transformers, and reading "string" as "bit-string", we have
newtype Parser a = Parser (StateT [Bool] [] a)
deriving (Functor, Applicative, Monad, Alternative)
runParser :: Parser a -> [Bool] -> [(a, [Bool])]
runParser (Parser m) = runStateT m
A parser is a monadic computation which operates statefully on a stream of Booleans, yielding a collection of successfully-parsed as. GHC's GeneralizedNewtypeDeriving superpowers allow me to elide the boilerplate instances of Monad et al.
The goal, then, is to write a Parser (Tree SevenBits) - a parser which returns a tree of septuples of Booleans. (You can turn the 7 bits into a Word8 at your leisure by deriving a Functor instance for Tree and using fmap.) I'm going to use the following definition of Tree because it's simpler - I'm sure you can figure out how to adapt this code to your own ends.
data Tree a = Leaf a | Node (Tree a) (Tree a) deriving Show
type SevenBits = (Bool, Bool, Bool, Bool, Bool, Bool, Bool)
Here's a parser that attempts to consume a single bit from the input stream, failing if it's empty:
one :: Parser Bool
one = Parser $ do
stream <- get
case stream of
[] -> empty
(x:xs) -> put xs *> return x
Here's one which attempts to consume a particular bit from the input stream, failing if it doesn't match:
bit :: Bool -> Parser ()
bit b = do
i <- one
guard (i == b)
Here I'm pulling a sequence of seven Booleans from the input stream using replicateM and packing them into a tuple. We'll be using this to populate Leaf nodes' contents.
sevenBits :: Parser SevenBits
sevenBits = pack7 <$> replicateM 7 one
where pack7 [a,b,c,d,e,f,g] = (a, b, c, d, e, f, g)
Now we can finally write the code which parses the tree structure itself. We'll be choosing between the Node and Leaf alternatives using <|>.
tree :: Parser (Tree SevenBits)
tree = node <|> leaf
where node = bit False *> liftA2 Node tree tree
leaf = bit True *> fmap Leaf sevenBits
If node succeeds in parsing a low bit from the head of the stream, it continues to recursively parse the encoding of the left subtree followed by the right subtree, sequencing the applicative actions with liftA2. The trick is that node fails if it doesn't encounter a low bit at the head of the input stream, which tells <|> to give up on node and try leaf instead.
Note how the structure of tree reflects the structure of the Tree type itself. This is applicative parsing at work. We could alternately have structured this parser monadically, first using one to parse an arbitrary bit and then using a case analysis on the bit to determine whether we should continue to parse a pair of trees or a leaf. In my opinion this version is simpler, more declarative, and less verbose.
Also compare the clarity of this code to the low-level style of #behzad.nouri's foldr-based solution. Rather than building an explicit finite-state machine which switches between parsing nodes and leaves - an imperative-flavoured idea - my design allows you to declaratively describe the grammar to the machine using standard functions like liftA2 and <|> and trust that the abstractions will do the right thing.
Anyway, here I'm parsing a simple tree consisting of a pair of Leafs containing the (binary-encoded) numbers 0 and 1. As you can see, it returns the single successful parse and an empty stream of remaining bits.
ghci> runParser tree $ map (>0) [0, 1, 0,0,0,0,0,0,0, 1, 0,0,0,0,0,0,1]
[(Node (Leaf (False, False, False, False, False, False, False)) (Leaf (False, False, False, False, False, False, True)),[])]
Ok, here's a simple (ad-hoc, but easier to understand) way.
We need to buid a function parse, with the following type:
parse :: [Int] -> Tree Char
The approach you mentioned, with stacks, is the imperative one. Here we just lay on the recursive calls. The stack will be built by the compiler and it will just have each recursive call stored in it (At least you can imagine it that way, if you want, or just ignore all this paragraph).
So, the idea is the following: whenever you find a 0, you need to make two recursive calls to the algorithm. The first recursive call will read one branch (the left one) of the tree. The second one needs to be called with the rest of the list as argument. The rest left by the first recursive call. So, we need a auxiliar function parse' with the following type (now we return a pair, being the second value the rest of list):
parse' :: [Int] -> (Tree Char, [Int])
Next, you can see a piece of code where the 0 case is just as described before.
For the 1 case, we just need to take the next 7 numbers and make them into a char somehow (I leave the definition of toChar for you), then, just return a Leaf and the rest of the list.
parse' (0:xs) = let (l, xs') = parse' xs
(r, xs'') = parse' xs' in (Node 0 l r, xs'') --xs'' should be []
parse' (1:xs) = let w = toChar (take 7 xs) in (Leaf 0 w , drop 7 xs)
Finally, our parse function just calls the auxiliary parse one and returns the first element of the pair.
parse xs = fst $ parse' xs
do a right fold:
import Data.Char (chr)
data Tree a = Leaf a | Node (Tree a) (Tree a)
deriving Show
build :: [Int] -> [Tree Char]
build xs = foldr go (\_ _ -> []) xs 0 0
where
nil = Leaf '?'
go 0 run 0 0 = case run 0 0 of
[] -> Node nil nil:[]
x:[] -> Node x nil:[]
x:y:zs -> Node x y :zs
go 1 run 0 0 = run 0 1
go _ _ _ 0 = error "this should not happen!"
go x run v 7 = (Leaf $ chr (v * 2 + x)): run 0 0
go x run v k = run (v * 2 + x) (k + 1)
then:
\> head $ build [0,0,0,1,1,1,0, ...] -- the list of 01s as in the question
Node (Node (Node (Leaf 'k') (Leaf 't'))
(Node (Node (Leaf 'q') (Leaf 'g')) (Leaf 'r')))
(Node (Leaf 'w') (Leaf 'a'))
Given a tree data structure defined as
data Tree = Node Int Tree Tree | Leaf
How can one transform it into a list of values along all paths?
For example Node 1 (Node 2 Leaf Leaf) (Node 3 Leaf Leaf) should translate to [[1,2], [1,3]].
You have a recursive data structure, so you should expect a recursive solution. The first step in such a solution is to identify the base cases. For this problem, there is the obvious base case: Leaf. We probably also want to treat Node x Leaf Leaf as a base case to avoid duplicate paths.
Now let's write down the type signature. This should make it clear what our base cases should produce.
paths :: Tree -> [[Int]]
For Leaf the sensible thing to do is return a list containing an empty list since a Leaf is representing an empty path.
paths Leaf = [[]]
For Node x Leaf Leaf, we can return a list consisting of a list containing x.
paths (Node x Leaf Leaf) = [[x]]
The next part requires the most thought. We need to consider what to do with the non-base case Node x left right. The strategy here is to assume that we have the result of paths left and paths right and then decide what we need to do with x. We're building paths, so we need to tack x onto the front of all the left paths and the right paths. We also need to combine the two lists into a single list.
paths (Node x left right) = map (x:) (paths left ++ paths right)
And that's it. Of course, now you might want to see if there's a more efficient way to implement it, or if there's a common pattern here instead (i.e. can we write this as a fold?).
The answer here is very simple, so for a Tree structure such as the one you provided, if we have:
data Tree = Node Int Tree Tree | Leaf
We would need a nested function within our function, basically a function which returns a list from a branch, this way we can have the first argument of the Tree (the trunk or initial value) separated from values of either of the branches, but I'm sure there is a more efficient implementation, so here it is:
traverse :: Tree a -> [[Int]] -- Do not use "a" in the return type
traverse Leaf = [[]]
traverse (Node value left right) = [value] ++ treeToList left : [value] ++ treeToList right : []
where treeToList Leaf = []
treeToList (Node a left right) = [a] ++ treeToList left ++ treeToList right
returns
> traverse (Node 2 (Node 3 Leaf Leaf) (Node 4 Leaf Leaf))
> [[2,3],[2,4]]
Be careful with the return type as Tree a denotes that a is polymorphic but the constructor Node takes only values of type Int, denoting the returned list can only be of type Int.
I am given the following tree definition and functions:
data Tree a = Node a [Tree a] deriving (Eq, Read, Show)
treeRoot :: Tree a -> a
treeRoot (Node a _) = a
treeSubtrees :: Tree a -> [Tree a]
treeSubtrees (Node _ subtrees) = subtrees
I need to create a function 'nodesAtLevel' that takes two arguments: a tree and an integer n >= 0. The function needs to return a list of all the nodes at the given level n. The root of the tree is level 0. I am very new to Haskell, and yes, this is part of a homework assignment, so if you could help walk me through the thought process of completing this, it would be greatly appreciated! I currently have the definition of the 'nodesAtLevel' function written as follows:
nodesAtLevel :: Int -> Tree a -> [a]
Ok, let's to this step by step (leaving you with some holes for now):
nodes at level 0
as I understand it you are suppost to only return the roots value here (of course in a list)
so what goes in the ... here?
nodesAtLevel 0 (Node a subtrees) = ...
nodes at deeper levels
well the structure is nicely recursive so we probably want to use recursion.
So let's go recursively deeper one level deeper (decreasing the way we have left to go - aka our n)
But there is a slight problem: nodesAtLevel acts on a single node but we only have a list of nodes left (the subtrees) .. so what to do?
Well maybe we should do something for each of the subtrees/subnodes - so we need to find the right function f here (hint you probably want to map and concat the results ...):
nodesAtLevel n (Node a subtrees) = f (nodesAtLevel (n-1)) subtrees
what can that f be? Can you guess it? Maybe you can write it yourself if not?
Additional Hint:
maybe you should first find out what type f has - because then you might be even able to use Hoogle to find a good fit.
If you use a newer GHC version you an let the compiler do the work if you write
nodesAtLevel n (Node _ subtrees) = _f (nodesAtLevel (n-1)) subtrees
where _f is a hole - now if you load this in GHCi it will give you a
Found hole â_fâ with type: ....
error with lot's of additional information ;)
so just find ... and f and this should work ;)
BTW you can use the functions you already have instead of pattern matching again as I did, but I feel it's easier to see the result this way - so if you follow this path you don't need to use treeSubtrees or treeRoot
solution
... = [a]
f = concatMap
so one possible way to do it is this:
nodesAtLevel :: Int -> Tree a -> [a]
nodesAtLevel 0 (Node a _) = [a]
nodesAtLevel n (Node _ subtrees) = concatMap (nodesAtLevel (n-1)) subtrees
i have the following type:
data Tree a = Empty |
Branch { key :: a,
balance :: Int8,
left :: Tree a,
right :: Tree a,
up :: Bool --used internally to stop updating balance
}
deriving (Eq)
and a function that matches the following pattern:
roll (Branch y (-2) l (Branch ry 1 (Branch rly 0 Empty Empty _) rr _) _) = ...
even though Empty Empty inside (Branch rly 0 Empty Empty _) is the only possible case, i was wondering - will generalizing the form to :
roll (Branch y 2 (Branch ly (-1) ll (Branch lry 0 lrl lrr _) _) r _) = ...
work faster (even negligibly) because runtime doesn't need to match lrl and lrr to Empty ?
It might yield a very tiny speed increase - you would have to benchmark it properly to know for sure. (If you're not going to look at lrl or lrr, you might as well use _ instead.)
My personal recommendation would be to leave the explicit Empty patterns in there. You say "there is no other possibility", but having this documented in the code becomes very helpful in the unlikely event that you are in fact mistaken. ;-)
(It may also affect the overall strictness/laziness of your program - but that's an entire other discussion...)
Yes, it will be faster. If its worth it, only benchmarking can tell.