From 0bf14430ea7f4b69f2f29b4a936b269829289c30 Mon Sep 17 00:00:00 2001 From: Soren Date: Sun, 25 Nov 2018 10:49:04 -0800 Subject: [PATCH] 3 gold star --- aoc/src/main/scala/aoc/y2017/Day03.scala | 49 +++++++++++++- aoc/src/main/scala/aoc/y2017/Day05.scala | 4 +- aoc/src/main/scala/aoc/y2017/Day06.scala | 63 ++++++++++++++++++ aoc/src/main/scala/aoc/y2017/Day07.scala | 75 ++++++++++++++++++++++ aoc/src/main/scala/aoc/y2017/Day25.scala | 12 ++-- aoc/src/main/scala/aoc/y2017/package.scala | 2 + build.sbt | 2 +- 7 files changed, 196 insertions(+), 11 deletions(-) create mode 100644 aoc/src/main/scala/aoc/y2017/Day06.scala create mode 100644 aoc/src/main/scala/aoc/y2017/Day07.scala diff --git a/aoc/src/main/scala/aoc/y2017/Day03.scala b/aoc/src/main/scala/aoc/y2017/Day03.scala index 996fe99..13b0591 100644 --- a/aoc/src/main/scala/aoc/y2017/Day03.scala +++ b/aoc/src/main/scala/aoc/y2017/Day03.scala @@ -5,7 +5,6 @@ import aoc.Day object Day03 extends Day { override def part1(input: String): String = { - case class Cell(num: Int, stepSize: Int, stepFrac: Int, stepped: Int, dist: (Int, Int)) val inum = input.toInt (inum match { case 1 => 0 @@ -19,7 +18,53 @@ object Day03 extends Day { } override def part2(input: String): String = { - "Not Currently Implemented" // TODO Implement this + implicit class TupleInt2Ops(t: (Int, Int)) { + def +(o: (Int, Int)): (Int, Int) = (t, o) match { + case ((x1, y1), (x2, y2)) => (x1 + x2, y1 + y2) + } + } + sealed trait Direction { + def change: (Int, Int) + } + case object MoveUp extends Direction { + override def change: (Int, Int) = (0, 1) + } + case object MoveRight extends Direction { + override def change: (Int, Int) = (1, 0) + } + case object MoveDown extends Direction { + override def change: (Int, Int) = (0, -1) + } + case object MoveLeft extends Direction { + override def change: (Int, Int) = (-1, 0) + } + def sumOfSurrounding(p: (Int, Int), m: Map[(Int, Int), Int]): Int = { + val surrounding = List( + (-1, 1), ( 0, 1), ( 1, 1), + (-1, 0), /* */ ( 1, 0), + (-1, -1), ( 0, -1), ( 1, -1) + ) + surrounding.map(o => m.getOrElse(p + o, 0)).sum + } + lazy val movementStream: Stream[Int] = Stream.from(1).flatMap(i => Stream(i, i)) + lazy val directionStream: Stream[Direction] = MoveRight #:: MoveUp #:: MoveLeft #:: MoveDown #:: directionStream + lazy val pathStream = movementStream.zip(directionStream).flatMap { + case (times, dir) => Stream.fill(times)(dir) + } + lazy val pathIterator = pathStream.toIterator + val targetNum = input.toInt + def findNext(m: Map[(Int, Int), Int] = Map((0, 0) -> 1), p: (Int, Int) = (0, 0), i: Iterator[Direction]): Int = { + val nd = i.next() + val np = p + nd.change + val sum = sumOfSurrounding(np, m) + val nm = m + (np -> sum) + if(sum > targetNum) { + sum + } else { + findNext(nm, np, i) + } + } + findNext(i = pathIterator).toString } } diff --git a/aoc/src/main/scala/aoc/y2017/Day05.scala b/aoc/src/main/scala/aoc/y2017/Day05.scala index 74a35f9..5c562ca 100644 --- a/aoc/src/main/scala/aoc/y2017/Day05.scala +++ b/aoc/src/main/scala/aoc/y2017/Day05.scala @@ -16,7 +16,7 @@ object Day05 extends Day { def countSteps(p: Program, steps: Int = 0)(implicit stepper: Stepper): Int = { print(s"\rCurrent Instruction: ${p.index}/${p.instructions.size}${" " * p.instructions.size.toString.length}") - if(p.index >= p.instructions.size) { + if (p.index >= p.instructions.size) { steps } else { countSteps(p.step, steps + 1) @@ -44,7 +44,7 @@ object Day05 extends Day { implicit val stepper: Stepper = new Stepper { def step(p: Program): Program = { val instruction = p.instructions(p.index) - val newList = p.instructions.updated(p.index, if(instruction >= 3) instruction - 1 else instruction + 1) + val newList = p.instructions.updated(p.index, if (instruction >= 3) instruction - 1 else instruction + 1) Program(newList, p.index + instruction) } } diff --git a/aoc/src/main/scala/aoc/y2017/Day06.scala b/aoc/src/main/scala/aoc/y2017/Day06.scala new file mode 100644 index 0000000..d8eba4a --- /dev/null +++ b/aoc/src/main/scala/aoc/y2017/Day06.scala @@ -0,0 +1,63 @@ +package aoc.y2017 + +import aoc.Day + +object Day06 extends Day { + + def uniquePrefix[A](as: Stream[A]): Stream[A] = { + def go(as: Stream[A], seen: Set[A]): Stream[A] = as match { + case h #:: t if !seen(h) => h #:: go(t, seen + h) + case _ => Stream.empty[A] + } + go(as, Set.empty) + } + + def rotateLeft[A](list: List[A], i: Int): List[A] = { + val size = list.size + list.drop(i % size) ++ list.take(i % size) + } + + def rotateRight[A](list: List[A], i: Int): List[A] = { + val size = list.size + list.drop(size - (i % size)) ++ list.take(size - (i % size)) + } + + case class State(blocks: List[Int]) { + + def step: State = { + val mi = blocks.indexWhere(_ == blocks.max) + val shifted = rotateLeft(blocks, mi) + val max = shifted.head + val loops = max / shifted.size + val extra = max % shifted.size + val looped = shifted.map(_ + loops) + val extraSlice = looped.tail.take(extra).map(_ + 1) + val back = looped.tail.drop(extra) + val constructed = loops +: (extraSlice ++ back) + State(rotateRight(constructed, mi)) + } + + } + + def showAndGetStream(input: String): Stream[State] = { + val os = State(input.split('\t').toList.map(_.toInt)) + val stream = Stream.iterate(os)(s => s.step) + val uStream = uniquePrefix(stream) + uStream.foreach(s => print(s"\r${s.blocks.mkString("\t")} ")) + println() + uStream + } + + override def part1(input: String): String = { + val uStream = showAndGetStream(input) + uStream.toList.size.toString + } + + override def part2(input: String): String = { + val uStream = showAndGetStream(input) + val l = uStream.toList + val n = l.last.step + (l.size - l.indexOf(n)).toString + } + +} diff --git a/aoc/src/main/scala/aoc/y2017/Day07.scala b/aoc/src/main/scala/aoc/y2017/Day07.scala new file mode 100644 index 0000000..8ead48a --- /dev/null +++ b/aoc/src/main/scala/aoc/y2017/Day07.scala @@ -0,0 +1,75 @@ +package aoc.y2017 + +import aoc.Day + +object Day07 extends Day { + + import fastparse._, SingleLineWhitespace._ + + case class TowerRef(name: String, weight: Int, children: List[String]) { + + def resolve(trs: List[TowerRef]): Tower = + Tower(name, weight, children.map(c => trs.find(_.name == c).get.resolve(trs))) + + } + + case class Tower(name: String, weight: Int, children: List[Tower]) { + + def childWeights: List[Int] = children.map(_.totalWeight) + + def totalWeight: Int = weight + childWeights.sum + + } + + def childrenParser[_: P]: P[List[String]] = + P(("->" ~ CharIn("a-z").rep(1).!.rep(1, ",")).?).map(_.fold(List[String]())(_.toList)) + + def towerParser[_: P]: P[TowerRef] = P(CharIn("a-z").rep(1).! ~ "(" ~ CharIn("0-9").rep(1).! ~ ")" ~ childrenParser).map { + case (name, weight, children) => TowerRef(name, weight.toInt, children) + } + + def towerListParser[_: P]: P[List[TowerRef]] = towerParser.rep(1, "\n").map(_.toList) + + def lowest(trs: List[TowerRef]): TowerRef = { + val allChildren = trs.flatMap(_.children) + val name = trs.map(_.name).filterNot(allChildren.contains).head + trs.find(_.name == name).get + } + + override def part1(input: String): String = { + val Parsed.Success(trs: List[TowerRef], _) = parse(input, towerListParser(_)) + lowest(trs).name + } + + override def part2(input: String): String = { + val Parsed.Success(trs: List[TowerRef], _) = parse(input, towerListParser(_)) + val lowestT = lowest(trs) + val resolved = lowestT.resolve(trs) + def searchForUnevenness(tower: Tower): List[Int] = { + if(tower.childWeights.distinct.size == 1) { + tower.children.flatMap(searchForUnevenness) + } else { + if(tower.childWeights.isEmpty) { + List() + } else { + val ds = tower.childWeights.distinct + val (w1, w2) = (ds.head, ds.last) + val (c1, c2) = (tower.childWeights.count(_ == w1), tower.childWeights.count(_ == w2)) + val (offWeight, onWeight) = if (Math.max(c1, c2) == c1) { + (w2, w1) + } else { + (w1, w2) + } + val offChild = tower.children.find(_.totalWeight == offWeight).get + if (offChild.childWeights.distinct.size == 1) { + List((onWeight - offWeight) + offChild.weight) + } else { + offChild.children.flatMap(searchForUnevenness) + } + } + } + } + searchForUnevenness(resolved).head.toString + } + +} diff --git a/aoc/src/main/scala/aoc/y2017/Day25.scala b/aoc/src/main/scala/aoc/y2017/Day25.scala index 3c04865..226b8a3 100644 --- a/aoc/src/main/scala/aoc/y2017/Day25.scala +++ b/aoc/src/main/scala/aoc/y2017/Day25.scala @@ -19,12 +19,12 @@ object Day25 extends Day { override def change: Int = 1 } case class Program( - beginIn: State, - diagnosticCount: Int, - states: Map[State, InState], - index: Int = 0, - tape: Map[Int, Int] = Map() - ) { + beginIn: State, + diagnosticCount: Int, + states: Map[State, InState], + index: Int = 0, + tape: Map[Int, Int] = Map() + ) { def step: Program = { val ndc = diagnosticCount - 1 diff --git a/aoc/src/main/scala/aoc/y2017/package.scala b/aoc/src/main/scala/aoc/y2017/package.scala index 6ed8831..16882a5 100644 --- a/aoc/src/main/scala/aoc/y2017/package.scala +++ b/aoc/src/main/scala/aoc/y2017/package.scala @@ -10,6 +10,8 @@ package object y2017 extends Year { "3" -> Day03, "4" -> Day04, "5" -> Day05, + "6" -> Day06, + "7" -> Day07, "25" -> Day25 ) diff --git a/build.sbt b/build.sbt index 22e83ee..db39c43 100644 --- a/build.sbt +++ b/build.sbt @@ -4,7 +4,7 @@ val sharedSettings = Seq( name := "aoc", organization := "tf.bug", version := "0.1.0", - scalaVersion := "2.11.12", + scalaVersion := "2.12.7", libraryDependencies ++= List( "com.lihaoyi" %%% "fastparse" % "2.0.4", ),