Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ikavalio/76890695336738610832f7a2ef9394af to your computer and use it in GitHub Desktop.
Save ikavalio/76890695336738610832f7a2ef9394af to your computer and use it in GitHub Desktop.
object Solution {
def main(args: Array[String]) {
println(
draw(0, 100 / 2, 100, 16, 0, 63, scala.io.StdIn.readInt(), 1, 5).reverseMap(_.mkString).mkString("\n")
)
}
def mergeResult(l1: List[List[Char]], l2: List[List[Char]]): List[List[Char]] =
l1 zip l2 map { p: (List[Char], List[Char]) => p._1 ::: p._2 }
/**
* xStart - x coordinate of leftmost point that belongs to drawer
* xCenter - x coordinate of tree center within bounding box
* xEnd - x coordinate of rightmost point that belong to drawer
* currHeight - size of trunk of tree fragment (size of fragment is twice the size of trunk)
* heightGap - number of already filled rows
* yMax - total number of rows
* visDepth - number of visible levels
* currDepth - current level
* maxDepth - max levels
*/
def draw(xStart: Int, xCenter: Int, xEnd: Int, currHeight: Int, heightGap: Int, yMax: Int, visDepth: Int, currDepth: Int, maxDepth: Int): List[List[Char]] = {
drawTree(xEnd - xStart, xCenter - xStart, currHeight, 2 * currHeight,
if (currDepth == maxDepth) yMax - heightGap - 2 * currHeight else 0, currDepth > visDepth
) ::: (if (currDepth < maxDepth) {
mergeResult(
draw(xStart, xCenter - currHeight, xCenter, currHeight / 2, // left half
heightGap + 2 * currHeight, yMax, visDepth, currDepth + 1, maxDepth),
draw(xCenter, xCenter + currHeight, xEnd, // right half
currHeight / 2, heightGap + 2 * currHeight, yMax, visDepth, currDepth + 1, maxDepth)
)
} else {
Nil
})
}
/**
* width - size of fragment along x coordinate
* posCenter - x coordinate of center of tree
* currHeight - current height of tree's trunk
* yPos - y coordinate iterator of figure (2 * currHeight to 0)
* yGap - number of placeholder lines to draw after tree
* isPlaceholder - if true draw placeholder lines instead of tree
*/
def drawTree(width: Int, posCenter: Int, currHeight: Int, yPos: Int, yGap: Int, isPlaceholder: Boolean): List[List[Char]] = {
if (isPlaceholder) {
yPos match {
case n if n > 0 => ("_" * width).toList :: drawTree(width, posCenter, currHeight, yPos - 1, yGap, isPlaceholder)
case _ =>
yGap match {
case m if m > 0 => ("_" * width).toList :: drawTree(width, posCenter, currHeight, yPos, m - 1, isPlaceholder)
case _ => Nil
}
}
} else {
yPos match {
case n if n > 0 =>
n match {
case tr if tr > currHeight =>
(("_" * (posCenter - 1)) + "1" + ("_" * (width - posCenter))).toList ::
drawTree(width, posCenter, currHeight, yPos - 1, yGap, isPlaceholder)
case br =>
mergeResult(
branch(posCenter - 2, 1, currHeight, isLeft=true),
branch(0, width - posCenter - 1, currHeight, isLeft=false)
) ::: (if (yPos == 1) drawTree(width, posCenter, currHeight, 0, yGap, isPlaceholder=true) else Nil)
}
case _ => Nil
}
}
}
def branch(padLeft: Int, padRight: Int, items: Int, isLeft: Boolean): List[List[Char]] = {
items match {
case 0 => Nil
case _ =>
(("_" * padLeft) + "1" + ("_" * padRight)).toList :: (
if (isLeft) branch(padLeft - 1, padRight + 1, items - 1, isLeft)
else branch(padLeft + 1, padRight - 1, items - 1, isLeft)
)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment