diff --git a/aoc/src/main/scala/aoc/y2017/Day11.scala b/aoc/src/main/scala/aoc/y2017/Day11.scala index 306561a..9e57f5d 100644 --- a/aoc/src/main/scala/aoc/y2017/Day11.scala +++ b/aoc/src/main/scala/aoc/y2017/Day11.scala @@ -75,7 +75,7 @@ object Day11 extends Day { override def part2(input: String): String = { val directions = getDirections(input) def findFurthest(directions: List[Direction], step: Int = 1, max: Int = 0): Int = { - if(step > directions.length) { + if (step > directions.length) { max } else { val mds = directions.take(step) diff --git a/aoc/src/main/scala/aoc/y2017/Day12.scala b/aoc/src/main/scala/aoc/y2017/Day12.scala new file mode 100644 index 0000000..790053d --- /dev/null +++ b/aoc/src/main/scala/aoc/y2017/Day12.scala @@ -0,0 +1,54 @@ +package aoc.y2017 + +import aoc.Day + +import scalax.collection.Graph +import scalax.collection.GraphPredef._, scalax.collection.GraphEdge._ +import scalax.collection.edge.Implicits._ + +object Day12 extends Day { + + import fastparse._, SingleLineWhitespace._ + + def channelNameParser[_: P]: P[Int] = P(CharIn("0-9").rep(1).!).map(_.toInt) + def connectionListParser[_: P]: P[Seq[Int]] = P(channelNameParser.rep(1, ","./)) + + def channelParser[_: P]: P[Seq[DiEdge[Int]]] = P(channelNameParser ~ "<->" ~ connectionListParser).map { + case (name, connections) => connections.map(name ~> _) + } + + def channelsParser[_: P]: P[Graph[Int, DiEdge]] = + P(channelParser.rep(1, "\n"./)).map(s => { + val allEdges = s.flatten + Graph.apply(allEdges: _*) + }) + + def getGraph(input: String): Graph[Int, DiEdge] = { + val Parsed.Success(graph, _) = parse(input, channelsParser(_)) + graph + } + + def findGroup(graph: Graph[Int, DiEdge])(startingNode: graph.NodeT): Set[graph.NodeT] = + graph.nodes.filter(_.pathTo(startingNode).isDefined).toSet + + override def part1(input: String): String = { + val graph = getGraph(input) + val zero = graph get 0 + graph.nodes.count(_.pathTo(zero).isDefined).toString + } + + override def part2(input: String): String = { + val graph = getGraph(input) + def groups(g: Graph[Int, DiEdge], count: Int = 0): Int = { + if (g.isEmpty) { + count + } else { + val node = g.nodes.toList.head + val group = findGroup(g)(node) + groups(g --! group, count + 1) + } + } + groups(graph).toString + } + +} diff --git a/aoc/src/main/scala/aoc/y2017/package.scala b/aoc/src/main/scala/aoc/y2017/package.scala index 3ce0a11..8ad233a 100644 --- a/aoc/src/main/scala/aoc/y2017/package.scala +++ b/aoc/src/main/scala/aoc/y2017/package.scala @@ -16,6 +16,7 @@ package object y2017 extends Year { "9" -> Day09, "10" -> Day10, "11" -> Day11, + "12" -> Day12, "25" -> Day25 ) @@ -30,6 +31,7 @@ package object y2017 extends Year { } implicit class TupleInt2Ops(t: (Int, Int)) { + def +(o: (Int, Int)): (Int, Int) = (t, o) match { case ((x1, y1), (x2, y2)) => (x1 + x2, y1 + y2) } diff --git a/build.sbt b/build.sbt index db39c43..d7df41b 100644 --- a/build.sbt +++ b/build.sbt @@ -6,7 +6,8 @@ val sharedSettings = Seq( version := "0.1.0", scalaVersion := "2.12.7", libraryDependencies ++= List( - "com.lihaoyi" %%% "fastparse" % "2.0.4", + "com.lihaoyi" %%% "fastparse" % "2.0.4", + "org.scala-graph" %%% "graph-core" % "1.12.5", ), mainClass := Some("tf.bug.aoc.Main"), )