Day 08

import Solution from "./solution.ts";

function inBounds(point: [number, number], bound: [number, number]) {
  return point.every((e, i) => e >= 0 && e < bound[i]);
}

function findAntidote(
  coords: [number, number][],
  bounds: [number, number],
  second = false,
): Set<string> {
  const antidotes = new Set<string>();
  const [stable, ...rest] = coords;
  for (const coord of rest) {
    const d = [stable[0] - coord[0], stable[1] - coord[1]];
    if (!second) {
      for (const sign of [-1, 2]) {
        const p = [stable[0] + (sign * d[0]), stable[1] + (sign * d[1])];
        antidotes.add(p.join(","));
      }
    } else {
      for (const sign of [-1, 1]) {
        for (
          let i = 0, p = stable;
          inBounds(p, bounds);
          i++,
            p = [stable[0] + (sign * i * d[0]), stable[1] + (sign * i * d[1])]
        ) {
          antidotes.add(p.join(","));
        }
      }
    }
  }
  return rest.length === 1
    ? antidotes
    : antidotes.union(findAntidote(rest, bounds, second));
}

function solve(arr: string[][], second = false) {
  const points = new Map<string, [number, number][]>();
  arr.forEach((l, x) =>
    l.forEach((c, y) => {
      if (c !== ".") {
        points.set(c, [...(points.get(c) ?? []), [x, y]]);
      }
    })
  );
  return points.values().reduce(
    (p, c) => p.union(findAntidote(c, [arr.length, arr[0].length], second)),
    new Set<string>(),
  ).size;
}

const task = new Solution(
  (arr: string[][]) => solve(arr),
  (arr: string[][]) => solve(arr, true),
  {
    sep: "\n",
    transform: (s) => s.split(""),
  },
);
task.expect(14, 34);

export default task;

Last edited 04. April 2025 13:29