Day 6
This commit is contained in:
parent
abf2060411
commit
4047fc52ac
|
@ -17,7 +17,11 @@ object Main {
|
||||||
val part = askForPart(day)
|
val part = askForPart(day)
|
||||||
println("Problem input? End input with an `End of Input` line.")
|
println("Problem input? End input with an `End of Input` line.")
|
||||||
val input = LazyList.continually(StdIn.readLine()).takeWhile(_ != "End of Input").toList.mkString("\n")
|
val input = LazyList.continually(StdIn.readLine()).takeWhile(_ != "End of Input").toList.mkString("\n")
|
||||||
println(s"Output: ${part(input)}")
|
val startTime = System.currentTimeMillis()
|
||||||
|
val output = part(input)
|
||||||
|
val endTime = System.currentTimeMillis()
|
||||||
|
println(s"Output: $output")
|
||||||
|
println(s"Time: ${endTime - startTime}ms")
|
||||||
}
|
}
|
||||||
|
|
||||||
def askForYear(): Year = {
|
def askForYear(): Year = {
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
package aoc.y2019
|
||||||
|
|
||||||
|
import aoc.Day
|
||||||
|
import cats._
|
||||||
|
import cats.implicits._
|
||||||
|
import cats.data._
|
||||||
|
import cats.free._
|
||||||
|
|
||||||
|
import scala.annotation.tailrec
|
||||||
|
|
||||||
|
object Day06 extends Day {
|
||||||
|
|
||||||
|
case class Body(name: String)
|
||||||
|
type Orbits = Cofree[Vector, Body]
|
||||||
|
|
||||||
|
import fastparse._, SingleLineWhitespace._
|
||||||
|
|
||||||
|
def parseBody[_: P]: P[Body] = P(CharIn("A-Z", "0-9").rep.!).map(Body)
|
||||||
|
def parseOrbit[_: P]: P[(Body, Body)] = P(parseBody ~ ")" ~ parseBody)
|
||||||
|
def parseOrbitList[_: P]: P[Vector[(Body, Body)]] = P(parseOrbit.rep(1, "\n")).map(_.toVector)
|
||||||
|
|
||||||
|
def constructOrbits(orbitMap: Map[Body, Vector[Body]], initial: Body): Orbits = {
|
||||||
|
lazy val childOrbits = orbitMap.getOrElse(initial, Vector.empty[Body]).map(constructOrbits(orbitMap, _))
|
||||||
|
Cofree(initial, Eval.later(childOrbits))
|
||||||
|
}
|
||||||
|
|
||||||
|
def indirectOrbits(orbits: Orbits, level: Int = 0): Int = {
|
||||||
|
val childOrbits = orbits.tail.value.map(indirectOrbits(_, level + 1))
|
||||||
|
childOrbits.sum + level
|
||||||
|
}
|
||||||
|
|
||||||
|
def hasBody(orbits: Orbits, body: Body): Boolean = {
|
||||||
|
orbits.head == body || orbits.tail.value.exists(hasBody(_, body))
|
||||||
|
}
|
||||||
|
|
||||||
|
@tailrec def closestCommonOrbit(orbits: Orbits, a: Body, b: Body): Option[Orbits] = {
|
||||||
|
def bothChildren(orbits: Orbits): Option[Orbits] = Option.when(hasBody(orbits, a) && hasBody(orbits, b))(orbits)
|
||||||
|
|
||||||
|
orbits.tail.value.collectFirstSome(bothChildren) match {
|
||||||
|
case Some(closerCommonOrbit) => closestCommonOrbit(closerCommonOrbit, a, b)
|
||||||
|
case None => bothChildren(orbits)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def distanceToChildBody(orbits: Orbits, target: Body, depth: Int = 0): Option[Int] = {
|
||||||
|
if(orbits.head == target) depth.some
|
||||||
|
else orbits.tail.value match {
|
||||||
|
case Vector() => None
|
||||||
|
case nonEmpty => nonEmpty.map(distanceToChildBody(_, target, depth + 1)).find(_.isDefined).flatten
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def orbitsFromInput(input: String): Orbits = {
|
||||||
|
val orbitList = parse(input, parseOrbitList(_)).get.value
|
||||||
|
val orbitMap = orbitList.groupBy(_._1).view.mapValues(_.map(_._2)).toMap
|
||||||
|
val firstPlanet = orbitMap.keys.find(body => orbitMap.values.count(_.contains(body)) == 0).get
|
||||||
|
constructOrbits(orbitMap, firstPlanet)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def part1(input: String): String = {
|
||||||
|
indirectOrbits(orbitsFromInput(input)).toString
|
||||||
|
}
|
||||||
|
|
||||||
|
override def part2(input: String): String = {
|
||||||
|
val orbits = orbitsFromInput(input)
|
||||||
|
val orbitalTransfers = (for {
|
||||||
|
closestCommon <- closestCommonOrbit(orbits, Body("YOU"), Body("SAN"))
|
||||||
|
distanceToMe <- distanceToChildBody(closestCommon, Body("YOU"))
|
||||||
|
distanceToSan <- distanceToChildBody(closestCommon, Body("SAN"))
|
||||||
|
} yield (distanceToMe + distanceToSan) - 2).get
|
||||||
|
orbitalTransfers.toString
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ package object y2019 extends Year {
|
||||||
"3" -> Day03,
|
"3" -> Day03,
|
||||||
"4" -> Day04,
|
"4" -> Day04,
|
||||||
"5" -> Day05,
|
"5" -> Day05,
|
||||||
|
"6" -> Day06,
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ val sharedSettings = Seq(
|
||||||
"com.lihaoyi" %%% "fastparse" % "2.1.3",
|
"com.lihaoyi" %%% "fastparse" % "2.1.3",
|
||||||
"org.scala-graph" %%% "graph-core" % "1.13.1",
|
"org.scala-graph" %%% "graph-core" % "1.13.1",
|
||||||
"org.typelevel" %%% "cats-core" % "2.0.0",
|
"org.typelevel" %%% "cats-core" % "2.0.0",
|
||||||
|
"org.typelevel" %%% "cats-free" % "2.0.0",
|
||||||
),
|
),
|
||||||
mainClass := Some("tf.bug.aoc.Main"),
|
mainClass := Some("tf.bug.aoc.Main"),
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue