Advent of Code 2024

Day 14 is about robots patrolling the bathroom. Part 2 is an interesting challenge, more of a thought exercise but not really a hard one to code. I thought sure part 2 was gonna require some insanely large number of seconds of movement, so I prepared for that in part 1. It turned out my guess was wrong, but my preparations still helped for part 2. I created a class RobotGrid. For part 1 I had to deal with the negative delta directions in an extra step because Java does some weirdness with negative mods, but otherwise it was fairly straight-forward. Part 2 was even more straight-forward once I came up with an approach to try.

final class RobotGrid
{
  record Coord(int x, int y) {}
  record Vector(Coord location, Coord direction) {}
  
  private final int height;
  private final int width;
  private final List<Vector> robots = new ArrayList<>();

  public RobotGrid(final String[] robotPositionsAndVectors, final int inputHeight, final int inputWidth)
  {
    this.height = inputHeight;
    this.width  = inputWidth;
    parseRobotPositionsAndVectors(robotPositionsAndVectors);
  }

  private static final Pattern ROBOT_VECTOR_LINE = Pattern.compile("p=([0-9]+),([0-9]+) v=([-]?[0-9]+),([-]?[0-9]+)");
  private void parseRobotPositionsAndVectors(final String[] robotPositionsAndVectors)
  {
    for (final String line : robotPositionsAndVectors)
    {
      final Matcher robotPositionAndVector = ROBOT_VECTOR_LINE.matcher(line);
      if (!robotPositionAndVector.matches())  throw new IllegalStateException(line);
      final int x = Integer.parseInt(robotPositionAndVector.group(1));
      final int y = Integer.parseInt(robotPositionAndVector.group(2));
      final int dx = Integer.parseInt(robotPositionAndVector.group(3));
      final int dy = Integer.parseInt(robotPositionAndVector.group(4));
      robots.add(new Vector(new Coord(x, y), new Coord(dx, dy)));
    }
  }

  public long getResultAfterSeconds(int numberOfSeconds)  // part 1
  {
    final int[] counts = new int[5];  // 4 quadrants + centre (which we'll ignore)
    for(final Vector robot : robots)
    {
      final Coord newRobotLocation = moveRobot(robot, numberOfSeconds);
      final int quadrant = getQuadrant(newRobotLocation);
      counts[quadrant]++;
    }
    int result = 1;
    for (int i=0; i<4; i++)
    {
      result *= counts[i];
    }
    return result;
  }

  // Java does some weirdness with mods of negative numbers.  Rather than deal
  // with that, I just used abs() and then added an extra unit of the mod value
  // to pull the number positive again
  private Coord moveRobot(final Vector startLocation, int numberOfSecondsToMove)
  {
    final int x = startLocation.location().x();
    final int y = startLocation.location().y();
    final int dx = startLocation.direction().x(); 
    final int dy = startLocation.direction().y();
    
    int xMove = (Math.abs(dx) * numberOfSecondsToMove) % width;
    if (dx < 0)  xMove = 0 - xMove;
    int yMove = (Math.abs(dy) * numberOfSecondsToMove) % height;
    if (dy < 0)  yMove = 0 - yMove;
    final int newX = (x + xMove + width) % width;
    final int newY = (y + yMove + height) % height;

    return new Coord(newX, newY);
  }

  // The quadrant mapping is almost irrelevant because the numbers will be multiplied 
  private int getQuadrant(final Coord location)
  {
    final int midY = height/2;
    final int midX = width/2;
    final int x = location.x();
    final int y = location.y();
    
    // ignore robots in the middle as instructed
    if ((x == midX) || (y == midY)) return 4;

    if (x < midX)
    {
      if (y < midY)
        return 0;
      else
        return 1;
    }
    if (y < midY)
      return 2;
    else
      return 3;
  }

  public long howLongForXmasTreeEasterEgg()  // part 2
  {
    int robotMovementSeconds = 1;
    Set<Coord> robots = moveRobots(robotMovementSeconds);
    while (!inXmasArrangement(robots))
    {
      robotMovementSeconds++;
      robots = moveRobots(robotMovementSeconds);
    }
    dumpRobots(robots);
    return robotMovementSeconds;
  }

  private Set<Coord> moveRobots(final int numberOfSeconds)
  {
    final Set<Coord> result = new HashSet<>();
    for(final Vector robot : robots)
    {
      final Coord newRobotLocation = moveRobot(robot, numberOfSeconds);
      result.add(newRobotLocation);
    }
    return result;
  }

  // Initial assumption that the easter egg means every robot is in a
  // unique position proved itself out
  private boolean inXmasArrangement(final Set<Coord> robotArrangement)
  {
    if (robotArrangement.size() == robots.size()) return true;
    return false;
  }

  private void dumpRobots(final Set<Coord> robotArrangement)
  {
    for (int y = 0; y < height; y++)
    {
      for (int x = 0; x < width; x++)
      {
        final Coord c = new Coord(x, y);
        if (robotArrangement.contains(c))
          System.out.print("*");
        else
          System.out.print(".");
      }
      System.out.println();
    }
    System.out.println();
  }
}

And here’s the part 2 output

...............................*...........*......................................*..................
...........................................*.......................*.................................
.....................................................................................................
........................................*............................................................
.....................................................................................................
..............................................*................................*.....................
.....................................................................................................
..........................................*......................................*...................
...................................................................*.....................*...........
..............*...................................................*.......*..........................
.........................*................................................................*..........
.................................*...................................................................
.....................................................................................................
..*..................................................................................................
.....................................................................................................
................*.................*......................*...........................................
...........................................*.........................................................
.....................................................................................................
........................................*..................................*.........................
..............*.................................................................*..................*.
.........................................................*...........................................
.....................................................................................................
..........................................................................................*..........
...........................*...................*.................................................*...
...........................*................................................*........................
.....................................................................................................
.......*......................*......................*....*..........................................
.....................................................................................................
............*........................................................................................
................................*........................................*...........................
...........................................................*.........................................
..................................................................*..................................
.....................................................................................................
........................*.......*...............*....................................................
...............................*.................*...............*............................*......
.....................................................................................................
.....................................................................................................
.................................................................................*...................
...*........*.................................*......................................................
...............................................................................................*.....
.....................................................................................................
..........*............*................................*......................................*.....
...................................*..................*.....................*........................
.................................................................................................*...
............................................................................*........................
........................*............*.............*...............*............................*....
...................................................................*.................................
.....................................................................................................
.................................................*******************************.....................
....*..........*.............................*...*.............................*.....................
............*.....*.*............................*.............................*.....................
....................*.........................*..*.............................*.....................
...........*..................................*..*.............................*........*............
.................................................*..............*..............*...............*.....
.................................................*.............***.............*.....................
...........*.....................................*............*****............*.....................
.................*.......*.......................*...........*******...........*.....................
.................................................*..........*********..........*.....................
.............*...................................*............*****............*.............*.......
.................................................*...........*******...........*.....................
.....*...........................................*..........*********..........*..................*..
.................................................*.........***********.........*....*................
...........................*................*....*........*************........*.....................
...........**....................................*..........*********..........*.....................
.......................................*.........*.........***********.........*.....................
.................................................*........*************........*.....................
.................................................*.......***************.......*.....................
.................................................*......*****************......*.....................
.................................................*........*************........*.....................
.................................................*.......***************.......*.....................
.................................................*......*****************......*.....................
.................................................*.....*******************.....*...............*.....
.................................................*....*********************....*.....................
........................................*........*.............***.............*.....................
............................*....................*.............***.............*...........*....*....
......................................*........*.*.............***.............*.....................
.................................................*.............................*.....................
.................................................*.............................*.....................
.................................................*.............................*....*................
.................................................*.............................*.....................
..............................*.........*........*******************************.....................
.....................................*...............................................*...............
...............................................*.......*...*....................*....................
.......*.......................*.....................................................................
...................................*...........................................*.....................
................................*....*...............................................................
........................................................*...............*...........*................
.....................................................................................................
.........................*.........................*...........................*.....................
.....................................................................................................
............................*..............................*..........*..............................
.....................................................................................................
.....................................................................................................
.........................*.....................*.....................................................
.....................................................................................................
..............................*......................**.......*......................................
..............................................................*.....*............**..........*.......
............................*................................*.....*.................................
.....................................................................................................
..............*......................................................................................
...................*.................................................................*...............
*...............................*....................................................................
.............................................*.......................................................

The runtime was pretty reasonable

Part 1: 0.0110099s
Part 2: 0.2041993s
1 Like