TechWorkRamblings

by Mike Kalvas

202412040000 Advent of Code 2024 Day 04

Ceres Search

Today were visiting the Ceres monitoring station from 2019 day 10 and helping the station chief solve her word searches.

#blog #project

The Puzzle

Today were visiting the Ceres monitoring station from 2019 day 10 and helping the station chief solve her word searches.

We get a grid of letters and need to find sequences of the word XMAS in it. We follow typical word search rules and allow words to go up, down, forwards, backwards, and on diagonals.

Solution

I know there’s a way to just regex the answer directly. I saw a particularly inscrutable, code-golfed solution that was pretty cool on the subreddit after finishing my version. But I couldn’t be bothered with any of that and just grug-brained it. I’m not a big fan of the days where the main challenge is just tracking indexes around grids. I kind of wanted to just finish it and move on.

const solve = (input) => {
  let sum = 0;
  const g = input.map(chars);
  for (const [y, r] of g.entries()) {
    for (const [x, c] of r.entries()) {
      const words = { lr: '', td: '', dr: '', dl: '' };

      if (c === 'X' || c === 'S') {
        words.lr = g[y][x] + g[y][x + 1] + g[y][x + 2] + g[y][x + 3];
        if (y < g.length - 3) {
          words.td = g[y][x] + g[y + 1][x] + g[y + 2][x] + g[y + 3][x];
          words.dr =
            g[y][x] + g[y + 1][x + 1] + g[y + 2][x + 2] + g[y + 3][x + 3];
          words.dl =
            g[y][x] + g[y + 1][x - 1] + g[y + 2][x - 2] + g[y + 3][x - 3];
        }
      }

      const ws = vals(words);
      sum += ws.count('XMAS') + ws.count('SAMX');
    }
  }
  return sum;
};

The second part changed up the “word” we were searching for. Instead of searching for XMAS, we’re searching for MAS in an X formation. For example,

M S
 A
M S

Once again, these can be in any combination of direction, it’s just about the three letters being in the sequence and the whole formation being present.

Luckily, the way I wrote the code for the first part let me insert some changes and extract the solution, only parameterizing over the comparison function for summing matches.

- const solve = (input) => {
+ const solve = (input, countFn) => {
  let sum = 0;
  const g = input.map(chars);
  for (const [y, r] of g.entries()) {
    for (const [x, c] of r.entries()) {
-     const words = { lr: '', td: '', dr: '', dl: '' };
+     const words = { lr: '', td: '', dr: '', dl: '', xl: '', xr: '' };

      if (c === 'X' || c === 'S') {
        words.lr = g[y][x] + g[y][x + 1] + g[y][x + 2] + g[y][x + 3];
        if (y < g.length - 3) {
          words.td = g[y][x] + g[y + 1][x] + g[y + 2][x] + g[y + 3][x];
          words.dr =
            g[y][x] + g[y + 1][x + 1] + g[y + 2][x + 2] + g[y + 3][x + 3];
          words.dl =
            g[y][x] + g[y + 1][x - 1] + g[y + 2][x - 2] + g[y + 3][x - 3];
        }
      }

+     if (c === 'A' && 0 < y && y < g.length - 1) {
+       words.xl = g[y - 1][x - 1] + g[y][x] + g[y + 1][x + 1];
+       words.xr = g[y - 1][x + 1] + g[y][x] + g[y + 1][x - 1];
+     }

-     const ws = vals(words);
-     sum += ws.count('XMAS') + ws.count('SAMX');
+     sum += countFn(words);
    }
  }
  return sum;
export const solutionOne = (input) =>
  solve(input, (words) => {
    const ws = vals(words);
    return ws.count('XMAS') + ws.count('SAMX');
  });

export const solutionTwo = (input) =>
  solve(input, (ws) => {
    return +(['MAS', 'SAM'].includes(ws.xl) && ['MAS', 'SAM'].includes(ws.xr));
  });

I was not feeling this puzzle. Historically, I haven’t enjoyed the grid walking, index management type puzzles as much as other days. Hopefully we get something a little more intriguing tomorrow.

You can find the full solutions to today's AoC puzzles in my AoC GitHub repo.