const fs = require("fs") const input = fs.readFileSync("input.txt", "utf-8", err => { err && console.error(err) }).split("\n").filter(str => str.length).map(str => str.split("").map(num => parseInt(num))) const getNeighbours = (rowNum, colNum) => { return [ input[rowNum][colNum - 1] < 9 && [rowNum, colNum - 1], input[rowNum][colNum + 1] < 9 && [rowNum, colNum + 1], input[rowNum - 1] && input[rowNum - 1][colNum] < 9 && [rowNum - 1, colNum], input[rowNum + 1] && input[rowNum + 1][colNum] < 9 && [rowNum + 1, colNum], ].filter(point => point) } const equalArr = (a, b) => a.length === b.length && a.every((v, i) => v === b[i]) const basins = [] let sum = 0 for (const [rowNum, row] of input.entries()){ for (const [colNum, height] of row.entries()){ let previousColHeight = row[colNum-1] if (typeof(previousColHeight) === "undefined") { previousColHeight = 9 } if (height < previousColHeight){ const nextColHeight = row[colNum+1] const previousRowHeight = input[rowNum - 1] && input[rowNum - 1][colNum] const nextRowHeight = input[rowNum + 1] && input[rowNum + 1][colNum] if ( (typeof(nextColHeight) != "undefined" && nextColHeight < height) || (typeof(previousRowHeight) != "undefined" && previousRowHeight < height) || (typeof(nextRowHeight) != "undefined" && nextRowHeight < height)) continue basins.push([rowNum, colNum]) sum += height } } } const basinSizes = [] for (const basin of basins) { let neighbours = [basin] for (const neighbour of neighbours){ const next = getNeighbours(neighbour[0], neighbour[1]) const nonDupes = next.filter(n => { for (let d of neighbours){ if (equalArr(d, n)) return false } return true }) neighbours.push(...nonDupes); } basinSizes.push(neighbours.length) } basinSizes.sort((a, b) => b - a) console.log(sum + basins.length) console.log(basinSizes[0] * basinSizes[1] * basinSizes[2])