package aoc object AoC2017 extends Year { override def days = Map( "1" -> Day1, "2" -> Day2, "3" -> Day3, "25" -> Day25 ) object Day1 extends Day { override def part1(input: String): String = { val reg = """(\d)(?=\1)""".r val matches = reg.findAllIn(input).toList val csum = matches.map(_.toInt).sum if(input.head == input.last) { (csum + input.head.toString.toInt).toString } else { csum.toString } } override def part2(input: String): String = { val (left, right) = input.splitAt(input.length / 2) val zipped = left.zip(right) val doubled = zipped.filter { case (l, r) => l == r}.map { case (c, _) => c.toString } (doubled.map(_.toInt).sum * 2).toString } } object Day2 extends Day { override def part1(input: String): String = { val lines = input.lines.toList val rows = lines.map(_.split("""\s+""").map(_.toInt)) val minMax = rows.map(r => (r.min, r.max)) val differences = minMax.map { case (min, max) => max - min } differences.sum.toString } override def part2(input: String): String = { val lines = input.lines.toList val rows = lines.map(_.split("""\s+""").map(_.toInt)) rows.flatMap { r => val q = r.zipWithIndex.flatMap { case (e, i) => r.drop(i + 1).map(f => { val (min, max) = (Math.min(e, f), Math.max(e, f)) if(max % min == 0) { Some(max / min) } else { None } }) } q.filter(_.isDefined).map(_.get) }.sum.toString } } object Day3 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 case _ => val layer = (Math.sqrt(inum).ceil / 2).floor.toInt val square = ((layer + 1) * 2) - 1 val diff = (square * square) - inum val wave = Math.abs(layer - (diff % (layer * 2))) layer + wave }).toString } override def part2(input: String): String = { "Not Currently Implemented" // TODO Implement this } } object Day25 extends Day { import fastparse._, MultiLineWhitespace._ case class State(name: String) case class InState(state: State, whenZero: Branch, whenOne: Branch) case class Branch(write: Int, move: Direction, stateChange: State) sealed trait Direction { def change: Int } case object MoveLeft extends Direction { override def change: Int = -1 } case object MoveRight extends Direction { override def change: Int = 1 } case class Program(beginIn: State, diagnosticCount: Int, states: Map[State, InState], index: Int = 0, tape: Map[Int, Int] = Map()) { def step: Program = { val ndc = diagnosticCount - 1 val cs = states(beginIn) val cc = tape.getOrElse(index, 0) val br = cc match { case 0 => cs.whenZero case 1 => cs.whenOne } val wr = br.write val mv = br.move val ns = br.stateChange val nm = tape + (index -> wr) Program(ns, ndc, states, index + mv.change, nm) } } def stateParser[_: P]: P[State] = P( "state" ~ CharIn("A-Z").rep.! ).map(State) def writeParser[_: P]: P[Int] = P( "- Write the value" ~ ("0" | "1").! ~ "." ).map(_.toInt) def directionParser[_: P]: P[Direction] = P( "- Move one slot to the" ~ ("left" | "right").! ~ "." ).map { case "left" => MoveLeft case "right" => MoveRight } def stateChangeParser[_: P]: P[State] = P("- Continue with" ~ stateParser ~ ".") def branchParser[_: P]: P[Branch] = P( writeParser ~ directionParser ~ stateChangeParser ).map { case (write, dir, state) => Branch(write, dir, state) } def inStateParser[_: P]: P[InState] = P( "In" ~ stateParser ~ ":" ~ "If the current value is 0:" ~ branchParser ~ "If the current value is 1:" ~ branchParser ).map { case (state, v0, v1) => InState(state, v0, v1) } def programParser[_: P]: P[Program] = P( "Begin in" ~ stateParser ~ "." ~ "Perform a diagnostic checksum after" ~ CharIn("0-9").rep(1).!.map(_.toInt) ~ "steps." ~ inStateParser.rep.map(f => { val z = f.map(_.state).zip(f) z.toMap }) ).map { case (begin, steps, states) => Program(begin, steps, states) } override def part1(input: String): String = { val Parsed.Success(program, _) = parse(input, programParser(_)) def finalState(p: Program): Program = { val np = p.step print(s"\rInstructions Left: ${np.diagnosticCount}${" " * program.diagnosticCount.toString.length}") np.diagnosticCount match { case 0 => np case _ => finalState(np) } } println() finalState(program).tape.values.count(_ == 1).toString } override def part2(input: String): String = { "You Win!" } } }