Skip to content

Instantly share code, notes, and snippets.

@sungkmi
Created June 27, 2015 01:44
Show Gist options
  • Save sungkmi/a28f469617ccda1631cd to your computer and use it in GitHub Desktop.
Save sungkmi/a28f469617ccda1631cd to your computer and use it in GitHub Desktop.
object HikingDeer extends App {
def minEncounter(hikers: Seq[(Int, Int, Int)]): Int = {
val h = hikers.map(_._2).sum
def loop(events: collection.SortedMap[Double, Set[(Int, Int)]], current: Int, min: Int): Int = {
// println(events, current, min)
if (min == 0 || current >= 2 * h) min
else {
val (time, hikers): (Double, Set[(Int, Int)]) = events.head
val d = (for {
(speed, count) <- hikers
d = if (count == 0) -1 else 1
} yield d).sum
val nextEvents = (events.tail /: (hikers)) {
case (events, (speed, count)) =>
events + ((time + speed) -> (events.getOrElse(time + speed, Set.empty) + ((speed, count + 1))))
}
loop(nextEvents, current + d, min min (current + d))
}
}
val events = for {
(position, numberOfHikers, initSpeed) <- hikers
i <- 0 until numberOfHikers
speed = i + initSpeed
} yield ((360 - position).toDouble / 360 * speed, speed)
val eventMap = collection.SortedMap.empty[Double, Set[(Int, Int)]] ++ (events.groupBy(_._1).mapValues {
case events: Seq[(Double, Int)] =>
events.map(x => (x._2, 0)).toSet
})
loop(eventMap, h, h)
}
def process(lineIn: Iterator[String])(lineOut: String => Unit) =
for (i <- 1 to lineIn.next().toInt) {
val hikers = Seq.fill(lineIn.next().toInt) {
val Array(a, b, c) = lineIn.next() split ' ' map (_.toInt)
(a, b, c)
}
lineOut(s"Case #$i: ${minEncounter(hikers)}")
}
val filename = "C-small-practice-2"
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 HikingDeer._
class HikingDeerTest extends FunSuite {
test("sample #1") {
assert(minEncounter(Seq((1, 1, 12), (359, 1, 12), (2, 1, 12), (358, 1, 12))) === 0)
}
test("sample #2") {
assert(minEncounter(Seq((180, 1, 100000), (180, 1, 1))) === 1)
}
test("sample #3") {
assert(minEncounter(Seq((180, 2, 1))) === 0)
}
test("sample case") {
val input = """3
4
1 1 12
359 1 12
2 1 12
358 1 12
2
180 1 100000
180 1 1
1
180 2 1""".lines
val expected = """Case #1: 0
Case #2: 1
Case #3: 0""".lines
lineComparison(input, expected)
}
ignore("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)
}
ignore("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