Skip to content

Instantly share code, notes, and snippets.

@sungkmi
Last active November 1, 2015 14:55
Show Gist options
  • Save sungkmi/6ad95f8c7256b28d5e91 to your computer and use it in GitHub Desktop.
Save sungkmi/6ad95f8c7256b28d5e91 to your computer and use it in GitHub Desktop.
object GSnake extends App {
def lengthOfSnake(R: Int, C: Int, actions: Seq[(Int, String)]): Int = {
case class Snake(body: Vector[(Int, Int)], direction: Int) {
def forward(foods: Set[(Int, Int)]): (Snake, Set[(Int, Int)]) = {
val (r, c) = body.head
val (foods1, body1) = if (foods contains (r, c)) (foods - ((r, c)), body) else (foods, body.init)
val head1 = Vector(
(if (r - 1 < 1) R else r - 1, c),
(r, if (c + 1 > C) 1 else c + 1),
(if (r + 1 > R) 1 else r + 1, c),
(r, if (c - 1 < 1) C else c - 1)
)(direction)
(Snake(head1 +: body1, direction), foods1)
}
}
def move(map: (Snake, Set[(Int, Int)]), action: Option[Boolean]): (Snake, Set[(Int, Int)]) = {
val (snake, foods) = map
Snake(snake.body, (snake.direction + (action match {
case None => 0
case Some(true) => 1
case Some(false) => -1
})) % 4).forward(foods)
}
val foods0: Set[(Int, Int)] = (for {
r <- (1 to R)
c <- 1 to C if (r + c) % 2 == 1
} yield (r, c)).toSet
val actionMap = actions.toMap.mapValues(action => Some(action == "R")) withDefaultValue None
def loop(map: (Snake, Set[(Int, Int)]), actions: List[Option[Boolean]]): Int = {
println(map, actions.head)
val (snake, foods) = move(map, actions.head)
println(s"==> $snake")
if (actions.tail.isEmpty || (snake.body.tail contains snake.body.head)) map._1.body.size
else loop((snake, foods), actions.tail)
}
loop((Snake(Vector((1, 1)), 1), foods0), (0 to 10 map actionMap).toList)
}
def process(lineIn: Iterator[String])(lineOut: String => Unit) =
for (i <- 1 to lineIn.next().toInt) {
def readInts() = { lineIn.next().split(' ').map(_.toInt) }
val Array(n, m) = readInts()
}
val filename = "C-large-practice"
val writer = new java.io.PrintWriter(filename + ".out")
try {
process(io.Source.fromFile(filename + ".in").getLines) { s =>
writer.println(s); writer.flush()
}
} finally {
writer.flush(); writer.close()
}
}
import org.scalatest._
import GSnake._
class GSnakeTest extends FunSuite with Matchers {
test("sample #1") {
/*
3 x 3 // Seq((1,"R"),(2,"L"),(3, "R")))
0: (1, 1) > 1
1: (1, 2) v 2
2: (2, 2) (1, 2) > 1
3: (2, 3) (2, 2) v 2
4: (3, 3) (2, 3) (2, 2) v 2
*/
assert(lengthOfSnake(3, 3, Seq((1,"R"),(2,"L"),(3, "R"))) === 3)
}
test("sample #2") {
assert(lengthOfSnake(3, 3, Seq((2, "R"),(4, "R"), (6, "R"), (7, "R"), (8, "R"))) === 5)
}
ignore("sample case") {
val input = """2
3 3
0 1 10
1 2 3
2 0 3
3 3
0 1 10
1 2 3
2 1 3""".lines
val expected = """Case #1:
0
Case #2:""".lines
lineComparison(input, expected)
}
ignore("full small case") {
val input = io.Source.fromFile("C-small-practice.in").getLines()
val expected = io.Source.fromFile("C-small-practice.out").getLines()
lineComparison(input, expected)
}
ignore("full large case") {
val input = io.Source.fromFile("C-large-practice.in").getLines()
val expected = io.Source.fromFile("C-large-practice.out").getLines()
lineComparison(input, expected)
}
def lineComparison(input: Iterator[String], expected: Iterator[String]) {
process(input) { s =>
for (line <- s.lines) assert(line.trim === expected.next().trim)
}
assert(expected.hasNext === false, "Finished too fast.")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment