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 (3760B)


      1 const fs = require('fs');
      2 
      3 const lines = fs.readFileSync('input', 'utf-8')
      4 // const lines = fs.readFileSync('sample', 'utf-8')
      5   .split('\n')
      6 
      7 const elves = [];
      8 for(let y=0; y<lines.length; y++) {
      9   const line = lines[y];
     10   for(let x=0; x<line.length; x++) {
     11     if (line.charAt(x) == '#') {
     12       elves.push({
     13         x,
     14         y,
     15       });
     16     }
     17   }
     18 }
     19 
     20 function adjacent(grid, origin) {
     21   const neighbours = [];
     22   for(let y=origin.y-1; y<=origin.y+1; y++) {
     23     if (!grid[y]) continue;
     24     for(let x=origin.x-1; x<=origin.x+1; x++) {
     25       if (y == origin.y && x == origin.x) continue;
     26       if (grid[y][x]) neighbours.push(grid[y][x]);
     27     }
     28   }
     29   return neighbours;
     30 }
     31 
     32 let step1 = 0;
     33 const moves = ['N','S','W','E'];
     34 
     35 const test = {
     36   N: origin => subject => subject.y < origin.y,
     37   S: origin => subject => subject.y > origin.y,
     38   W: origin => subject => subject.x < origin.x,
     39   E: origin => subject => subject.x > origin.x,
     40 };
     41 
     42 function drawmap(elves) {
     43   let output = '\n';
     44   let minx =  Infinity;
     45   let miny =  Infinity;
     46   let maxx = -Infinity;
     47   let maxy = -Infinity;
     48   for(const elf of elves) {
     49     if (elf.x < minx) minx = elf.x;
     50     if (elf.y < miny) miny = elf.y;
     51     if (elf.x > maxx) maxx = elf.x;
     52     if (elf.y > maxy) maxy = elf.y;
     53   }
     54   for(let y=miny; y<=maxy; y++) {
     55     for(let x=minx; x<=maxx; x++) {
     56       if (elves.find(elf => elf.x == x && elf.y == y)) {
     57         output += '#';
     58       } else {
     59         output += ' ';
     60       }
     61     }
     62     output += '\n';
     63   }
     64   process.stdout.write(output);
     65 }
     66 
     67 const dirdiff = {
     68   N: [ 0, -1],
     69   S: [ 0,  1],
     70   W: [-1,  0],
     71   E: [ 1,  0],
     72 };
     73 
     74 // drawmap(elves);
     75 
     76 const grid = [];
     77 for(const elf of elves) {
     78   grid[elf.y] = grid[elf.y] || [];
     79   grid[elf.y][elf.x] = elf;
     80 }
     81 
     82 (async () => {
     83   let proposals = [];
     84   let rounds = 0;
     85   do {
     86     proposals = [];
     87 
     88     // stage 1, make proposals
     89     for(const elf of elves) {
     90       // Only make a proposal if neighbours are found
     91       const neighbours = adjacent(grid, elf);
     92       if (!neighbours.length) continue;
     93       for(const direction of moves) {
     94         if (neighbours.find(test[direction](elf))) continue;
     95         proposals.push({
     96           elf,
     97           direction,
     98           x: elf.x + dirdiff[direction][0],
     99           y: elf.y + dirdiff[direction][1],
    100         });
    101         break;
    102       }
    103     }
    104 
    105     // stage 2, count proposals per location
    106     let positions = [];
    107     for(const proposal of proposals) {
    108       if (!positions[proposal.y]) positions[proposal.y] = [];
    109       positions[proposal.y][proposal.x] = (positions[proposal.y][proposal.x]||0) + 1;
    110     }
    111 
    112     // stage 3, move the elves
    113     for(const proposal of proposals) {
    114       if (positions[proposal.y][proposal.x] > 1) continue;
    115       grid[proposal.elf.y][proposal.elf.x] = false;
    116       grid[proposal.y] = grid[proposal.y] || [];
    117       grid[proposal.y][proposal.x] = proposal.elf;
    118       proposal.elf.x = proposal.x;
    119       proposal.elf.y = proposal.y;
    120     }
    121 
    122     // stage 4, moves
    123     moves.push(moves.shift());
    124 
    125     // Round counter
    126     rounds++;
    127 
    128     // if (rounds % 1e1 == 0) {
    129     // drawmap(elves);
    130     // console.log(proposals.length);
    131     // }
    132 
    133     if (rounds == 10) {
    134       // Find area to check
    135       let minx =  Infinity;
    136       let miny =  Infinity;
    137       let maxx = -Infinity;
    138       let maxy = -Infinity;
    139       for(const elf of elves) {
    140         if (elf.x < minx) minx = elf.x;
    141         if (elf.y < miny) miny = elf.y;
    142         if (elf.x > maxx) maxx = elf.x;
    143         if (elf.y > maxy) maxy = elf.y;
    144       }
    145 
    146       // Calculate empty area
    147       const width  = maxx - minx + 1;
    148       const height = maxy - miny + 1;
    149       const area   = (width * height) - elves.length;
    150       console.log({ area });
    151     }
    152 
    153   } while(proposals.length);
    154 
    155 
    156   console.log({ elves: elves.length, rounds });
    157 
    158 })();