class Grid {
constructor(n, m, startIndex, endIndex, values) {
this.n = n;
this.m = m;
this.startIndex = startIndex;
this.endIndex = endIndex;
this.values = values;
}
*[Symbol.iterator]() {
for (let y = 0, i = 0; y < this.n; ++y) {
for (let x = 0; x < this.m; ++x, ++i) {
yield [x, y, this.values[i]];
}
}
}
*range() {
for (let i = 0, n = this.n * this.m; i < n; ++i) {
yield i;
}
}
heightAt(i) {
return this.values[i];
}
*outgoingEdgesAt(i) {
const h = this.heightAt(i) + 1;
const [x, y] = this.position(i);
if (0 < y && this.heightAt(i - this.m) <= h) yield i - this.m;
if (y < this.n - 1 && this.heightAt(i + this.m) <= h) yield i + this.m;
if (0 < x && this.heightAt(i - 1) <= h) yield i - 1;
if (x < this.m - 1 && this.heightAt(i + 1) <= h) yield i + 1;
}
*incomingEdgesAt(i) {
const h = this.heightAt(i) - 1;
const [x, y] = this.position(i);
if (0 < y && this.heightAt(i - this.m) >= h) yield i - this.m;
if (y < this.n - 1 && this.heightAt(i + this.m) >= h) yield i + this.m;
if (0 < x && this.heightAt(i - 1) >= h) yield i - 1;
if (x < this.m - 1 && this.heightAt(i + 1) >= h) yield i + 1;
}
index(x, y) {
return this.m * y + x;
}
x(i) {
return i % this.m;
}
y(i) {
return Math.floor(i / this.m);
}
position(i) {
return [this.x(i), this.y(i)];
}
}