const fs = require('fs/promises'); const sum = (arr) => arr.reduce((total, num) => total+num, 0); const arrayOfLength = n => Array.from(Array(n).keys()).map(() => {}); const main = async () => { const input = (await fs.readFile("./input.txt", 'utf8')).split("\n"); const coord = ([x, y]) => { if(isNaN(x) || typeof y === "undefined") { throw new Error(""); } return `${x}-${y}`; }; let sandUnitCount = 0; const fillPath = ([x1, y1], [x2, y2]) => { const fillIns = []; if(x1 === x2) { const yDiff = y2 - y1; for(let y = y1; y !== y2; y = y + (Math.abs(yDiff)/yDiff)) { fillIns.push(coord([x1, y])); } } else { const xDiff = x2 - x1; for(let x = x1; x !== x2; x = x + (xDiff/Math.abs(xDiff))) { fillIns.push(coord([x, y1])); } } return fillIns; }; const grid = input.reduce((obj, row, i) => { if(row === "" ) { return obj; } const path = row.split(" -> "); for(let i = 0; i < path.length - 1; i++) { const start = path[i].split(",").map(x => parseInt(x)); const end = path[i + 1].split(",").map(x => parseInt(x)); const filledIn = fillPath(start, end); filledIn.forEach(x => obj[x] = "#") } const lastRock = path[path.length - 1].split(",").map(x => parseInt(x)) obj[coord(lastRock)] = "#"; return obj; }, {}) const sandFall = (x, y) => { if(y === 174) { return [x, y]; } if(!grid[coord([x, y + 1])]) { return sandFall(x, y + 1); } if(!grid[coord([x - 1, y + 1])]) { return sandFall(x - 1, y + 1); } if(!grid[coord([x + 1, y + 1])]) { return sandFall(x + 1, y + 1); } return [x, y]; }; const print = () => { for(let y = 0; y < 175; ++y) { console.log(arrayOfLength(100).map((_, i) => grid[coord([i + 450, y])] || ".").join("")); } console.log("\n\n\n") console.log("Sand count: ", sandUnitCount); }; while(true) { const loc = sandFall(500, 0); sandUnitCount++; grid[coord(loc)] = "o"; console.log("Location of sand: ", loc); if(loc[0] === 500 && loc[1] === 0) { break; } } console.log("Answer: ", sandUnitCount); print(); } main();