From 9b2acceba1514be34f1ee6e9f60f07da3542704e Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Sat, 14 Dec 2024 09:15:46 +0200 Subject: [PATCH] Clean up 2024 day 14 --- .../eu/sim642/adventofcode2024/Day14.scala | 45 +++++-- .../sim642/adventofcode2024/Day14Test.scala | 114 +++++++++++++++++- 2 files changed, 145 insertions(+), 14 deletions(-) diff --git a/src/main/scala/eu/sim642/adventofcode2024/Day14.scala b/src/main/scala/eu/sim642/adventofcode2024/Day14.scala index 3a6b99e1..dffe69f3 100644 --- a/src/main/scala/eu/sim642/adventofcode2024/Day14.scala +++ b/src/main/scala/eu/sim642/adventofcode2024/Day14.scala @@ -9,28 +9,44 @@ object Day14 { // copied from 2021 day 25 extension (pos: Pos) { def %+(other: Pos): Pos = Pos(pos.x %+ other.x, pos.y %+ other.y) + infix def compareTo(other: Pos): Pos = Pos(pos.x `compareTo` other.x, pos.y `compareTo` other.y) + def sign: Pos = Pos(pos.x.sign, pos.y.sign) } case class Robot(pos: Pos, velocity: Pos) { + def step(roomSize: Pos): Robot = Robot((pos + velocity) %+ roomSize, velocity) def step(t: Int, roomSize: Pos): Robot = Robot((pos + t *: velocity) %+ roomSize, velocity) } - def safetyFactor(robots: Seq[Robot], roomSize: Pos = Pos(101, 103)): Int = { + val inputRoomSize: Pos = Pos(101, 103) + + def safetyFactor(robots: Seq[Robot], roomSize: Pos = inputRoomSize): Int = { val newRobots = robots.map(_.step(100, roomSize)) - //newRobots.foreach(println) val roomMiddle = Pos(roomSize.x / 2, roomSize.y / 2) - //println(roomMiddle) - //val quadrants0 = newRobots.groupBy(robot => (robot.pos.x.compare(roomMiddle.x), robot.pos.y.compare(roomMiddle.y))).withDefaultValue(0) - //quadrants0.foreach(println) - val quadrants = newRobots.groupCount(robot => (robot.pos.x.compare(roomMiddle.x), robot.pos.y.compare(roomMiddle.y))).withDefaultValue(0) - quadrants((1, 1)) * quadrants((-1, 1)) * quadrants((1, -1)) * quadrants((-1, -1)) + val quadrants = newRobots.groupCount(robot => + (robot.pos `compareTo` roomMiddle).sign // use .sign to clamp to -1, 0, 1 + ).withDefaultValue(0) + Pos.diagonalOffsets.map(quadrants).product } - def findEasterEgg(robots: Seq[Robot], roomSize: Pos = Pos(101, 103)): Int = { - Iterator.from(0) - .map(t => robots.map(_.step(t, roomSize))) // TODO: optimize - .map(newRobots => newRobots.groupCount(_.pos)) - .indexWhere(_.values.forall(_ <= 1)) // look for arrangement with unique positions + def findEasterEgg(robots: Seq[Robot], roomSize: Pos = inputRoomSize): (Seq[Robot], Int) = { + Iterator.iterate(robots)(_.map(_.step(roomSize))) + .zipWithIndex + .find(_._1.groupCount(_.pos).values.forall(_ <= 1)) // look for arrangement with unique positions + // TODO: optimize by stopping groupCount when some goes over 1 + .get + } + + def printRobots(robots: Seq[Robot], roomSize: Pos = inputRoomSize): Unit = { + val posRobots = robots.groupCount(_.pos) + + for (y <- 0 until roomSize.y) { + for (x <- 0 until roomSize.x) { + val pos = Pos(x, y) + print(posRobots.get(pos).map(count => ('0' + count).toChar).getOrElse('.')) // TODO: toDigit? + } + println() + } } def parseRobot(s: String): Robot = s match { @@ -44,6 +60,9 @@ object Day14 { def main(args: Array[String]): Unit = { println(safetyFactor(parseRobots(input))) - println(findEasterEgg(parseRobots(input))) + + val (easterEggRobots, easterEggTime) = findEasterEgg(parseRobots(input)) + printRobots(easterEggRobots) + println(easterEggTime) } } diff --git a/src/test/scala/eu/sim642/adventofcode2024/Day14Test.scala b/src/test/scala/eu/sim642/adventofcode2024/Day14Test.scala index 1cd1a2fd..b92e78fe 100644 --- a/src/test/scala/eu/sim642/adventofcode2024/Day14Test.scala +++ b/src/test/scala/eu/sim642/adventofcode2024/Day14Test.scala @@ -4,6 +4,8 @@ import Day14.* import eu.sim642.adventofcodelib.pos.Pos import org.scalatest.funsuite.AnyFunSuite +import java.io.ByteArrayOutputStream + class Day14Test extends AnyFunSuite { val exampleInput = @@ -29,6 +31,116 @@ class Day14Test extends AnyFunSuite { } test("Part 2 input answer") { - assert(findEasterEgg(parseRobots(input)) == 7093) + val (easterEggRobots, easterEggTime) = findEasterEgg(parseRobots(input)) + assert(easterEggTime == 7093) + + val out = new ByteArrayOutputStream() + Console.withOut(out) { + printRobots(easterEggRobots) + } + assert(out.toString.trim == + """.........................1........................................................................... + |..............................1...................................................................... + |.....................................................................................1.........1..... + |..............................................1.........................................1............ + |..................................................................................................... + |.1.............1..................................................................................... + |..................................................................................................... + |......1.....1.......................................................1...................1............ + |1.........................................................................1.......................... + |..........................................1.......................................................... + |..................................................................................................... + |..............................................................................1................1..... + |................................1...1...............1..............................1................. + |....................1................................................................................ + |.......................1........................................................1.................... + |...........1...........1.....................1....................................................... + |...................................................1..........1...................................... + |..................1...........1...................................................................1.. + |..................................................................................................... + |.................1...........................1....................................................... + |................1..1................................1................................................ + |..................................................................................................... + |..................................................................................................... + |............................1.1.....1111111111111111111111111111111.................................. + |.1..................................1.............................1.................................. + |....................................1.............................1.................................. + |...1................................1.............................1..........................1....... + |..........................1.........1.............................1...................1.............. + |....................................1..............1..............1.................................. + |...............................1....1.............111.............1.................................. + |....................................1............11111............1.................................. + |....................................1...........1111111...........1......................1........1.. + |....................................1..........111111111..........1............1................1.... + |....................................1............11111............1........1......................... + |....................................1...........1111111...........1.................................. + |.....................1............1.1..........111111111..........1.1............................1... + |....................................1.........11111111111.........1.................................. + |....................................1........1111111111111........1.................................. + |....................................1..........111111111..........1.1..................11............ + |....................................1.........11111111111.........1.................................. + |....................................1........1111111111111........1.................................. + |......................1.............1.......111111111111111.......1.................................. + |.......1............................1......11111111111111111......1.................................. + |...........1..1.....................1........1111111111111........1................1................. + |....................................1.......111111111111111.......1...........................1...... + |....................................1......11111111111111111......1.....1.................1.......... + |......1.............................1.....1111111111111111111.....1..........1....................... + |................1...................1....111111111111111111111....1...................1.............. + |..................................1.1.............111.............1.................................. + |....................................1.............111.............1......1........................... + |....................................1.............111.............1.................................. + |....................................1.............................1.................................. + |............................1.......1.............................1.................................. + |....................................1.............................1.................................. + |...............1....................1.............................1..............1................... + |..............1.........1...........1111111111111111111111111111111.....................1............ + |...........................1........................................1................................ + |....................1.....1................1..........................1.............................. + |............................1........................................................................ + |...............................................................................................1..... + |.........................1......................................1.................................... + |.........................................................................1...1....................... + |............................................1........................................................ + |.............................................................................1........1.............. + |..................................................................................................... + |..................................................................................................... + |...1............................................1..............1..................................... + |..................................................................................................... + |..................................................................................................... + |....................................................................................1............1... + |..................................................................1.................................. + |................................1.......................1............................................ + |..................................................................................................... + |......................1.............................................................................. + |..............................1............1......................................................... + |..............................................................1...................................... + |................................................................1.................................... + |......................................1............................1....................1............ + |..................................................................................................... + |..................................................................................................... + |.........................................................................1....................1...... + |....................................1.......1............1.......1.........................1......... + |..................................................................................................... + |...................................1................................1................................ + |..........................................................................1.......................... + |.....................................................................1.........1.................1... + |........................................1...........1...................1............................ + |.................................................................1....1.............................. + |...........................................1......................................................... + |..................................................................................................... + |.1....1............................................................................1................. + |.........................................................1........................................... + |..........................................................................................1.......... + |...................................1........................................................1........ + |........................1......................................1..........................1.1........ + |.......1..................................................................1.........................1 + |..................................................................................................... + |..................................................................................................... + |..................................................................1................................1. + |.........................................................................1........................... + |..........................1.......................................................................... + |.................................................................1................................... + |...........1.........................................................................................""".stripMargin) } }