Skip to content

Instantly share code, notes, and snippets.

@UberMouse
Created March 18, 2014 02:08
Show Gist options
  • Save UberMouse/9612311 to your computer and use it in GitHub Desktop.
Save UberMouse/9612311 to your computer and use it in GitHub Desktop.
package rover
/**
* Created by wyntl1 on 18/03/14.
*/
class TurnDirection
case class Left() extends TurnDirection
case class Right() extends TurnDirection
abstract class Direction() {
def move(pos:Point, forward:Boolean):Point
def turn(dir:TurnDirection):Direction
}
case class North() extends Direction {
def move(pos:Point, forward:Boolean) = Point(pos.x, pos.y+(if(forward) 1 else -1))
def turn(dir:TurnDirection) = dir match {
case Left() => West()
case Right() => East()
}
}
case class East() extends Direction {
def move(pos:Point, forward:Boolean) = Point(pos.x+(if(forward) 1 else -1), pos.y)
def turn(dir:TurnDirection) = dir match {
case Left() => North()
case Right() => South()
}
}
case class South() extends Direction {
def move(pos:Point, forward:Boolean) = Point(pos.x, pos.y-(if(forward) 1 else -1))
def turn(dir:TurnDirection) = dir match {
case Left() => East()
case Right() => West()
}
}
case class West() extends Direction {
def move(pos:Point, forward:Boolean) = Point(pos.x-(if(forward) 1 else -1), pos.y)
def turn(dir:TurnDirection) = dir match {
case Left() => South()
case Right() => North()
}
}
package rover
import scala.collection.mutable
/**
* Created by wyntl1 on 18/03/14.
*/
case class Point(x:Int, y:Int)
case class Planet(height:Int, width:Int, obstacles:List[Point] = List[Point]())
case class InvalidMove() extends Exception()
class Rover(val position:Point, val direction:Direction, val planet:Planet) {
def processCommands(commands:List[String]):(Rover, String) = {
val doneCommands = new mutable.Queue[String]()
val toProcessCommands = new mutable.Queue[String]()
commands.foreach(toProcessCommands.enqueue(_))
try {
val rover = commands.map {
case "f" => moveForward _
case "b" => moveBackward _
case "l" => rotateLeft _
case "r" => rotateRight _
}.foldLeft(this) { case (rover, command) =>
doneCommands.enqueue(toProcessCommands.dequeue())
command(rover)
}
(rover, s"OK: ${doneCommands.mkString(" ")}")
}
catch {
case e:InvalidMove => return (this, s"NOK: ${toProcessCommands.mkString(" ")}")
}
}
def rotateLeft( r:Rover = this) = updateRover(r.position, dir = r.direction.turn(Left()), r.planet)
def rotateRight( r:Rover = this) = updateRover(r.position, dir = r.direction.turn(Right()), r.planet)
def moveForward( r:Rover = this) = updateRover(r.direction.move(r.position, forward = true), r.direction, r.planet)
def moveBackward(r:Rover = this) = updateRover(r.direction.move(r.position, forward = false), r.direction, r.planet)
private def updateRover(x:Int, y:Int, dir:Direction, p:Planet):Rover = {
if(p.obstacles.contains(Point(x, y))) throw new InvalidMove()
Rover(if(x <= p.width) x else x-p.width,
if(y <= p.height) y else y-p.height,
dir,
p)
}
private def updateRover(p:Point, dir:Direction, planet:Planet):Rover = updateRover(p.x, p.y, dir, planet)
override def toString = s"Rover($position, $direction)"
}
object Rover {
def apply(x:Int, y:Int, dir:Direction, p:Planet) = new Rover(Point(x, y), dir, p)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment