Day 3 y2019

This commit is contained in:
Aly 2019-12-03 19:57:35 -08:00 committed by Anthony Cerruti
parent 214438d779
commit f412003d6f
2 changed files with 103 additions and 0 deletions

View File

@ -0,0 +1,102 @@
package aoc.y2019
import java.util.UUID
import aoc.Day
import cats._
import cats.implicits._
import cats.data.State
object Day03 extends Day {
sealed trait Direction
case object Up extends Direction
case object Down extends Direction
case object Left extends Direction
case object Right extends Direction
case class Move(dir: Direction, spaces: Int) {
val directions = Vector.fill(spaces)(dir)
}
case class Wire(moves: Vector[Move])
import fastparse._, SingleLineWhitespace._
def parseUp[_: P]: P[Up.type] = P("U").map(_ => Up)
def parseDown[_: P]: P[Down.type] = P("D").map(_ => Down)
def parseLeft[_: P]: P[Left.type] = P("L").map(_ => Left)
def parseRight[_: P]: P[Right.type] = P("R").map(_ => Right)
def parseDirection[_: P]: P[Direction] = parseUp | parseDown | parseLeft | parseRight
def parseNumber[_: P]: P[Int] = P(CharIn("0-9").rep(1).!).map(_.toInt)
def parseMove[_: P]: P[Move] = P(parseDirection ~ parseNumber).map {
case (direction, spaces) => Move(direction, spaces)
}
def parseLine[_: P]: P[Vector[Move]] = P(parseMove.rep(1, ",")).map(_.toVector)
case class Coordinate(x: Int, y: Int) {
def move(direction: Direction, times: Int = 1): Coordinate = direction match {
case Up => Coordinate(x, y + times)
case Down => Coordinate(x, y - times)
case Left => Coordinate(x - times, y)
case Right => Coordinate(x + times, y)
}
def manhattanDistance: Int = Math.abs(x) + Math.abs(y)
}
val emptyBoard: Board = (Vector(), Vector())
type Board = (Vector[Coordinate], Vector[Coordinate])
type BoardModification = State[Board, Unit]
def lay(wires: (Wire, Wire)): BoardModification = {
wires match {
case (Wire(leftWireMoves), Wire(rightWireMoves)) =>
val leftWireDirections = leftWireMoves.flatMap(_.directions)
val rightWireDirections = rightWireMoves.flatMap(_.directions)
val leftWireOptions = leftWireDirections.map(Some(_)).padTo(rightWireDirections.length, None)
val rightWireOptions = rightWireDirections.map(Some(_)).padTo(leftWireDirections.length, None)
val moves = leftWireOptions.zip(rightWireOptions)
moves.traverse(move).map(_ => ())
}
}
def move(move: (Option[Direction], Option[Direction])): BoardModification = State.modify {
case (leftWire, rightWire) => move match {
case (leftMove, rightMove) =>
(
leftMove.fold(leftWire)(d => leftWire.appended(leftWire.lastOption.getOrElse(Coordinate(0, 0)).move(d))),
rightMove.fold(rightWire)(d => rightWire.appended(rightWire.lastOption.getOrElse(Coordinate(0, 0)).move(d)))
)
}
}
def endingBoard(input: String): (Vector[Coordinate], Vector[Coordinate]) = {
val Vector(wireOneStr, wireTwoStr) = input.linesIterator.toVector
val wireOne = Wire(parse(wireOneStr, parseLine(_)).get.value)
val wireTwo = Wire(parse(wireTwoStr, parseLine(_)).get.value)
val layWires = lay(wireOne, wireTwo)
val endingBoard: Board = layWires.runS(emptyBoard).value
endingBoard
}
override def part1(input: String): String = {
val (leftCoords, rightCoords) = endingBoard(input)
val intersections = leftCoords.intersect(rightCoords)
intersections.map(_.manhattanDistance).min.toString
}
override def part2(input: String): String = {
val (leftCoords, rightCoords) = endingBoard(input)
val intersections = leftCoords.intersect(rightCoords)
val intersectionSteps = intersections.map(c => leftCoords.indexOf(c) + rightCoords.indexOf(c) + 2)
intersectionSteps.min.toString
}
}

View File

@ -5,6 +5,7 @@ package object y2019 extends Year {
override def days: Map[String, Day] = Map(
"1" -> Day01,
"2" -> Day02,
"3" -> Day03,
)
}