75 lines
2.2 KiB
Scala
75 lines
2.2 KiB
Scala
package aoc.y2017
|
|
|
|
import aoc.Day
|
|
|
|
object Day03 extends Day {
|
|
|
|
override def part1(input: String): String = {
|
|
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 = {
|
|
implicit class TupleInt2Ops(t: (Int, Int)) {
|
|
def +(o: (Int, Int)): (Int, Int) = (t, o) match {
|
|
case ((x1, y1), (x2, y2)) => (x1 + x2, y1 + y2)
|
|
}
|
|
}
|
|
sealed trait Direction {
|
|
def change: (Int, Int)
|
|
}
|
|
case object MoveUp extends Direction {
|
|
override def change: (Int, Int) = (0, 1)
|
|
}
|
|
case object MoveRight extends Direction {
|
|
override def change: (Int, Int) = (1, 0)
|
|
}
|
|
case object MoveDown extends Direction {
|
|
override def change: (Int, Int) = (0, -1)
|
|
}
|
|
case object MoveLeft extends Direction {
|
|
override def change: (Int, Int) = (-1, 0)
|
|
}
|
|
def sumOfSurrounding(p: (Int, Int), m: Map[(Int, Int), Int]): Int = {
|
|
val surrounding = List(
|
|
(-1, 1),
|
|
(0, 1),
|
|
(1, 1),
|
|
(-1, 0), /* */ (1, 0),
|
|
(-1, -1),
|
|
(0, -1),
|
|
(1, -1)
|
|
)
|
|
surrounding.map(o => m.getOrElse(p + o, 0)).sum
|
|
}
|
|
lazy val movementStream: Stream[Int] = Stream.from(1).flatMap(i => Stream(i, i))
|
|
lazy val directionStream: Stream[Direction] = MoveRight #:: MoveUp #:: MoveLeft #:: MoveDown #:: directionStream
|
|
lazy val pathStream = movementStream.zip(directionStream).flatMap {
|
|
case (times, dir) => Stream.fill(times)(dir)
|
|
}
|
|
lazy val pathIterator = pathStream.toIterator
|
|
val targetNum = input.toInt
|
|
def findNext(m: Map[(Int, Int), Int] = Map((0, 0) -> 1), p: (Int, Int) = (0, 0), i: Iterator[Direction]): Int = {
|
|
val nd = i.next()
|
|
val np = p + nd.change
|
|
val sum = sumOfSurrounding(np, m)
|
|
val nm = m + (np -> sum)
|
|
if (sum > targetNum) {
|
|
sum
|
|
} else {
|
|
findNext(nm, np, i)
|
|
}
|
|
}
|
|
findNext(i = pathIterator).toString
|
|
}
|
|
|
|
}
|