Files
haskell/exercises/Set5b.hs
T
2025-12-24 13:31:32 +02:00

222 lines
7.4 KiB
Haskell

-- Exercise set 5b: playing with binary trees
module Set5b where
import Mooc.Todo
-- The next exercises use the binary tree type defined like this:
data Tree a = Empty | Node a (Tree a) (Tree a)
deriving (Show, Eq)
------------------------------------------------------------------------------
-- Ex 1: implement the function valAtRoot which returns the value at
-- the root (top-most node) of the tree. The return value is Maybe a
-- because the tree might be empty (i.e. just a Empty)
valAtRoot :: Tree a -> Maybe a
valAtRoot (Node t _ _) = Just t
valAtRoot Empty = Nothing
------------------------------------------------------------------------------
-- Ex 2: compute the size of a tree, that is, the number of Node
-- constructors in it
--
-- Examples:
-- treeSize (Node 3 (Node 7 Empty Empty) Empty) ==> 2
-- treeSize (Node 3 (Node 7 Empty Empty) (Node 1 Empty Empty)) ==> 3
treeSize :: Tree a -> Int
treeSize (Node _ t1 t2) = 1 + (treeSize t1) + (treeSize t2)
treeSize Empty = 0
------------------------------------------------------------------------------
-- Ex 3: get the largest value in a tree of positive Ints. The
-- largest value of an empty tree should be 0.
--
-- Examples:
-- treeMax Empty ==> 0
-- treeMax (Node 3 (Node 5 Empty Empty) (Node 4 Empty Empty)) ==> 5
treeMax :: Tree Int -> Int
treeMax (Node value t1 t2) = if value >= max (treeMax t1) (treeMax t2) then value else if treeMax t1 > treeMax t2 then treeMax t1 else treeMax t2
treeMax Empty = 0
------------------------------------------------------------------------------
-- Ex 4: implement a function that checks if all tree values satisfy a
-- condition.
--
-- Examples:
-- allValues (>0) Empty ==> True
-- allValues (>0) (Node 1 Empty (Node 2 Empty Empty)) ==> True
-- allValues (>0) (Node 1 Empty (Node 0 Empty Empty)) ==> False
allValues :: (a -> Bool) -> Tree a -> Bool
allValues condition (Node value t1 t2) = if condition value then allValues condition t1 && allValues condition t2 else False
allValues condition Empty = True
------------------------------------------------------------------------------
-- Ex 5: implement map for trees.
--
-- Examples:
--
-- mapTree (+1) Empty ==> Empty
-- mapTree (+2) (Node 0 (Node 1 Empty Empty) (Node 2 Empty Empty))
-- ==> (Node 2 (Node 3 Empty Empty) (Node 4 Empty Empty))
mapTree :: (a -> b) -> Tree a -> Tree b
mapTree f (Node value t1 t2) = Node (f value) (mapTree f t1) (mapTree f t2)
mapTree f Empty = Empty
------------------------------------------------------------------------------
-- Ex 6: given a value and a tree, build a new tree that is the same,
-- except all nodes that contain the value have been removed. Also
-- remove the subnodes of the removed nodes.
--
-- Examples:
--
-- 1 1
-- / \ ==> \
-- 2 0 0
--
-- cull 2 (Node 1 (Node 2 Empty Empty)
-- (Node 0 Empty Empty))
-- ==> (Node 1 Empty
-- (Node 0 Empty Empty))
--
-- 1 1
-- / \ \
-- 2 0 ==> 0
-- / \
-- 3 4
--
-- cull 2 (Node 1 (Node 2 (Node 3 Empty Empty)
-- (Node 4 Empty Empty))
-- (Node 0 Empty Empty))
-- ==> (Node 1 Empty
-- (Node 0 Empty Empty)
--
-- 1 1
-- / \ \
-- 0 3 ==> 3
-- \ \
-- 2 0
--
-- cull 0 (Node 1 (Node 0 Empty
-- (Node 2 Empty Empty))
-- (Node 3 Empty
-- (Node 0 Empty Empty)))
-- ==> (Node 1 Empty
-- (Node 3 Empty Empty))
cull :: Eq a => a -> Tree a -> Tree a
cull val (Node value t1 t2)
| val == value = Empty
| otherwise = Node value (cull val t1) (cull val t2)
cull val Empty = Empty
------------------------------------------------------------------------------
-- Ex 7: check if a tree is ordered. A tree is ordered if:
-- * all values to the left of the root are smaller than the root value
-- * all of the values to the right of the root are larger than the root value
-- * and the left and right subtrees are ordered.
--
-- Hint: allValues will help you here!
--
-- Examples:
-- 1
-- / \ is ordered:
-- 0 2
-- isOrdered (Node 1 (Node 0 Empty Empty)
-- (Node 2 Empty Empty)) ==> True
--
-- 1
-- / \ is not ordered:
-- 2 3
-- isOrdered (Node 1 (Node 2 Empty Empty)
-- (Node 3 Empty Empty)) ==> False
--
-- 2
-- / \
-- 1 3 is not ordered:
-- \
-- 0
-- isOrdered (Node 2 (Node 1 Empty
-- (Node 0 Empty Empty))
-- (Node 3 Empty Empty)) ==> False
--
-- 2
-- / \
-- 0 3 is ordered:
-- \
-- 1
-- isOrdered (Node 2 (Node 0 Empty
-- (Node 1 Empty Empty))
-- (Node 3 Empty Empty)) ==> True
isOrdered :: Ord a => Tree a -> Bool
isOrdered (Node val t1 t2)
| allValues (val>) t1 && allValues (val<) t2 = isOrdered t1 && isOrdered t2
| otherwise = False
isOrdered Empty = True
------------------------------------------------------------------------------
-- Ex 8: a path in a tree can be represented as a list of steps that
-- go either left or right.
data Step = StepL | StepR
deriving (Show, Eq)
-- Define a function walk that takes a tree and a list of steps, and
-- returns the value at that point. Return Nothing if you fall of the
-- tree (i.e. hit a Empty).
--
-- Examples:
-- walk [] (Node 1 (Node 2 Empty Empty) Empty) ==> Just 1
-- walk [StepL] (Node 1 (Node 2 Empty Empty) Empty) ==> Just 2
-- walk [StepL,StepL] (Node 1 (Node 2 Empty Empty) Empty) ==> Nothing
walk :: [Step] -> Tree a -> Maybe a
walk (step:steps) (Node a t1 t2) = case step of
StepL -> walk steps t1
StepR -> walk steps t2
walk [] (Node a _ _) = Just a
walk _ Empty = Nothing
------------------------------------------------------------------------------
-- Ex 9: given a tree, a path and a value, set the value at the end of
-- the path to the given value. Since Haskell datastructures are
-- immutable, you'll need to build a new tree.
--
-- If the path falls off the tree, do nothing.
--
-- Examples:
-- set [] 1 (Node 0 Empty Empty) ==> (Node 1 Empty Empty)
-- set [StepL,StepL] 1 (Node 0 (Node 0 (Node 0 Empty Empty)
-- (Node 0 Empty Empty))
-- (Node 0 Empty Empty))
-- ==> (Node 0 (Node 0 (Node 1 Empty Empty)
-- (Node 0 Empty Empty))
-- (Node 0 Empty Empty))
--
-- set [StepL,StepR] 1 (Node 0 Empty Empty) ==> (Node 0 Empty Empty)
set :: [Step] -> a -> Tree a -> Tree a
set path val tree = todo
------------------------------------------------------------------------------
-- Ex 10: given a value and a tree, return a path that goes from the
-- root to the value. If the value doesn't exist in the tree, return Nothing.
--
-- You may assume the value occurs in the tree at most once.
--
-- Examples:
-- search 1 (Node 2 (Node 1 Empty Empty) (Node 3 Empty Empty)) ==> Just [StepL]
-- search 1 (Node 2 (Node 4 Empty Empty) (Node 3 Empty Empty)) ==> Nothing
-- search 1 (Node 2 (Node 3 (Node 4 Empty Empty)
-- (Node 1 Empty Empty))
-- (Node 5 Empty Empty)) ==> Just [StepL,StepR]
search :: Eq a => a -> Tree a -> Maybe [Step]
search = todo