Skip to content

Instantly share code, notes, and snippets.

@sungkmi
Last active February 23, 2024 10:28
Show Gist options
  • Save sungkmi/6aaa18b44bec454d77e3 to your computer and use it in GitHub Desktop.
Save sungkmi/6aaa18b44bec454d77e3 to your computer and use it in GitHub Desktop.
object Pegman extends App {
def minArrows(grid: IndexedSeq[IndexedSeq[Char]]): Option[Int] = {
val (r, c) = (grid.size, grid(0).size)
def arrows(grid: IndexedSeq[IndexedSeq[Char]]): Seq[(Int, Int, Char)] = {
for {
i <- 0 until r
j <- 0 until c
g = grid(i)(j) if "^v><" contains g
} yield (i, j, g)
}
def needToRotate(row: Int, column: Int, direction: Char): Boolean = direction match {
case '^' =>
!(for {
i <- 0 until row
} yield grid(i)(column)).exists{ "^v><".contains(_)}
case 'v' =>
!(for {
i <- row+1 until r
} yield grid(i)(column)).exists{ "^v><".contains(_)}
case '<' =>
!(for {
j <- 0 until column
} yield grid(row)(j)).exists{ "^v><".contains(_)}
case '>' =>
!(for {
j <- column+1 until c
} yield grid(row)(j)).exists{ "^v><".contains(_)}
}
def possibleToRotate(row: Int, column: Int): Boolean = {
(for{
i <- 0 until r if i!=row
} yield grid(i)(column)).exists{ _ !='.'} ||
(for{
j <- 0 until c if j!=column
} yield grid(row)(j)).exists{ _ !='.'}
}
(Some(0) /:[Option[Int]] arrows(grid)) {
case (None, _ ) => None
case (Some(count), (row, column, direction)) =>
if (!needToRotate(row, column, direction)) Some(count)
else if (possibleToRotate(row, column)) Some(count+1)
else None
}
}
def process(lineIn: Iterator[String])(lineOut: String => Unit) =
for (i <- 1 to lineIn.next().toInt) {
val Array(r, c) = lineIn.next() split ' ' map (_.toInt)
val grid = Vector.fill(r){lineIn.next().toVector}
lineOut(s"Case #$i: ${minArrows(grid) getOrElse "IMPOSSIBLE"}")
}
val filename = "A-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 Pegman._
class PegmanTest extends FunSuite {
test("sample #1") {
assert(minArrows(Vector("^".toVector, "^".toVector)) === Some(1))
}
test("sample #2") {
assert(minArrows(Vector(">v".toVector, "^<".toVector)) === Some(0))
}
test("sample #3") {
assert(minArrows(Vector("...".toVector, ".^.".toVector, "...".toVector)) === None)
}
test("sample #4") {
assert(minArrows(Vector(".".toVector)) === Some(0))
}
test("sample case") {
val input = """4
2 1
^
^
2 2
>v
^<
3 3
...
.^.
...
1 1
.""".lines
val expected = """Case #1: 1
Case #2: 0
Case #3: IMPOSSIBLE
Case #4: 0""".lines
lineComparison(input, expected)
}
test("full small case") {
val input = io.Source.fromFile("A-small-practice.in").getLines()
val expected = io.Source.fromFile("A-small-practice.out").getLines()
lineComparison(input, expected)
}
test("full large case") {
val input = io.Source.fromFile("A-large-practice.in").getLines()
val expected = io.Source.fromFile("A-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