Advertisement
Tetrikitty

lab02

Oct 6th, 2018
40
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. module Lab02 where
  2. import           Control.Monad (join)
  3. import qualified Data.List     as L
  4. import           Prelude       hiding (product, reverse)
  5. import Debug.Trace (trace)
  6. {-|
  7.    Please refer to README.md for submission instructions, and additional
  8.    information.
  9. -}
  10. {-|
  11.    Q1:
  12.    Consider the following implementation of reverse using 'foldr'. It contains a
  13.    bug that causes it to return the wrong result. Can you fix it so that you get
  14.    the following correct outcome?
  15.    > reverse [1, 2, 3]
  16.    [3, 2, 1]
  17.    > reverse [1, 2]
  18.    [2, 1]
  19.    > reverse []
  20.    []
  21. -}
  22. reverse :: [a] -> [a]
  23. reverse xs = foldr (\x acc -> acc ++ [x]) [] xs
  24. {-|
  25.    Q2: List Operaions
  26.    Using only 'map', 'filter', 'foldl' and 'join', write code for the following list
  27.    operations. You may use let constructs to name intermediate computations
  28. -}
  29. {-|
  30.    (a)
  31.    Compute the cross product of 2 lists that returns an element from each list as
  32.    a pair (a, b) using foldl.
  33.    > product [1, 2, 3] ['a', 'b']
  34.    [(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b'), (3, 'a'), (3, 'b')]
  35. -}
  36. product :: [a] -> [b] -> [(a, b)]
  37. product xs ys = foldl (\acc x -> acc ++ (foldl (\acc2 y -> acc2 ++ [(x,y)])) [] ys) [] xs
  38. {-|
  39.    (b)
  40.    Compute the cross product (without using foldl) of 2 lists that returns an integer from each list as
  41.    a pair (a, b), such that a*b > a+b.
  42.    > product2 [1, 2, 3] [2, 7]
  43.    [(3,2),(2,7),(3,7)]
  44. -}
  45. product2 :: [Int] -> [Int] -> [(Int, Int)]
  46. product2 xs ys = filter (\(x,y) -> x * y > x + y) (join (map (\y -> (map (\x -> (x, y)) xs)) ys))
  47. {-|
  48.    (c)
  49.    Compute the divisor from the product of 2 lists, but only if the second
  50.    element is non-zero.
  51.    > divisorProd [5, 9, 4] [2, 0, 3]
  52.    = [5/2,9/2,4/2,5/3,9/3,4/3]
  53.    = [2, 4, 2, 1, 3, 1]
  54. -}
  55. divisorProd :: [Int] -> [Int] -> [Int]
  56. divisorProd xs ys = foldl (\acc y -> acc ++ (foldl (\acc2 x -> if y == 0 then acc2 else acc2 ++ [(x `div `y)])) [] xs) [] ys
  57. {-|
  58.    Q3:
  59.    Write a function that could count the number of positive, negative, and zero
  60.    elements in a list of numbers;
  61.    (i)  using only 'foldr'
  62.    (ii) using only 'filter' and 'length'
  63. -}
  64. countNums1 :: [Int] -> (Int, Int, Int)
  65. countNums1 xs =
  66.   let pos xs = foldr (\x acc -> if x > 0 then acc + 1 else acc) 0 xs
  67.       neg xs = foldr (\x acc -> if x < 0 then acc + 1 else acc) 0 xs
  68.       zer xs = foldr (\x acc -> if x == 0 then acc + 1 else acc) 0 xs
  69.   in (pos xs, neg xs, zer xs)
  70.  
  71. countNums2 :: [Int] -> (Int, Int, Int)
  72. countNums2 xs =
  73.   let pos xs = (length . filter (\x -> x > 0)) xs
  74.       neg xs = (length . filter (\x -> x < 0)) xs
  75.       zer xs = (length . filter (\x -> x == 0)) xs
  76.   in (pos xs, neg xs, zer xs)
  77. {-|
  78.    Q4: Higher-Order functions for trees
  79.    We can implement 2 common higher-order functions, mapTree and foldTree, on
  80.    simple binary trees, as shown below. Use these two higher order functions to
  81.    complete the subsequent questions on binary trees.
  82. -}
  83. data Tree a
  84.    = Leaf a
  85.    | Node a (Tree a) (Tree a)
  86.    deriving Show
  87. t1 :: Tree Int
  88. t1 = Node 3 (Leaf 1) (Leaf 2)
  89. t2 :: Tree Int
  90. t2 = Node 4 t1 (Leaf 6)
  91. t3 :: Tree Int
  92. t3 = Node 5 t2 (Leaf 3)
  93. instance Functor Tree where
  94.    fmap f t =
  95.      case t of
  96.        Leaf v ->
  97.          Leaf (f v)
  98.        Node v leftTree rightTree ->
  99.          Node (f v) (fmap f leftTree) (fmap f rightTree)
  100. mapTree :: (a -> b) -> Tree a -> Tree b
  101. mapTree = fmap
  102. foldTree :: (a -> b) -> (a -> b -> b -> b) -> Tree a -> b
  103. foldTree fLeaf _ (Leaf v) = fLeaf v
  104. foldTree fLeaf fNode (Node v leftTree rightTree) =
  105.    fNode v leftRes rightRes
  106.    where
  107.      leftRes = foldTree fLeaf fNode leftTree
  108.      rightRes = foldTree fLeaf fNode rightTree
  109. {-|
  110.    (a)
  111.    Write a function that would add n to every element of a tree.
  112.    > t1
  113.    Node 3 (Leaf 1) (Leaf 2)
  114.    > addN 3 t1
  115.    Node 6 (Leaf 4) (Leaf 5)
  116. -}
  117. addN ::Int -> Tree Int -> Tree Int
  118. addN n t = mapTree (\x -> x + n) t
  119. {-|
  120.    (b)
  121.    Write a function that would return the left most element of a tree
  122.    > t2
  123.    Node 4 (Node 3 (Leaf 1) (Leaf 2)) (Leaf 6)
  124.    > leftMost t2
  125.    1
  126.    > t3
  127.    Node 5 (Node 4 (Node 3 (Leaf 1) (Leaf 2)) (Leaf 6)) (Leaf 3)
  128.    > leftMost t3
  129.    1
  130. -}
  131. leftMost :: Tree a -> a
  132. leftMost t = foldTree (\x -> x) (\x y z -> y) t
  133. {-|
  134.    (c)
  135.    Write a function that would mirror a tree aound its root element, i.e., a
  136.    tree with its left and right subtrees recursively flipped.
  137.    > t2
  138.    Node 4 (Node 3 (Leaf 1) (Leaf 2)) (Leaf 6)
  139.    > mirrorTree t2
  140.    Node 4 (Leaf 6) (Node 3 (Leaf 2) (Leaf 1))
  141. -}
  142. mirrorTree :: Tree a -> Tree a
  143. mirrorTree t = foldTree (\x -> Leaf x) (\x y z -> Node x z y) t
  144. t4 :: Tree Char
  145. t4 = Node 'a' (Leaf 'b') (Node 'c' (Leaf 'e') (Leaf 'f'))
  146. {-|
  147.    (d)
  148.    Write a function that would tag each element of a tree with the size of its
  149.    subtree.
  150.    > t4
  151.    Node 'a' (Leaf 'b') (Node 'c' (Leaf 'e') (Leaf 'f'))
  152.    > addSize t4
  153.    Node (5, 'a') (Leaf (1, 'b')) (Node (3, 'c') (Leaf (1, 'e')) (Leaf (1, 'f')))
  154. -}
  155. addSize :: Tree a -> Tree (Int, a)
  156. addSize t =
  157.   let val (Node x _ _) = x
  158.       val (Leaf x)     = x
  159.   in foldTree (\x -> Leaf (1, x)) (\x y z -> Node (1 + (fst (val y)) + (fst (val z)), x) y z) t
  160. {-|
  161.    (e)
  162.    Write a function to check if a tree of integers is a binary search tree, i.e.,
  163.    a tree where all the elements in the left subtree are strictly smaller than
  164.    the root node, which is, in turn, smaller than or equal to all the elements
  165.    of the right subtree.
  166.    > t1
  167.    Node 3 (Leaf 1) (Leaf 2)
  168.    > checkBST t1
  169.    False
  170.    > t5
  171.    Node 2 (Leaf 1) (Leaf 3)
  172.    > checkBST t5
  173.    True
  174. -}
  175. t5 :: Tree Int
  176. t5 = Node 2 (Leaf 1) (Leaf 3)
  177. checkBST :: Tree Int -> Bool
  178. checkBST t =
  179.   let val (Node x _ _) = x
  180.       val (Leaf x)     = x
  181.   in fst (val (foldTree (\x -> Leaf (True, x)) (\x y z -> Node ((fst (val y)) && (fst (val z)) && snd (val y) < x && x < snd (val z), x) y z) t))
  182. {-|
  183.    Q5:
  184.    The 'foldTree' operation uses tree recursion.
  185.    Let us write a different tree folding operation that works with the help of
  186.    an accumulating parameter that would be similar to 'foldr'.
  187.    An example of this which uses postorder traversal is given below.
  188.    (a) Count the number of elements in a tree using 'foldTreePostorder'
  189.    > t4
  190.    Node 'a' (Leaf 'b') (Node 'c' (Leaf 'e') (Leaf 'f'))
  191.    > countTree t4
  192.    5
  193.    (b) Compare 'foldTreePostorder' with 'foldTree'. Can one be implemented in
  194.        terms of the other, or are they incomparable?
  195.    They are incomparable.
  196. -}
  197. foldTreePostorder :: Show a => (a -> b -> b) -> Tree a -> b -> b
  198. foldTreePostorder f (Leaf v) acc = f v acc
  199. foldTreePostorder f (Node v leftTree rightTree) acc =
  200.    foldTreePostorder f leftTree z2
  201.    where
  202.      z1 = foldTreePostorder f rightTree acc
  203.      z2 = f v z1
  204. countTree :: Show a => Tree a -> Int
  205. countTree t = foldTreePostorder (\v acc -> acc + 1) t 0
  206. {-|
  207.    Q6: Pretty printers
  208.    Consider the binary tree defined earlier.
  209.    You have been given a higher-order printer, 'showTree', that returns a tree as
  210.    a string (prints a tree) in prefix form. For example, the tree 't2' would be:
  211.    Node 4
  212.    Node 3
  213.    Leaf 1
  214.    Leaf 2
  215.    Node 3
  216.    Leaf 1
  217.    Leaf 2
  218.    (i) The above pretty printing is not very readable; provide a neater pretty
  219.         printer in 'showTree2' that would provide space indentation to represent
  220.         the depth of each subtree.
  221.         > showTree2 t2
  222.         Node 4
  223.           Node 3
  224.             Leaf 1
  225.             Leaf 2
  226.           Node 3
  227.             Leaf 1
  228.             Leaf 2
  229.    (ii) We can also print a tree in infix form. Complete the 'showTreeInfix'
  230.         function to allow binary trees to be printed in infix order.
  231.          > showTreeInfix t2
  232.              Leaf 1
  233.            Node 3
  234.              Leaf 2
  235.          Node 4
  236.              Leaf 1
  237.            Node 3
  238.              Leaf 2
  239. -}
  240. showTree :: Show a => Tree a -> String
  241. showTree (Leaf v) = "Leaf " ++ show v ++ "\n"
  242. showTree (Node v leftTree rightTree) =
  243.    "Node " ++ show v ++ "\n" ++
  244.    showTree leftTree ++
  245.    showTree rightTree
  246.  
  247. showTree2 :: Show a => Tree a -> String
  248. showTree2 t =
  249.    let pad 0 = ""
  250.        pad n = "  " ++ pad (n-1)
  251.        sho (Leaf v) n = (pad n) ++ "Leaf " ++ show v ++ "\n"
  252.        sho (Node v leftTree rightTree) n = (pad n) ++ "Node " ++ show v ++ "\n" ++
  253.                                            sho leftTree (n+1) ++
  254.                                            sho rightTree(n+1)
  255.    in sho t 0
  256.  
  257. showTreeInfix :: Show a => Tree a -> String
  258. showTreeInfix t =
  259.    let pad 0 = ""
  260.        pad n = "  " ++ pad (n-1)
  261.        sho (Leaf v) n = (pad n) ++ "Leaf " ++ show v ++ "\n"
  262.        sho (Node v leftTree rightTree) n = sho leftTree (n+1) ++
  263.                                            (pad n) ++ "Node " ++ show v ++ "\n" ++
  264.                                            sho rightTree(n+1)
  265.    in sho t 0
  266. {-|
  267.    Q7: Numbered Lists
  268.    We have our own printer for lists in 'showList', which prints a list as a
  269.    comma separated string of its elements, surrounded by square brackets
  270.    > showList ls
  271.    "[\"This\", \"is\", \"a\", \"numbered\", \"list\"]"
  272.    Give a list printer that would number each element of a given list and print
  273.    it.
  274.    > showListNum ", " ls
  275.    "[(1)\"This\", (2)\"is\", (3)\"a\", (4)\"numbered\", (5)\"list\"]"
  276.    You may make use of the addNum function below which adds a number to each
  277.    element of a list.
  278. -}
  279. showList :: Show a => [a] -> String
  280. showList xs = "[" ++ L.intercalate ", " (map show xs) ++ "]"
  281. addNum :: [a] -> [(Int, a)]
  282. addNum xs =
  283.    let
  284.      aux [] _       = []
  285.      aux (y : ys) n = (n, y) : aux ys (n + 1)
  286.    in
  287.      aux xs 1
  288. ls :: [String]
  289. ls = ["This", "is", "a", "numbered", "list"]
  290. showListNum :: Show a => String -> [a] -> String
  291. showListNum separator l =
  292.   let format (x, y) = "(" ++ show x ++ ")" ++ show y ++ ""
  293.   in "[" ++ L.intercalate separator (map format (addNum l)) ++ "]"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement