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.
Related
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).
I'm trying to write a function that given a list of numbers, returns a list where every 2nd number is doubled in value, starting from the last element. So if the list elements are 1..n, n-th is going to be left as-is, (n-1)-th is going to be doubled in value, (n-2)-th is going to be left as-is, etc.
So here's how I solved it:
MyFunc :: [Integer] -> [Integer]
MyFunc xs = reverse (MyFuncHelper (reverse xs))
MyFuncHelper :: [Integer] -> [Integer]
MyFuncHelper [] = []
MyFuncHelper (x:[]) = [x]
MyFuncHelper (x:y:zs) = [x,y*2] ++ MyFuncHelper zs
And it works:
MyFunc [1,1,1,1] = [2,1,2,1]
MyFunc [1,1,1] = [1,2,1]
However, I can't help but think there has to be a simpler solution than reversing the list, processing it and then reversing it again. Could I simply iterate the list backwards? If yes, how?
The under reversed f xs idiom from the lens library will apply f to xs in reverse order:
under reversed (take 5) [1..100] => [96,97,98,99,100]
When you need to process the list from the end, usually foldr works pretty well. Here is a solution for you without reversing the whole list twice:
doubleOdd :: Num a => [a] -> [a]
doubleOdd = fst . foldr multiplyCond ([], False)
where multiplyCond x (rest, flag) = ((if flag then (x * 2) else x) : rest, not flag)
The multiplyCond function takes a tuple with a flag and the accumulator list. The flag constantly toggles on and off to track whether we should multiply the element or not. The accumulator list simply gathers the resulting numbers. This solution may be not so concise, but avoids extra work and doesn't use anything but prelude functions.
myFunc = reverse
. map (\(b,x) -> if b then x*2 else x)
. zip (cycle [False,True])
. reverse
But this isn't much better. Your implementation is sufficiently elegant.
The simplest way to iterate the list backwards is to reverse the list. I don't think you can really do much better than that; I suspect that if you have to traverse the whole list to find the end, and remember how to get back up, you might as well just reverse it. If this is a big deal, maybe you should be using some other data structure instead of lists—Vector or Seq might be good choices.
Another way to write your helper function is to use Traversable:
import Control.Monad.State
import Data.Traversable (Traversable, traverse)
toggle :: (Bool -> a -> b) -> a -> State Bool b
toggle f a =
do active <- get
put (not active)
return (f active a)
doubleEvens :: (Num a, Traversable t) => t a -> t a
doubleEvens xs = evalState (traverse (toggle step) xs) False
where step True x = 2*x
step False x = x
yourFunc :: Num a => [a] -> [a]
yourFunc = reverse . doubleEvens
Or if we go a bit crazy with Foldable and Traversable, we can try this:
Use Foldable's foldl to extract a reverse-order list from any of its instances. For some types this will be more efficient than reversing a list.
Then we can use traverse and State to map each element of the original structure to its counterpart in the reversed order.
Here's how to do it:
import Control.Monad.State
import Data.Foldable (Foldable)
import qualified Data.Foldable as F
import Data.Traversable (Traversable, traverse)
import Data.Map (Map)
import qualified Data.Map as Map
toReversedList :: Foldable t => t a -> [a]
toReversedList = F.foldl (flip (:)) []
reverse' :: Traversable t => t a -> t a
reverse' ta = evalState (traverse step ta) (toReversedList ta)
where step _ = do (h:t) <- get
put t
return h
yourFunc' :: (Traversable t, Num a) => t a -> t a
yourFunc' = reverse' . doubleEvens
-- >>> yourFunc' $ Map.fromList [(1, 1), (2, 1), (3, 1), (4, 1)]
-- fromList [(1,2),(2,1),(3,2),(4,1)]
-- >>> yourFunc' $ Map.fromList [(1, 1), (2, 1), (3, 1)]
-- fromList [(1,1),(2,2),(3,1)]
There's probably a better way to do this, though...
func xs = zipWith (*) xs $ reverse . (take $ length xs) $ cycle [1,2]
I'm new to F# and would like to know how to convert a simple integer list into a tree.
let lst =[1;2;3;4]
type Tree=
|Leaf of int
|Node Tree * Tree
list should convert to tree like this ---> Leaf 1,Node(Leaf 2),Node(Node(Leaf 3,Leaf 4))
The output that you want to get in your answer is a bit poorly formatted, but my interpretation is that you are trying to build a balanced binary tree. To do this recursively, you need to split the input list in two halves and then recursively build tree from the left and the right halves.
This is a bit tricky, because splitting a functional list in halves is not that simple. In practice, you could probably turn your data into an array and use that, but if you want a functional solution you can use:
type Tree = Leaf of int | Node of Tree * Tree
let rec half marker acc xs =
match xs, marker with
| x::xs, _::_::marker -> half marker (x::acc) xs
| x::xs, _::[] -> List.rev (x::acc), xs
| xs, _ -> List.rev acc, xs
The trick in the half function is that it iterates over the list and keeps two copies of the list. From one (called marker), it takes two elements at each step and so by the time this list is empty, you have reached the middle of the original list where we take just one element at each step.
Now you can write a simple recursive function to build a tree
let rec makeTree = function
| [] -> failwith "Does not work on empty lists"
| [x] -> Leaf x
| xs -> let l, r = half xs [] xs
Node(makeTree l, makeTree r)
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