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:l05 [2025/03/30 22:12] ldaniel |
pp:2025:scala:l05 [2025/04/04 15:09] (current) tpruteanu |
||
---|---|---|---|
Line 53: | Line 53: | ||
Given the implementation of binary trees from the previous lab: | Given the implementation of binary trees from the previous lab: | ||
<code scala> | <code scala> | ||
- | trait BinaryTree { | + | trait BTree |
- | override def toString: String = super.toString: String | + | |
- | } | + | |
- | case object TVoid extends BinaryTree { | + | case object TVoid extends BTree |
- | override def toString: String = "-" | + | |
+ | case class Node(left: BTree, info: Int, right: BTree) extends BTree | ||
+ | |||
+ | def leaf_node(value : Int) : BTree = { | ||
+ | Node(TVoid, value, TVoid) | ||
} | } | ||
- | case class Node(left: BinaryTree, info: Int, right: BinaryTree) extends BinaryTree { | + | object BTreePrinter { |
- | override def toString: String = { | + | case class PrintInfo(len: Int, center: Int, text: List[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) | + | def pp(tree: BTree): PrintInfo = tree match { |
+ | case TVoid => PrintInfo(3, 2, List("Nil")) | ||
+ | |||
+ | case Node(left, value, right) => | ||
+ | val strValue = value.toString | ||
+ | val ppL = pp(left) | ||
+ | val ppR = pp(right) | ||
+ | val nlen = ppL.len + ppR.len + 1 | ||
+ | val ncenter = ppL.len + 1 | ||
+ | |||
+ | require(strValue.length <= nlen, "Nice try") | ||
+ | |||
+ | val alignedX = " " * (ncenter - (strValue.length / 2) - 1) + strValue | ||
+ | val centerLine = " " * (ncenter - 1) + "|" | ||
+ | val dottedLine = " " * (ppL.center - 1) + "-" * (nlen - ppL.center - (ppR.len - ppR.center + 1) + 2) | ||
+ | val downLines = " " * (ppL.center - 1) + "|" + " " * (nlen - ppL.center - (ppR.len - ppR.center +1)) + "|" | ||
+ | |||
+ | val combinedLines = zipPad("",(l, r) => l ++ (" " * (ppL.len - l.size + 1 )) ++ r, ppL.text, ppR.text) | ||
+ | |||
+ | PrintInfo(nlen, ncenter, alignedX :: centerLine :: dottedLine :: downLines :: combinedLines) | ||
} | } | ||
+ | def zipPad[A](pad: A, f: (A, A) => A, left: List[A], right: List[A]): List[A] = (left, right) match { | ||
+ | case (Nil, Nil) => Nil | ||
+ | case (x :: xs, Nil) => x :: zipPad(pad, f, xs, List(pad)) | ||
+ | case (Nil, y :: ys) => f(pad, y) :: zipPad(pad, f, List(pad), ys) | ||
+ | case (x :: xs, y :: ys) => f(x, y) :: zipPad(pad, f, xs, ys) | ||
+ | } | ||
+ | |||
+ | def printTree(tree: BTree): String = "\n" + pp(tree).text.mkString("\n") | ||
} | } | ||
- | def leaf_node(value : Int) : BinaryTree = { | + | extension(t: BTree) { |
- | Node(TVoid, value, TVoid) | + | def toStringTree: String = BTreePrinter.printTree(t) |
} | } | ||
+ | |||
</code> | </code> | ||
Line 93: | Line 106: | ||
<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)))) | ||
+ | arborica.toStringTree | ||
</code> | </code> | ||