Published
Edited
Nov 13, 2019
1 fork
2 stars
Insert cell
Insert cell
Insert cell
Insert cell
part1 = Object.entries(groundWithWater).filter(([p, n]) => {
return (n === '|' || n === '~') && +p.split(',')[1] >= extent[0]
}).length
Insert cell
groundWithWater = {
let state = {...ground}
const spring = [500, 0]
for (let n = 0; n < 30; n++) // make up for the left/right randomness
state = drip(state, spring)
state = settle(state)
return state
}
Insert cell
function settle(ground) {
// bounded on the left and right by a '#'
const canSettle = ([x, y]) => {
let px = x
while (true) {
px -= 1
const p = [px, y]
if (!(p in ground))
return false
if (ground[p] === '#')
break
}
px = x
while (true) {
px += 1
const p = [px, y]
if (!(p in ground))
return false
if (ground[p] === '#')
break
}
return true
}

// for any '|', check if it's really a '~'
for (const [p, type] of Object.entries(ground)) {
if (type === '|' && canSettle(p.split(',').map(Number)))
ground[p] = '~'
}
return ground
}
Insert cell
function drip(ground, source) {
const queue = [ source ]
const seen = {}
let n = 0
while (queue.length) {
const p = queue.shift(),
[x, y] = p
if (y > extent[1])
break
if (p in seen)
continue

seen[p] = true
if (!(p in ground) || ground[p] === '|') {
let dx = Math.sign(Math.random() - 0.5) // try left and right, randomly
ground[p] = '|'
queue.unshift([x, y+1], [x+dx, y], [x-dx, y])
}
}
return ground
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more