advent-of-code

Entries to advent of code, multiple years
git clone git://git.finwo.net/misc/advent-of-code
Log | Files | Refs

index.js (2765B)


      1 #!/usr/bin/env node
      2 
      3 const fs = require('node:fs');
      4 
      5 const grid = fs
      6   .readFileSync('input', 'utf-8')
      7   .split('\r\n').join('\n')
      8   .split('\r').join('\n')
      9   .split('\n')
     10   .map(str => str.trim())
     11   .filter(str => str)
     12   .map(str => str.split(''))
     13   .map(row => row.map(c => c === '@'))
     14   ;
     15 
     16 const buildNeighbours = (grid) => {
     17   const neighbours = grid
     18     .map(row => row.map(() => 0));
     19 
     20   // Mark adjacent locations as having 'current' as neighbour
     21   for(let y = 0; y < grid.length; y++) {
     22     const row = grid[y];
     23     for(let x = 0; x < row.length ; x++) {
     24       // Skip if we're empty
     25       if (!grid[y][x]) continue;
     26       for(let ny = -1; ny <= 1; ny++) {
     27         if ((y+ny) < 0) continue;
     28         if ((y+ny) >= grid.length) continue;
     29         for(let nx = -1; nx <= 1; nx++) {
     30           if ((x+nx) < 0) continue;
     31           if ((x+nx) >= row.length) continue;
     32           // Skip self
     33           if (nx === 0 && ny === 0) continue;
     34           neighbours[y+ny][x+nx]++;
     35         }
     36       }
     37     }
     38   }
     39 
     40   return neighbours;
     41 };
     42 
     43 const buildReachable = (grid, neighbours) => {
     44   // Mark reachable rolls in part 1
     45   let count = 0;
     46   const _map = grid.map(row => row.map(() => false));
     47   for(let y = 0; y < grid.length; y++) {
     48     const row = grid[y];
     49     for(let x = 0; x < row.length ; x++) {
     50       // Skip if we're empty
     51       if (!grid[y][x]) continue;
     52       if (neighbours[y][x] >= 4) continue;
     53       _map[y][x] = true;
     54       count++;
     55     }
     56   }
     57   return {
     58     _map,
     59     count,
     60   };
     61 };
     62 
     63 const removeReachable = (grid, reachableMap) => {
     64   for(let y = 0; y < grid.length; y++) {
     65     const row = grid[y];
     66     for(let x = 0; x < row.length ; x++) {
     67       if (reachableMap[y][x]) row[x] = false;
     68     }
     69   }
     70 };
     71 
     72 // Debug display origin grid
     73 const displayGrid = grid => {
     74   process.stdout.write(
     75     grid.map(row => row.map(c => c ? '@' : '.').join('')).join('\n') + '\n\n'
     76   );
     77 };
     78 
     79 // Debug display
     80 const displayReachable = (grid, reachableMap) => {
     81   process.stdout.write(
     82     grid.map(
     83       (row,y) => row.map(
     84         (roll,x) => reachableMap[y][x] ? 'x' : roll ? '@' : '.'
     85       ).join('')
     86     ).join('\n') + '\n\n'
     87   );
     88 }
     89 
     90 let neighbours = buildNeighbours(grid);
     91 let reachable = buildReachable(grid, neighbours);
     92 const part1 = reachable.count;
     93 
     94 let totalRemoved = 0;
     95 
     96 console.log(`Initial state:`);
     97 displayGrid(grid);
     98 
     99 while(reachable.count) {
    100   console.log(`Remove ${reachable.count} rolls of paper:`);
    101   totalRemoved += reachable.count;
    102   displayReachable(grid, reachable._map);
    103 
    104   removeReachable(grid, reachable._map);
    105   neighbours = buildNeighbours(grid);
    106   reachable = buildReachable(grid, neighbours);
    107 }
    108 
    109 process.stdout.write('\n');
    110 process.stdout.write(`------[ Part 1: ${part1} ]------\n`);
    111 process.stdout.write(`------[ Part 2: ${totalRemoved} ]------\n`);