Skip to content

Instantly share code, notes, and snippets.

@sungkmi
Last active August 29, 2015 14:08
Show Gist options
  • Save sungkmi/1b6655d57aebe80c6d87 to your computer and use it in GitHub Desktop.
Save sungkmi/1b6655d57aebe80c6d87 to your computer and use it in GitHub Desktop.
object TrainTimetable extends App {
def numOfTrains(t: Int, a2b: List[String], b2a: List[String]): (Int, Int) = {
trait Event { val at: Int }
case class Ready(at: Int) extends Event
case class Departure(at: Int) extends Event
def toEvents(timetable: List[String]): (List[Departure], List[Ready]) =
(timetable :\ (List.empty[Departure], List.empty[Ready])) {
case (train, (departures, readies)) =>
val Array(departure, arrival) = for {
time <- train split ' '
Array(hour, min) = time split ':' map (_.toInt)
} yield hour * 60 + min
(Departure(departure) :: departures, Ready(arrival + t) :: readies)
}
def count(readies: List[Ready], departures: List[Departure]): Int =
((0, 0) /: (readies ::: departures sortBy (_.at))) {
case ((ready, count), Ready(t)) => (ready + 1, count)
case ((0, count), Departure(t)) => (0, count + 1)
case ((ready, count), Departure(t)) => (ready - 1, count)
}._2
val (aDep, bReady) = toEvents(a2b)
val (bDep, aReady) = toEvents(b2a)
(count(aReady, aDep), count(bReady, bDep))
}
def process(lineIn: Iterator[String])(lineOut: String => Unit) =
for (i <- 1 to lineIn.next().toInt) {
val t = lineIn.next().toInt
val Array(na, nb) = lineIn.next().split(' ').map(_.toInt)
def read(n: Int) = List.fill(n)(lineIn.next())
val (ansA, ansB) = numOfTrains(t, read(na), read(nb))
lineOut(s"Case #$i: $ansA $ansB")
}
val writer = new java.io.PrintWriter("b.large.out")
try {
process(io.Source.fromFile("B-large-practice.in").getLines)(writer.println)
} finally {
writer.flush(); writer.close()
}
}
import org.scalatest._
import TrainTimetable._
class TrainTimetableTest extends FunSuite {
test("sample #1") {
assert(numOfTrains(5, List("09:00 12:00", "10:00 13:00", "11:00 12:30"), List("12:02 15:00", "09:00 10:30")) === (2, 2))
}
test("sample #2") {
assert(numOfTrains(5, List("09:00 09:01", "12:00 12:02"), List()) === (2, 0))
}
test("sample case") {
val input = """2
5
3 2
09:00 12:00
10:00 13:00
11:00 12:30
12:02 15:00
09:00 10:30
2
2 0
09:00 09:01
12:00 12:02""".lines
val expected = """Case #1: 2 2
Case #2: 2 0""".lines
lineComparison(input, expected)
}
test("full small case") {
val input = io.Source.fromFile("B-small-practice.in").getLines()
val expected = io.Source.fromFile("b.small.out.ref").getLines()
lineComparison(input, expected)
}
test("full large case") {
val input = io.Source.fromFile("B-large-practice.in").getLines()
val expected = io.Source.fromFile("b.large.out.ref").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)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment