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 });