aoc-2021/09_day/code.js

115 lines
No EOL
2.6 KiB
JavaScript

const readline = require('readline')
const rl = readline.createInterface({
input: process.stdin,
terminal: false
})
lines = []
rl.on('line', (line) => {
let raw = line.replace('\n', '').replace(' ', '')
if (raw.length > 0) {
lines.push(raw)
}
})
rl.on('close', () => {
const db = false
let rows = lines.map(l => l.split('').map(nb => parseInt(nb)))
//console.log(rows)
// first part: find low points
let lowPoints = []
let lowPointsCoord = []
for (let i = 0; i < rows.length; i++) {
for (let j = 0; j < rows[i].length; j++) {
let val = rows[i][j]
let toCmpWith = [[i-1, j], [i, j+1], [i+1, j], [i, j-1]]
let success = true
for (var k = 0; k < toCmpWith.length; k++) {
let [ y,x ] = toCmpWith[k]
if (
y < 0 ||
y >= rows.length ||
x < 0 ||
x >= rows[i].length
) {
// ignore, because these point don't exists
continue
}
// important: you have to use less or equal HERE!
if (rows[y][x] <= val) {
success = false
break
}
}
if (success) {
lowPoints.push(val)
lowPointsCoord.push([i, j])
}
}
}
// second part: find bassins
let findBassin = (alreadySeen, toSee) => {
if (toSee.length == 0) {
return []
}
const e = toSee[0]
const [y,x] = e
// check if the point exists
if (
y < 0 ||
y >= rows.length ||
x < 0 ||
x >= rows[y].length
) {
return findBassin(alreadySeen, toSee.slice(1))
}
// check if it's 9
if (rows[y][x] == 9) {
return findBassin(alreadySeen, toSee.slice(1))
}
// check if it's already seen
if (alreadySeen.filter(([_y, _x]) => _y == y && _x == x).length > 0) {
return findBassin(alreadySeen, toSee.slice(1))
}
neighbours = [[y-1, x], [y, x+1], [y+1, x], [y, x-1]]
res = findBassin([e, ...alreadySeen], [...neighbours, ...(toSee.slice(1))])
return [e, ...res]
}
let bassins = lowPointsCoord.map(c => findBassin([], [c]))
let bassinsSizes = bassins
.map(b => parseInt(b.length))
.sort((a, b) => a - b)
.slice(-3)
bassinsSizesProduct = bassinsSizes.reduce((a, p) => a*p)
let bassinsCoords = bassins.flat()
// output mini map of bassins
if (db) {
for (var i = 0; i < rows.length; i++) {
rowOutput = ''
for (var j = 0; j < rows[i].length; j++) {
if (bassinsCoords.filter(([y, x]) => y == i && x == j).length > 0) {
rowOutput += '\033[1m' + rows[i][j] + '\033[0m'
} else {
rowOutput += rows[i][j]
}
}
console.log(rowOutput)
}
}
let risks = lowPoints.map(height => 1+height)
let sum = risks.reduce((e, s) => e+s)
console.log(`Sum of the risk level of low points: ${sum}`)
console.log(`Product of 3 largest bassins size: ${bassinsSizesProduct}`)
})