From cf0b23d5a5ffc4fcb29911f74052b49f9e5f967d Mon Sep 17 00:00:00 2001 From: Soren Date: Sun, 25 Nov 2018 14:09:25 -0800 Subject: [PATCH] Add days 8 and 9 --- aoc/src/main/scala/aoc/y2017/Day08.scala | 118 ++++++++++++++++++++- aoc/src/main/scala/aoc/y2017/Day09.scala | 42 +++++++- aoc/src/main/scala/aoc/y2017/package.scala | 2 + 3 files changed, 160 insertions(+), 2 deletions(-) diff --git a/aoc/src/main/scala/aoc/y2017/Day08.scala b/aoc/src/main/scala/aoc/y2017/Day08.scala index d1cd1de..17e77f0 100644 --- a/aoc/src/main/scala/aoc/y2017/Day08.scala +++ b/aoc/src/main/scala/aoc/y2017/Day08.scala @@ -1,5 +1,121 @@ package aoc.y2017 -object Day08 { +import aoc.Day + +object Day08 extends Day { + + import fastparse._, NoWhitespace._ + + sealed trait Instruction { + def result(regValue: Int, input: Int): Int + } + case object Dec extends Instruction { + override def result(regValue: Int, input: Int): Int = regValue - input + } + case object Inc extends Instruction { + override def result(regValue: Int, input: Int): Int = regValue + input + } + + sealed trait Test { + def result(regValue: Int, input: Int): Boolean + } + case object Lt extends Test { + override def result(regValue: Int, input: Int): Boolean = regValue < input + } + case object Gt extends Test { + override def result(regValue: Int, input: Int): Boolean = regValue > input + } + case object Leq extends Test { + override def result(regValue: Int, input: Int): Boolean = regValue <= input + } + case object Geq extends Test { + override def result(regValue: Int, input: Int): Boolean = regValue >= input + } + case object Eq extends Test { + override def result(regValue: Int, input: Int): Boolean = regValue == input + } + case object Neq extends Test { + override def result(regValue: Int, input: Int): Boolean = regValue != input + } + + case class FullInstruction(reg: String, op: Instruction, v: Int) + case class FullTest(reg: String, op: Test, v: Int) + case class Line(i: FullInstruction, t: FullTest) + + def registerParser[_: P] = P(CharIn("a-z").rep(1).!) + def numberParser[_: P] = P(("-".? ~ CharIn("0-9").rep(1)).!).map(_.toInt) + def instructionParser[_: P] = P(("inc" | "dec").!).map { + case "inc" => Inc + case "dec" => Dec + } + def testParser[_: P] = P(("<=" | ">=" | "<" | ">" | "==" | "!=").!).map { + case "<" => Lt + case ">" => Gt + case "<=" => Leq + case ">=" => Geq + case "==" => Eq + case "!=" => Neq + } + def fullInstructionParser[_: P] = P(registerParser ~ " " ~ instructionParser ~ " " ~ numberParser).map { + case (reg, op, v) => FullInstruction(reg, op, v) + } + def fullTestParser[_: P] = P(registerParser ~ " " ~ testParser ~ " " ~ numberParser).map { + case (reg, op, v) => FullTest(reg, op, v) + } + def lineParser[_: P] = P(fullInstructionParser ~ " if " ~ fullTestParser).map { + case (i, t) => Line(i, t) + } + def listParser[_: P] = P(lineParser.rep(1, "\n")).map(_.toList) + + def getProgram(input: String): List[Line] = { + val Parsed.Success(list, _) = parse(input, listParser(_)) + list + } + + override def part1(input: String): String = { + val list = getProgram(input) + val allRegs = (list.map(_.i.reg) ++ list.map(_.t.reg)).distinct + val regMap: Map[String, Int] = allRegs.map(r => (r, 0)).toMap + val o = list.foldLeft(regMap)((map, cl) => { + print(s"\r$cl") + val testReg = map(cl.t.reg) + val test = cl.t.op + val v = cl.t.v + if(test.result(testReg, v)) { + val inReg = map(cl.i.reg) + val in = cl.i.op + val iv = cl.i.v + map + (cl.i.reg -> in.result(inReg, iv)) + } else { + map + } + }) + println() + o.values.max.toString + } + + override def part2(input: String): String = { + val list = getProgram(input) + val allRegs = (list.map(_.i.reg) ++ list.map(_.t.reg)).distinct + val regMap: Map[String, Int] = allRegs.map(r => (r, 0)).toMap + val (_, max) = list.foldLeft((regMap, 0)) { + case ((map, hm), cl) => + print(s"\r$cl") + val testReg = map(cl.t.reg) + val test = cl.t.op + val v = cl.t.v + val inReg = map(cl.i.reg) + if (test.result(testReg, v)) { + val in = cl.i.op + val iv = cl.i.v + val nv = in.result(inReg, iv) + (map + (cl.i.reg -> nv), Math.max(hm, nv)) + } else { + (map, Math.max(hm, inReg)) + } + } + println() + max.toString + } } diff --git a/aoc/src/main/scala/aoc/y2017/Day09.scala b/aoc/src/main/scala/aoc/y2017/Day09.scala index 4bed014..604e14c 100644 --- a/aoc/src/main/scala/aoc/y2017/Day09.scala +++ b/aoc/src/main/scala/aoc/y2017/Day09.scala @@ -1,5 +1,45 @@ package aoc.y2017 -object Day09 { +import aoc.Day + +object Day09 extends Day { + + import fastparse._, MultiLineWhitespace._ + + sealed trait Elem { + def score(level: Int = 1): Int + def garbageCount: Int + } + case class Group(contents: List[Elem]) extends Elem { + override def score(level: Int = 1): Int = level + contents.map(_.score(level + 1)).sum + override def garbageCount: Int = contents.map(_.garbageCount).sum + } + case class Garbage(contents: String) extends Elem { + override def score(level: Int = 1): Int = 0 + override def garbageCount: Int = { + val r = """!.""".r + contents.length - (r.findAllIn(contents).length * 2) + } + } + + def elemParser[_: P]: P[Elem] = P(groupParser | garbageParser) + def groupParser[_: P]: P[Group] = P("{" ~/ elemParser.rep(0, ","./) ~ "}").map(c => Group(c.toList)) + def garbageCharacterParser[_: P]: P[Unit] = P(("!".? ~ CharIn("""aeiou"'<{,}""")) | "!>" | "!!")./ + def garbageParser[_: P]: P[Garbage] = P("<" ~/ garbageCharacterParser.rep.! ~ ">").map(s => Garbage(s)) + + def getElem(input: String): Elem = { + val Parsed.Success(e, _) = parse(input, elemParser(_)) + e + } + + override def part1(input: String): String = { + val e = getElem(input) + e.score().toString + } + + override def part2(input: String): String = { + val e = getElem(input) + e.garbageCount.toString + } } diff --git a/aoc/src/main/scala/aoc/y2017/package.scala b/aoc/src/main/scala/aoc/y2017/package.scala index 16882a5..30ac7e7 100644 --- a/aoc/src/main/scala/aoc/y2017/package.scala +++ b/aoc/src/main/scala/aoc/y2017/package.scala @@ -12,6 +12,8 @@ package object y2017 extends Year { "5" -> Day05, "6" -> Day06, "7" -> Day07, + "8" -> Day08, + "9" -> Day09, "25" -> Day25 )