Created
March 6, 2016 21:19
-
-
Save JRuumis/e4d0f8c5986bb575d9dd to your computer and use it in GitHub Desktop.
Resucrive Tree
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Lots of opinions how to do enums in Scala properly. It depends on use case. Here you might do
sealed trait Directionwith multipleobject Left extends Directioninstead of what you did.However, perhaps even better - do a
val left = Coordinate(-1, +1)and then have Coordinate case class have adef +(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 asGrowthDirection.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)('_')}