Day 3 y2019
This commit is contained in:
parent
214438d779
commit
f412003d6f
2 changed files with 103 additions and 0 deletions
102
aoc/src/main/scala/aoc/y2019/Day03.scala
Normal file
102
aoc/src/main/scala/aoc/y2019/Day03.scala
Normal 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
|
||||
}
|
||||
|
||||
}
|
|
@ -5,6 +5,7 @@ package object y2019 extends Year {
|
|||
override def days: Map[String, Day] = Map(
|
||||
"1" -> Day01,
|
||||
"2" -> Day02,
|
||||
"3" -> Day03,
|
||||
)
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue