Day 05

import Solution from "./solution.ts";

function emptyRule() {
  return { before: new Set<number>(), after: new Set<number>() };
}

function createRules(arr: number[][]) {
  const rules = new Map<
    number,
    { before: Set<number>; after: Set<number> }
  >();
  for (const r of arr) {
    const prev = rules.get(r[0]) ?? emptyRule();

    prev.after.add(r[1]);
    rules.set(r[0], prev);
    const next = rules.get(r[1]) ?? emptyRule();
    next.before.add(r[0]);
    rules.set(r[1], next);
  }
  return rules;
}

function checkPage(
  i: number,
  pages: number[],
  rules: ReturnType<typeof createRules>,
) {
  const n = pages[i];
  const nonPrev = pages.slice(0, i).every((p) =>
    !(rules.get(n) ?? emptyRule()).after.has(
      p,
    )
  );
  const nonNext = pages.slice(i + 1).every((p) =>
    !(rules.get(n) ?? emptyRule()).before.has(
      p,
    )
  );
  return (nonNext && nonPrev);
}

function checkRules(
  rules: ReturnType<typeof createRules>,
  pages: number[][],
  pass = true,
) {
  const correct = pages.filter((u) =>
    u.every((_, i, arr) => checkPage(i, arr, rules)) === pass
  );
  return correct;
}

function fixPages(rules: ReturnType<typeof createRules>, pages: number[]) {
  const correct: number[] = [];
  for (let i = 0; i < pages.length; i++) {
    for (let k = 0; k <= correct.length; k++) {
      correct.splice(correct.length - k, 0, pages[i]);
      if (!checkPage(i - k, correct, rules)) {
        correct.splice(correct.length - k - 1, 1);
      } else {
        break;
      }
    }
  }
  return correct;
}

const task = new Solution(
  (arr: number[][][]) => {
    const rules = createRules(arr[0]);
    const correct = checkRules(rules, arr[1]);
    return correct.reduce((p, c) => p + c[(c.length - 1) / 2], 0);
  },
  (arr: number[][][]) => {
    const rules = createRules(arr[0]);
    const incorrect = checkRules(rules, arr[1], false);
    return incorrect.reduce(
      (p, c) => p + fixPages(rules, c)[(c.length - 1) / 2],
      0,
    );
  },
  {
    sep: "\n\n",
    transform: (s, i) => {
      return s.split("\n").map((l) =>
        l.split(i === 0 ? "|" : ",").map((n) => Number.parseInt(n))
      );
    },
  },
);
task.expect(143, 123);

export default task;

Last edited 04. April 2025 13:29