Random Walks
statistics
math
Published
January 17, 2026
Code
Code
Code
particle1DVis = {
const width = 500;
const height = 60;
const maxDisplay = 100;
const displayPos = Math.max(-maxDisplay, Math.min(maxDisplay, particle1DPos));
const xScale = (width - 40) / (2 * maxDisplay);
const centerX = width / 2;
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])
.style("width", "100%")
.style("max-width", width + "px")
.style("background", "#fafafa")
.style("border", "1px solid #333");
// Number line
svg.append("line")
.attr("x1", 20)
.attr("y1", 30)
.attr("x2", width - 20)
.attr("y2", 30)
.attr("stroke", "#333")
.attr("stroke-width", 1);
// Origin tick
svg.append("line")
.attr("x1", centerX)
.attr("y1", 25)
.attr("x2", centerX)
.attr("y2", 35)
.attr("stroke", "#333")
.attr("stroke-width", 1);
svg.append("text")
.attr("x", centerX)
.attr("y", 48)
.attr("text-anchor", "middle")
.attr("font-size", 10)
.text("0");
// Left bound tick
svg.append("text")
.attr("x", 20)
.attr("y", 48)
.attr("text-anchor", "middle")
.attr("font-size", 10)
.text(-maxDisplay);
// Right bound tick
svg.append("text")
.attr("x", width - 20)
.attr("y", 48)
.attr("text-anchor", "middle")
.attr("font-size", 10)
.text(maxDisplay);
// Particle
const particleX = centerX + displayPos * xScale;
svg.append("circle")
.attr("cx", particleX)
.attr("cy", 30)
.attr("r", 6)
.attr("fill", "#4a90d9");
return svg.node();
}Code
html`<div style="display: flex; gap: 20px; align-items: flex-start;">
<div style="flex: 2;">
${particle1DVis}
<div style="text-align: center; margin-top: 5px; font-size: 14px;">
Position: <strong>${particle1DPos}</strong>
</div>
</div>
<div style="flex: 1;">
<div style="margin-bottom: 10px;"><strong>Direction Weights</strong></div>
${viewof weight1DLeft} <span style="font-size: 12px; color: #666;">(${(normalized1DProbs.left * 100).toFixed(0)}%)</span>
${viewof weight1DRight} <span style="font-size: 12px; color: #666;">(${(normalized1DProbs.right * 100).toFixed(0)}%)</span>
<div style="margin-top: 15px;">
${viewof particle1DSpeed}
</div>
</div>
</div>`Code
Code
{
const interval = setInterval(() => {
const step = 1;
const r = Math.random();
let dx = 0, dy = 0;
const p = normalizedProbs;
if (r < p.left) {
dx = -step;
} else if (r < p.left + p.right) {
dx = step;
} else if (r < p.left + p.right + p.up) {
dy = -step;
} else {
dy = step;
}
const newX = mutable particlePos.x + dx;
const newY = mutable particlePos.y + dy;
mutable particlePos = ({x: newX, y: newY});
mutable particlePath = [...mutable particlePath, ({x: newX, y: newY})];
}, 100 / particleSpeed);
invalidation.then(() => clearInterval(interval));
}Code
particleVis = {
const size = 200;
const scale = 2;
const svg = d3.create("svg")
.attr("viewBox", [-size/2, -size/2, size, size])
.style("width", "100%")
.style("aspect-ratio", "1")
.style("border", "1px solid #333")
.style("background", "#fafafa");
// Origin crosshair
svg.append("line")
.attr("x1", -5).attr("y1", 0)
.attr("x2", 5).attr("y2", 0)
.attr("stroke", "#ccc")
.attr("stroke-width", 0.5);
svg.append("line")
.attr("x1", 0).attr("y1", -5)
.attr("x2", 0).attr("y2", 5)
.attr("stroke", "#ccc")
.attr("stroke-width", 0.5);
// Path trace
const line = d3.line()
.x(d => d.x * scale)
.y(d => d.y * scale);
svg.append("path")
.attr("d", line(particlePath))
.attr("fill", "none")
.attr("stroke", "lightblue")
.attr("stroke-width", 0.5);
// Particle
svg.append("circle")
.attr("cx", particlePos.x * scale)
.attr("cy", particlePos.y * scale)
.attr("r", 3)
.attr("fill", "#4a90d9");
return svg.node();
}Code
html`<div style="display: flex; gap: 20px; align-items: flex-start;">
<div style="flex: 1;">
${particleVis}
<div style="text-align: center; margin-top: 5px; font-size: 14px;">
Position: <strong>(${particlePos.x.toFixed(1)}, ${particlePos.y.toFixed(1)})</strong>
</div>
</div>
<div style="flex: 1;">
<div style="margin-bottom: 10px;"><strong>Direction Weights</strong></div>
${viewof weightLeft} <span style="font-size: 12px; color: #666;">(${(normalizedProbs.left * 100).toFixed(0)}%)</span>
${viewof weightRight} <span style="font-size: 12px; color: #666;">(${(normalizedProbs.right * 100).toFixed(0)}%)</span>
${viewof weightUp} <span style="font-size: 12px; color: #666;">(${(normalizedProbs.up * 100).toFixed(0)}%)</span>
${viewof weightDown} <span style="font-size: 12px; color: #666;">(${(normalizedProbs.down * 100).toFixed(0)}%)</span>
<div style="margin-top: 15px;">
${viewof particleSpeed}
</div>
</div>
</div>`