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


      1 const fs            = require('fs');
      2 const through       = require('through2');
      3 const char_for_char = require('../common/char-for-char.js');
      4 
      5 let   row  = [];
      6 const grid = [row];
      7 
      8 const rotate = arr => {
      9   const out = [];
     10   const row = [];
     11   for(let x=0; x<arr[0].length; x++) {
     12     out[x] = [];
     13     for(let y=0; y<arr.length; y++) {
     14       out[x][arr[0].length - 1 - y] = arr[y][x];
     15     }
     16   }
     17   return out;
     18 };
     19 
     20 fs.createReadStream('input')
     21 // fs.createReadStream('input')
     22   .pipe(char_for_char())
     23 
     24   // Load grid
     25   .pipe(through(function(char, enc, cb) {
     26     char = char.toString();
     27 
     28     // Newline = row separator
     29     if (char == '\n') {
     30       grid.push(row = []);
     31       return cb();
     32     }
     33 
     34     row.push(parseInt(char));
     35     cb();
     36   }))
     37 
     38   .on('finish', () => {
     39     // done
     40 
     41     // Remove last row if it's empty
     42     // Row is still a reference to it
     43     if (row.length == 0) {
     44       grid.pop();
     45     }
     46 
     47     // START PART 1
     48 
     49     // Make perspectives of the grid
     50     // const grids = [[[0,1],[2,3]]]; // Test rotation
     51     const grids = [rotate(grid)];
     52     grids.push(rotate(grids[grids.length-1]));
     53     grids.push(rotate(grids[grids.length-1]));
     54     grids.push(rotate(grids[grids.length-1]));
     55 
     56     // Check every perspective from left to right
     57     for(const perspective of grids) {
     58       for(let y=0; y<perspective.length; y++) {
     59         let colH = -1;
     60         for(let x=0; x<perspective.length; x++) {
     61           if (perspective[y][x] > colH) {
     62             colH = perspective[y][x];
     63             perspective[y][x] = 1;
     64           } else {
     65             perspective[y][x] = 0;
     66           }
     67         }
     68       }
     69     }
     70 
     71     // Turn perspectives upright again
     72     for(let x=0; x<1; x++) grids[2] = rotate(grids[2]);
     73     for(let x=0; x<2; x++) grids[1] = rotate(grids[1]);
     74     for(let x=0; x<3; x++) grids[0] = rotate(grids[0]);
     75 
     76     // Merge perspectives
     77     // No need to rotate, just using it as initializer
     78     let merged = rotate(grid);
     79     for(const row of merged) {
     80       for(let x=0; x<row.length; x++) row[x] = 0;
     81     }
     82     for(const perspective of grids) {
     83       for(let y=0; y<perspective.length; y++) {
     84         for(let x=0; x<perspective.length; x++) {
     85           merged[y][x] = merged[y][x] || perspective[y][x];
     86         }
     87       }
     88     }
     89 
     90     // Count the visible trees
     91     const visible = merged.reduce((r,a) => r + a.reduce((r, a) => r+a, 0), 0);
     92     console.log({ visible });
     93 
     94 
     95     // START PART 2
     96 
     97     const views = [];
     98 
     99     // Calculate scenic score for each position
    100     for(let y=0; y<grid.length; y++) {
    101       views[y] = [];
    102       for(let x=0; x<grid.length; x++) {
    103         views[y][x] = [];
    104         let v=0;
    105 
    106         // Direction: up, left, down, right
    107         v=0; for(let i=y-1; i>=0; i--) { v++; if (grid[i][x] >= grid[y][x]) { break; } } views[y][x].push(v);
    108         v=0; for(let i=x-1; i>=0; i--) { v++; if (grid[y][i] >= grid[y][x]) { break; } } views[y][x].push(v);
    109         v=0; for(let i=y+1; i<grid.length; i++) { v++; if (grid[i][x] >= grid[y][x]) { break; } } views[y][x].push(v);
    110         v=0; for(let i=x+1; i<grid.length; i++) { v++; if (grid[y][i] >= grid[y][x]) { break; } } views[y][x].push(v);
    111 
    112         // "Scenic score" = multiply house's views together
    113         views[y][x] = views[y][x].reduce((r, a) => r*a, 1);
    114       }
    115     }
    116 
    117     // Find the highest score
    118     let highscore = 0;
    119     for(let y=0; y<grid.length; y++) {
    120       for(let x=0; x<grid.length; x++) {
    121         if (views[y][x] >= highscore) highscore = views[y][x];
    122       }
    123     }
    124 
    125     console.log({ highscore });
    126   });