[javascript] Advent Of Code 2022 Day 23 Part 2

Viewer

copydownloadembedprintName: Advent Of Code 2022 Day 23 Part 2
  1. // 3:6 weird
  2.  
  3. const hash = (x: number, y: number): string => `${x}:${y}`;
  4. const unHash = (h: string): IRawPosition => {
  5.   const [x, y] = h.split(":").map(Number);
  6.   return { x, y };
  7. };
  8.  
  9. const parse = (lines: string[]): IPositions => {
  10.   const positions: IPositions = {};
  11.  
  12.   for (let y = 0; y < lines.length; y++) {
  13.     const line = lines[y];
  14.  
  15.     for (let x = 0; x < line.length; x++) {
  16.       const char = line[x];
  17.  
  18.       if (char === "#") {
  19.         positions[hash(x, y)] = {
  20.           priority: [
  21.             EDirection.NORTH,
  22.             EDirection.SOUTH,
  23.             EDirection.WEST,
  24.             EDirection.EAST,
  25.           ],
  26.           decision: EDirection.NONE,
  27.           duplicate: false,
  28.         };
  29.       }
  30.     }
  31.   }
  32.  
  33.   return positions;
  34. };
  35.  
  36. const markDuplicateDecisions = (positions: IPositions) => {
  37.   const counts: { [h: string]: number } = {};
  38.  
  39.   for (let h in positions) {
  40.     if (positions.hasOwnProperty(h)) {
  41.       const { decision } = positions[h];
  42.       const pos = unHash(h);
  43.       const targetPos = movePosition(pos, decision);
  44.       const targetH = hash(targetPos.x, targetPos.y);
  45.  
  46.       counts[targetH] = counts[targetH] ? counts[targetH] + 1 : 1;
  47.     }
  48.   }
  49.  
  50.   for (let h in positions) {
  51.     if (positions.hasOwnProperty(h)) {
  52.       const position = positions[h];
  53.       const pos = unHash(h);
  54.       const targetPos = movePosition(pos, position.decision);
  55.       const targetH = hash(targetPos.x, targetPos.y);
  56.       position.duplicate = counts[targetH] > 1;
  57.     }
  58.   }
  59. };
  60.  
  61. const isSomeoneClose = (h: string, positions: IPositions) => {
  62.   const pos = unHash(h);
  63.  
  64.   const dependencies = [
  65.     EDirection.NORTH,
  66.     EDirection.EAST,
  67.     EDirection.SOUTH,
  68.     EDirection.WEST,
  69.   ]
  70.     .flatMap((direction) => getDependencyPositions(pos, direction))
  71.     .filter(
  72.       (item, index, data) => data.findIndex((test) => test === item) === index
  73.     );
  74.  
  75.   return Boolean(
  76.     dependencies.find(({ x, y }) => positions[hash(x, y)] !== undefined)
  77.   );
  78. };
  79.  
  80. const makeInitialDecision = (h: string, positions: IPositions) => {
  81.   const pos = unHash(h);
  82.   const position = positions[h];
  83.  
  84.   const needMove = isSomeoneClose(h, positions);
  85.  
  86.   const decision = needMove
  87.     ? position.priority.find((potentialDecision) => {
  88.         const dependencies = getDependencyPositions(pos, potentialDecision);
  89.  
  90.         return dependencies.every(
  91.           ({ x, y }) => positions[hash(x, y)] === undefined
  92.         );
  93.       }) ?? EDirection.NONE
  94.     : EDirection.NONE;
  95.  
  96.   position.decision = decision;
  97. };
  98.  
  99. const makeInitialDecisions = (positions: IPositions) => {
  100.   for (let h in positions) {
  101.     if (positions.hasOwnProperty(h)) {
  102.       makeInitialDecision(h, positions);
  103.     }
  104.   }
  105. };
  106.  
  107. const downgradeChosenDecisions = (positions: IPositions) => {
  108.   for (let h in positions) {
  109.     if (positions.hasOwnProperty(h)) {
  110.       const position = positions[h];
  111.  
  112.       const priority = position.priority.shift();
  113.       position.priority.push(priority as EDirection);
  114.  
  115.       // if (position.decision !== EDirection.NONE) {
  116.       //   const decisionIndex = position.priority.findIndex(
  117.       //     (item) => item === position.decision
  118.       //   );
  119.  
  120.       //   position.priority.splice(decisionIndex, 1);
  121.       //   position.priority.push(position.decision);
  122.       // }
  123.     }
  124.   }
  125. };
  126.  
  127. const getDependencyPositions = (
  128.   pos: IRawPosition,
  129.   direction: EDirection
  130. ): IRawPosition[] => {
  131.   if (direction === EDirection.NORTH) {
  132.     return [
  133.       { x: pos.x, y: pos.y - 1 },
  134.       { x: pos.x - 1, y: pos.y - 1 },
  135.       { x: pos.x + 1, y: pos.y - 1 },
  136.     ];
  137.   } else if (direction === EDirection.EAST) {
  138.     return [
  139.       { x: pos.x + 1, y: pos.y },
  140.       { x: pos.x + 1, y: pos.y - 1 },
  141.       { x: pos.x + 1, y: pos.y + 1 },
  142.     ];
  143.   } else if (direction === EDirection.SOUTH) {
  144.     return [
  145.       { x: pos.x, y: pos.y + 1 },
  146.       { x: pos.x - 1, y: pos.y + 1 },
  147.       { x: pos.x + 1, y: pos.y + 1 },
  148.     ];
  149.   } else if (direction === EDirection.WEST) {
  150.     return [
  151.       { x: pos.x - 1, y: pos.y },
  152.       { x: pos.x - 1, y: pos.y - 1 },
  153.       { x: pos.x - 1, y: pos.y + 1 },
  154.     ];
  155.   }
  156.  
  157.   return [];
  158. };
  159.  
  160. const movePosition = (
  161.   pos: IRawPosition,
  162.   direction: EDirection
  163. ): IRawPosition => {
  164.   if (direction === EDirection.NORTH) {
  165.     return { x: pos.x, y: pos.y - 1 };
  166.   } else if (direction === EDirection.EAST) {
  167.     return { x: pos.x + 1, y: pos.y };
  168.   } else if (direction === EDirection.SOUTH) {
  169.     return { x: pos.x, y: pos.y + 1 };
  170.   } else if (direction === EDirection.WEST) {
  171.     return { x: pos.x - 1, y: pos.y };
  172.   }
  173.  
  174.   return pos;
  175. };
  176.  
  177. const moveItem = (h: string, positions: IPositions) => {
  178.   const pos = unHash(h);
  179.   const position = positions[h];
  180.   const { decision, duplicate } = position;
  181.  
  182.   if (decision !== EDirection.NONE && !duplicate) {
  183.     const { x, y } = movePosition(pos, decision);
  184.     delete positions[h];
  185.     const newH = hash(x, y);
  186.     positions[newH] = position;
  187.  
  188.     // console.log(`${h} -> ${newH}`);
  189.   }
  190. };
  191.  
  192. const moveItems = (positions: IPositions) => {
  193.   for (let h in positions) {
  194.     if (positions.hasOwnProperty(h)) {
  195.       moveItem(h, positions);
  196.     }
  197.   }
  198. };
  199.  
  200. const getBoundingRectangle = (positions: IPositions): IBoundingRectangle => {
  201.   let minX = Infinity;
  202.   let minY = Infinity;
  203.   let maxX = -Infinity;
  204.   let maxY = -Infinity;
  205.  
  206.   for (let h in positions) {
  207.     if (positions.hasOwnProperty(h)) {
  208.       const { x, y } = unHash(h);
  209.  
  210.       if (< minX) {
  211.         minX = x;
  212.       }
  213.  
  214.       if (> maxX) {
  215.         maxX = x;
  216.       }
  217.  
  218.       if (< minY) {
  219.         minY = y;
  220.       }
  221.  
  222.       if (> maxY) {
  223.         maxY = y;
  224.       }
  225.     }
  226.   }
  227.  
  228.   return { minX, minY, maxX, maxY };
  229. };
  230.  
  231. const getBoundingEmptySpaces = (positions: IPositions): number => {
  232.   const { minX, minY, maxX, maxY } = getBoundingRectangle(positions);
  233.  
  234.   let count = 0;
  235.  
  236.   for (let x = minX; x <= maxX; x++) {
  237.     for (let y = minY; y <= maxY; y++) {
  238.       if (positions[hash(x, y)] === undefined) {
  239.         count++;
  240.       }
  241.     }
  242.   }
  243.  
  244.   return count;
  245. };
  246.  
  247. const print = (positions: IPositions) => {
  248.   const { minX, maxX, minY, maxY } = getBoundingRectangle(positions);
  249.  
  250.   console.log("");
  251.  
  252.   for (let y = minY; y <= maxY; y++) {
  253.     for (let x = minX; x <= maxX; x++) {
  254.       process.stdout.write(positions[hash(x, y)] === undefined ? "." : "#");
  255.     }
  256.  
  257.     process.stdout.write("\n");
  258.   }
  259.  
  260.   console.log("\n");
  261. };
  262.  
  263. export const solution = async (lines: string[]) => {
  264.   const positions = parse(lines);
  265.  
  266.   // print(positions);
  267.  
  268.   let initialHash = "";
  269.   let finalHash = "";
  270.  
  271.   let iterations = 0;
  272.  
  273.   do {
  274.     iterations++;
  275.     initialHash = Object.keys(positions).join(" ");
  276.     makeInitialDecisions(positions);
  277.     markDuplicateDecisions(positions);
  278.     moveItems(positions);
  279.     downgradeChosenDecisions(positions);
  280.     // print(positions);
  281.     finalHash = Object.keys(positions).join(" ");
  282.   } while (initialHash !== finalHash);
  283.  
  284.   return iterations;
  285. };
  286.  
  287. enum EDirection {
  288.   NORTH = "N",
  289.   EAST = "E",
  290.   SOUTH = "S",
  291.   WEST = "W",
  292.   NONE = "-",
  293. }
  294.  
  295. interface IPosition {
  296.   decision: EDirection;
  297.   priority: EDirection[];
  298.   duplicate: boolean;
  299. }
  300.  
  301. interface IPositions {
  302.   [hash: string]: IPosition;
  303. }
  304.  
  305. interface IBoundingRectangle {
  306.   minX: number;
  307.   minY: number;
  308.   maxX: number;
  309.   maxY: number;
  310. }
  311.  
  312. interface IRawPosition {
  313.   x: number;
  314.   y: number;
  315. }
  316.  

Editor

You can edit this paste and save as new:


File Description
  • Advent Of Code 2022 Day 23 Part 2
  • Paste Code
  • 23 Dec-2022
  • 7.39 Kb
You can Share it: