Public
Edited
Dec 11, 2022
Insert cell
Insert cell
Insert cell
Insert cell
function simulate(moves, knotsNb = 2) {
let knots = new Array();
for (let k = 0; k < knotsNb; k++) knots.push(new Knot(k));

let positions = [[knots.map((k) => k.dump())]];

for (let move of moves) {
let steps = [];
let remainingDist = move.distance;
while (remainingDist > 0) {
knots[0].move(move.direction);
for (let k = 1; k < knotsNb; k++) {
knots[k].followKnot(knots[k - 1]);
}
let tail = knots[knotsNb - 1];
// visitedByTail.push([tail.x, tail.y]);
steps.push(knots.map((k) => k.dump()));
remainingDist--;
}
positions.push(steps);
// return visitedByTail;
}
return positions;
}
Insert cell
Insert cell
Insert cell
Insert cell
viewof step = Inputs.range([0, positions[visiblePositions].length - 1], {
label: "Visible step",
step: 1,
value: 0
})
Insert cell
Insert cell
Insert cell
class Knot {
constructor(idx) {
this.idx = idx;
this.x = 0;
this.y = 0;
}
followKnot(knot) {
if (this.idx === 0) return;
let distX = knot.x - this.x;
let distY = knot.y - this.y;
if (Math.abs(distX) === 2) {
if (this.x < knot.x) this.x++;
else this.x--;
if (this.y < knot.y) this.y++;
else if (this.y > knot.y) this.y--;
} else if (Math.abs(distY) === 2) {
if (this.y < knot.y) this.y++;
else this.y--;
if (this.x < knot.x) this.x++;
else if (this.x > knot.x) this.x--;
}
}
move(direction) {
switch (direction) {
case "R":
this.x++;
break;
case "L":
this.x--;
break;
case "U":
this.y++;
break;
case "D":
this.y--;
break;
}
}
dump() {
return { x: this.x, y: this.y, idx: this.idx };
}
}
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