Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
pp:2025:scala:l03 [2025/03/15 17:42] 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'': | + | Below, you 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 86: | Line 94: | ||
The type definition for Scala is given below. Please copy-paste this definition in your worksheet. | The type definition for Scala is given below. Please copy-paste this definition in your worksheet. | ||
<code scala> | <code scala> | ||
- | trait BinaryTree | + | trait BinaryTree { |
- | case object TVoid extends BinaryTree | + | override def toString: String = super.toString: String |
- | case class Node(left: BinaryTree, info: Int, right: BinaryTree) extends BinaryTree | + | } |
+ | |||
+ | case object TVoid extends BinaryTree { | ||
+ | override def toString: String = "-" | ||
+ | } | ||
+ | |||
+ | case class Node(left: BinaryTree, info: Int, right: BinaryTree) extends BinaryTree { | ||
+ | override def toString: String = { | ||
+ | def printTree( | ||
+ | tree: BinaryTree, | ||
+ | prefix: String = "", | ||
+ | isLeft: Boolean = true | ||
+ | ): String = | ||
+ | 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 | ||
+ | } | ||
+ | |||
+ | '\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 100: | Line 136: | ||
Being given the following BinaryTree: | Being given the following BinaryTree: | ||
<code scala> | <code scala> | ||
- | val arborica = Node(leaf_node(5), 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 112: | 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) | ||
- | -- 7. Define 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 trees: foldr :: (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 f (tfoldr f (f k acc) l) 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) | ||