aoc-old/aoc/src/main/scala/aoc/y2017/Day03.scala

71 lines
2.0 KiB
Scala

package aoc.y2017
import aoc._
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 = {
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
}
}