Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
pp:2025:scala:l03 [2025/03/16 00:06]
cata_chiru
pp:2025:scala:l03 [2025/03/28 12:04] (current)
cata_chiru
Line 3: Line 3:
 ===== 3.1 Abstract Lists ===== ===== 3.1 Abstract Lists =====
  
-Below you will find the algebraic definition of the datatype ''​IList'':​+Belowyou will find the algebraic definition of the datatype ''​IList'':​
 <​code>​ <​code>​
 Void : IList Void : IList
Line 9: Line 9:
 </​code>​ </​code>​
  
-This definition has already been implemented in Scala, below. Please copy-paste this definition in your worksheet.+This definition has already been implemented in Scala, ​as shown below. Please copy-paste this definition in your worksheet.
 <code scala> <code scala>
 trait IList  trait IList 
Line 23: Line 23:
 </​code>​ </​code>​
 Implement ''​isEmpty''​ in Scala: Implement ''​isEmpty''​ in Scala:
 +
 +''​! Hint:''​ To pattern match the list l as a Void or a Cons use the keyword ''​match''​ from Scala :
 <code scala> <code scala>
-def isEmpty(l: IList) : Boolean = ???+def isEmpty(l: IList) : Boolean = 
 +    l match { 
 +        case Void => ??? 
 +        case Cons(x, xs) => ??? 
 +    } 
 +}
 </​code>​ </​code>​
 +
  
 **3.1.2.** Write down axioms for ''​size : IList -> Int''​ and implement the operator in Scala: **3.1.2.** Write down axioms for ''​size : IList -> Int''​ and implement the operator in Scala:
Line 32: Line 40:
 </​code>​ </​code>​
  
-**3.1.3.** Implement ''​contains'' ​which checks ​if an element is a member of a list.+**3.1.3.** Implement ''​contains'' ​to check if an element is a member of a list.
 <code scala> <code scala>
 def contains(e: Int, l: IList) : Boolean = ??? def contains(e: Int, l: IList) : Boolean = ???
Line 95: Line 103:
  
 case class Node(left: BinaryTree, info: Int, right: BinaryTree) extends BinaryTree { case class Node(left: BinaryTree, info: Int, right: BinaryTree) extends BinaryTree {
-    ​override def toString: String = { +  ​override def toString: String = { 
-        def prettyPrint(tree: BinaryTree, ​depthInt): String = { +    def printTree( 
-            tree match { +                   tree: BinaryTree, 
-                case TVoid => tree.toString() +                   ​prefixString = "",​ 
-                case Node(l, value, r) => +                   ​isLeft:​ Boolean = true 
-                    "\t" ​* (depth ​1) + value.toString() + "​\n" ​+ +                 ): String = 
-                    ​prettyPrint(l, depth+1) + prettyPrint(r,​ depth+1) +      tree match { 
-            } +        case TVoid => 
-        ​}+          ""​ 
 +        ​case Node(l, value, r) => 
 +          val rightStr = 
 +            printTree(r,​ prefix + (if (isLeft && prefix.nonEmpty) ​"│   " ​else " ​   "), isLeft = false) 
 +          val nodeStr = 
 +            prefix ​(if (tree != this) if (isLeft) "​└── " else "​┌── " else " ​   ") + value.toString + "​\n"​ 
 +          val leftStr = 
 +            printTree(l, prefix ​(if (isLeft" ​   " else "​│ ​  "​)) 
 +          rightStr ​nodeStr ​leftStr 
 +      }
  
-        prettyPrint(this, 0+    '​\n'​ + printTree(this) 
-    }+  }
 } }
 </​code>​ </​code>​
  
-A Binary Tree can either be a void object (equivalent to NULL in C), or a Node with its information as an Int and two other trees as children (left and right).+A Binary Tree can either be a TVoid object (equivalent to NULL in C), or a Node with its information as an Int and two other trees as children (left and right).
  
-**3.2.0.** Implement ''​leaf_node''​ that receives an Integer ​and returns a leaf with that integer as value:+**3.2.0.** Implement ''​leaf_node''​ that receives an Int and returns a leaf with that integer as the node'​s ​value:
 <code scala> <code scala>
 def leaf_node(value : Int) : BinaryTree = ??? def leaf_node(value : Int) : BinaryTree = ???
Line 120: Line 137:
 <code scala> <code scala>
 val arborica = Node(Node(leaf_node(-1),​ 5, TVoid), 1, Node(leaf_node(4),​ 2, Node(leaf_node(3),​ 6, leaf_node(7)))) val arborica = Node(Node(leaf_node(-1),​ 5, TVoid), 1, Node(leaf_node(4),​ 2, Node(leaf_node(3),​ 6, leaf_node(7))))
-</​code>​ 
- 
-and the following print function 
-<code scala> 
-TBD 
 </​code>​ </​code>​
  
Line 131: Line 143:
 **3.2.1.** Implement ''​mirror''​ that mirrors the tree structure: **3.2.1.** Implement ''​mirror''​ that mirrors the tree structure:
 <code scala> <code scala>
-def mirror(t: BinaryTree) : BinaryTree = ???+def mirror(tree: BinaryTree) : BinaryTree = ???
 </​code>​ </​code>​
-  ​ 
--- 6. Implement the function flatten: ​ 
-flatten :: Tree a -> List a 
-flatten TVoid = GVoid 
-flatten (Node l k r) = app (GenCel k (flatten l)) (flatten r) 
--- flatten (Node l k r) = app (GenCel k (flatten l)) (flatten r) 
  
--- 7Define ​list concatenation over type List a:  +**3.2.1.** Implement ''​flatten''​ that squashes the tree traversed in preorder into a list: 
-app :: (List a) -> (List a-> (List a) +<code scala> 
-app GVoid GVoid GVoid +def flatten(tree: BinaryTree)List[Int] ??? 
-app l1 GVoid = l1 +</​code>​
-app GVoid l2 = l2 +
-app (GenCel val pointer) l2 = GenCel val (app pointer l2)+
  
--- 8. Define the function tmap which is the Tree a correspondent to map::​(a→b) → [a] → [b].  +**3.2.2.** ​Define the function ​''​tmap'' ​which is the Tree a correspondent to map::​(a→b) → [a] → [b].  
-tmap:: (a->b) -> (Tree a) -> (Tree b) +<code scala
-tmap f TVoid TVoid +def tmap(f: Int => Int, tree: BinaryTree: BinaryTree ​??? 
-tmap f (Node l k r) = Node (tmap f l) (f k) (tmap f r)+</​code>​
  
--- 10. Define the function tfoldr: ​ +**3.2.3.** ! Define the function ​''​tfoldr'',​ equivalent of foldr for treesfoldr :: (a -> b -> b) -> b -> Tree a -> b 
-tfoldr ​:: (a -> b -> b) -> b -> Tree a -> b +<code scala> 
-tfoldr f acc TVoid = acc +def tfoldr[B](f(Int, B) => B, acc: B, tree: BinaryTree):​ B = ??? 
-tfoldr f acc (Node l k r) = tfoldr ​(tfoldr f (f k accl) r+</​code>​ 
 + 
 +**3.2.4.** ! Implement the ''​flattening''​ function using tfoldr. The order of squashing the tree does not necessarily need to match the previous exercise:  
 +<code scala> 
 +def flattening(tree: BinaryTree): List[Int] = ??? 
 +</​code>​
  
--- 11. Implement the flattening function using tfoldr: ​ 
-flattening :: Tree a -> List a 
-flattening (Node l k r) = tfoldr GenCel GVoid (Node l k r)