Public
Edited
Dec 9, 2022
1 fork
2 stars
Insert cell
Insert cell
test = `30373
25512
65332
33549
35390
`
Insert cell
testGrid = parseGrid(test)
Insert cell
function parseGrid(input) {
const lines = input.trim().split("\n");
const n = lines.length;
const m = lines[0].length;
return new Grid(n, m, lines.flatMap((line) => line.split("").map(Number)));
}
Insert cell
class Grid {
constructor(n, m, grid) {
this.n = n; // number of columns
this.m = m; // number of rows
this.grid = grid;
}
*positions() {
for (let y = 0; y < this.m; ++y) {
for (let x = 0; x < this.n; ++x) {
yield [x, y];
}
}
}
*positionsLeft(x, y) {
for (let i = x - 1; i >= 0; --i) {
yield [i, y];
}
}
*positionsRight(x, y) {
for (let i = x + 1; i < this.n; ++i) {
yield [i, y];
}
}
*positionsTop(x, y) {
for (let i = y - 1; i >= 0; --i) {
yield [x, i];
}
}
*positionsBottom(x, y) {
for (let i = y + 1; i < this.m; ++i) {
yield [x, i];
}
}
heightAt(x, y) {
x = Math.floor(x);
y = Math.floor(y);
if (x >= 0 && x < this.n && y >= 0 && y < this.m) {
return this.grid[y * this.n + x];
}
}
everyShorter(positions, h) {
for (const [x, y] of positions) {
if (this.heightAt(x, y) >= h) {
return false;
}
}
return true;
}
countShorter(positions, h) {
let n = 0;
for (const [x, y] of positions) {
++n;
if (this.heightAt(x, y) >= h) {
break;
}
}
return n;
}
visibleAt(x, y) {
const h = this.heightAt(x, y);
return (
(this.everyShorter(this.positionsLeft(x, y), h) && 1) |
(this.everyShorter(this.positionsRight(x, y), h) && 2) |
(this.everyShorter(this.positionsTop(x, y), h) && 4) |
(this.everyShorter(this.positionsBottom(x, y), h) && 8)
);
}
scenicScoreAt(x, y) {
const h = this.heightAt(x, y);
return (
this.countShorter(this.positionsLeft(x, y), h) *
this.countShorter(this.positionsRight(x, y), h) *
this.countShorter(this.positionsTop(x, y), h) *
this.countShorter(this.positionsBottom(x, y), h)
);
}
}
Insert cell
visualizeGrid(testGrid)
Insert cell
function visualizeGrid(grid) {
return Plot.plot({
width: grid.m * 14,
height: grid.n * 14,
padding: 0,
axis: null,
x: { type: "band" },
y: { type: "band" },
marks: [
Plot.cell(grid.positions(), {fill: ([x, y]) => grid.visibleAt(x, y) !== 0, inset: 0.5}),
Plot.text(grid.positions(), {text: ([x, y]) => grid.heightAt(x, y)}),
]
});
}
Insert cell
countVisible(testGrid)
Insert cell
function countVisible(grid) {
return d3.sum(grid.positions(), ([x, y]) => grid.visibleAt(x, y) !== 0);
}
Insert cell
input = FileAttachment("input.txt").text()
Insert cell
grid = parseGrid(input)
Insert cell
visualizeGrid(grid)
Insert cell
countVisible(grid)
Insert cell
grid.n * grid.m
Insert cell
visualizeGrid2(testGrid)
Insert cell
function visualizeGrid2(grid) {
return Plot.plot({
width: grid.m * 20,
height: grid.n * 20,
axis: null,
x: { type: "band" },
y: { type: "band" },
color: { scheme: "blues" },
marks: [
Plot.cell(grid.positions(), {fill: ([x, y]) => grid.scenicScoreAt(x, y)}),
Plot.text(grid.positions(), {text: ([x, y]) => grid.scenicScoreAt(x, y)})
]
});
}
Insert cell
visualizeGrid2(grid)
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