aoc-old/aoc/src/main/scala/aoc/AoC2017.scala

168 lines
5.0 KiB
Scala

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!"
}
}
}