|
| 1 | +package day14 |
| 2 | + |
| 3 | +import locations.Directory.currentDir |
| 4 | +import inputs.Input.loadFileSync |
| 5 | + |
| 6 | +@main def part1: Unit = |
| 7 | + println("The solution is ${part1(loadInput())}") |
| 8 | + |
| 9 | +@main def part2: Unit = |
| 10 | + println("The solution is ${part2(loadInput())}") |
| 11 | + |
| 12 | +def loadInput(): String = loadFileSync(s"$currentDir/../input/day14") |
| 13 | + |
| 14 | +case class Vec2i(x: Int, y: Int) |
| 15 | + |
| 16 | +val size = Vec2i(101, 103) |
| 17 | + |
| 18 | +extension (self: Int) |
| 19 | + infix def rem(that: Int): Int = |
| 20 | + val m = math.abs(self) % that |
| 21 | + if self < 0 then |
| 22 | + that - m |
| 23 | + else |
| 24 | + m |
| 25 | + |
| 26 | +case class Robot(pos: Vec2i, velocity: Vec2i) |
| 27 | + def stepN(n: Int = 1): Robot = |
| 28 | + copy(pos = pos.copy(x = (pos.x + n * velocity.x) rem size.x, y = (pos.y + n * velocity.y) rem size.y)) |
| 29 | + |
| 30 | +def parse(str: String): List[Robot] = |
| 31 | + str.linesIterator.map { |
| 32 | + case s"p=$px,$py v=$vx,$vy" => |
| 33 | + Robot(Vec2i(px.toInt, py.toInt), Vec2i(vx.toInt, vy.toInt)) |
| 34 | + }.toList |
| 35 | + |
| 36 | +extension (robots: List[Robot]) { |
| 37 | + def stepN(n: Int = 1): List[Robot] = robots.map(_.stepN(n)) |
| 38 | + |
| 39 | + def safety: Int = |
| 40 | + val middleX = size.x / 2 |
| 41 | + val middleY = size.y / 2 |
| 42 | + |
| 43 | + robots.groupBy { robot => |
| 44 | + (robot.pos.x.compareTo(middleX), robot.pos.y.compareTo(middleY)) match |
| 45 | + case (0, _) | (_, 0) => -1 |
| 46 | + case ( 1, -1) => 0 |
| 47 | + case (-1, -1) => 1 |
| 48 | + case (-1, 1) => 2 |
| 49 | + case ( 1, 1) => 3 |
| 50 | + }.removed(-1).values.map(_.length).product |
| 51 | + |
| 52 | + def findEasterEgg: Int = |
| 53 | + (0 to 10403).find { i => |
| 54 | + val newRobots = robots.stepN(i) |
| 55 | + newRobots.groupBy(_.pos.y).count(_._2.length >= 10) > 15 && newRobots.groupBy(_.pos.x).count(_._2.length >= 15) >= 3 |
| 56 | + }.getOrElse(-1) |
| 57 | +} |
| 58 | + |
| 59 | +def part1(input: String): Int = parse(input).stepN(100).safety |
| 60 | + |
| 61 | +def part2(input: String): Int = parse(input).findEasterEgg |
0 commit comments