Skip to content

Instantly share code, notes, and snippets.

@JRuumis
Created March 6, 2016 21:19
Show Gist options
  • Select an option

  • Save JRuumis/e4d0f8c5986bb575d9dd to your computer and use it in GitHub Desktop.

Select an option

Save JRuumis/e4d0f8c5986bb575d9dd to your computer and use it in GitHub Desktop.
Resucrive Tree
package hackerrank
/**
* Created by Janis Rumnieks on 06/03/2016.
*/
object GrowthDirection extends Enumeration {
val LEFT, STAY, RIGHT = Value
}
import GrowthDirection._ // kāpēc bez šī nevar ????????
case class Coordinate(x: Int, y: Int) {
def move(direction: GrowthDirection.Value) = direction match {
case LEFT => Coordinate(x-1, y+1)
case STAY => Coordinate(x, y+1)
case RIGHT => Coordinate(x+1, y+1)
}
}
case class Segment(currentStep: Int, totalCurrentSegmentSteps: Int, segmentsLeft: Int) {
def moveStep: Segment = Segment(currentStep+1, totalCurrentSegmentSteps, segmentsLeft)
def changeStepDirection: Segment = Segment(1, totalCurrentSegmentSteps, segmentsLeft)
def createNextSegment: Segment = Segment(1, totalCurrentSegmentSteps/2, segmentsLeft-1)
def isCurrentSegmentDone: Boolean = currentStep == totalCurrentSegmentSteps
def isTreeDone: Boolean = segmentsLeft == 0
}
// Application
object RecursiveTree2 extends App {
def createTreeStep(coord: Coordinate, direction: GrowthDirection.Value, segment: Segment): List[Coordinate] = {
if (!segment.isCurrentSegmentDone && !segment.isTreeDone) // current step being drawn
coord :: createTreeStep(coord.move(direction), direction, segment.moveStep)
else if (segment.isCurrentSegmentDone && segment.isTreeDone) // current step done and no more steps
Nil
else if (segment.isCurrentSegmentDone && !segment.isTreeDone && direction == STAY) // current step done and current step was straight line
coord :: createTreeStep(coord.move(LEFT), LEFT, segment.changeStepDirection) ::: createTreeStep(coord.move(RIGHT), RIGHT, segment.changeStepDirection)
else if (segment.isCurrentSegmentDone && !segment.isTreeDone && direction != STAY) // current step done, current step was diagonal line
coord :: createTreeStep(coord.move(STAY), STAY, segment.createNextSegment)
else
Nil
}
def buildTree(coord: Coordinate, firstStepLength: Int, numberOfSegments: Int) = createTreeStep(coord, STAY, Segment(1,firstStepLength, numberOfSegments))
val (maxX, maxY) = (100,63) // 63 rows, 100 columns
val steps = 5 //io.StdIn.readInt()
val treeCoordinates = buildTree(Coordinate(49,0),16,steps) // x, y, firstStepLength, stepsLeft
// Array
val canvasArray: Array[Array[Char]] = Array.fill[Char](maxY,maxX) {'_'}
treeCoordinates.map { coord:Coordinate => canvasArray(maxY-coord.y-1)(coord.x) = '1' } // 63-y-1 - because the tree was built with longest branches on top, hence needs to be reversed
//canvasArray.map(_.mkString).map(println) // print Array canvas
// Vector
// val emptyCanvas2D: Vector[Vector[Char]] = Vector.fill[Char](maxY,maxX) {'_'} // nezinu, kā šo piedabūt pie strādāšanas
val emptyCanvas1D: Vector[Char] = Vector.fill[Char](maxY * maxX) {'_'}
val canvas1D = treeCoordinates.foldLeft (emptyCanvas1D) { (cumul:Vector[Char], coord:Coordinate) => cumul.updated( coord.y * maxX + coord.x, '1' ) } // paste coordinates into the canvas
(1 to maxY toList).foldLeft ( canvas1D.reverse ) { (cumul, _) => { val (l,ls) = cumul.splitAt (maxX); l.map( print ); println ; ls } } // print 1D vector canvas in 2D
}
@jurisk
Copy link
Copy Markdown

jurisk commented Mar 7, 2016

Lots of opinions how to do enums in Scala properly. It depends on use case. Here you might do sealed trait Direction with multiple object Left extends Direction instead of what you did.

However, perhaps even better - do a val left = Coordinate(-1, +1) and then have Coordinate case class have a def +(that: Coordinate) method.

In any case, all-uppercase names are not really used in Scala.

In topmost Scaladoc comment you could link to Hackerrank task, so I don't have to look for it.

You can do without import GrowthDirection._ but then refer to them as GrowthDirection.LEFT.

Does this not work for 2D vector? Didn't test it. val emptyCanvas2D: Vector[Vector[Char]] = Vector.fill[Char](maxY) {Vector.fill[Chart](maxX)('_')}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment