115 lines
2.6 KiB
JavaScript
115 lines
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}`)
|
||
|
})
|