R56 · Double-slit interference, particle by particle
Every answer below carries the name of the model that wrote it. Blind refers to the scoring: the review was done without knowing which model produced which answer — the published result names them.
2 of the 11 local models delivered nothing through our test harness in this round — for reasons that lie with our setup, not with the models. Those cards are marked DNF like any other, but they are not evidence about those models — the reason is noted on the card itself.
A frontier reference answered the same task (Claude Opus 5) — outside the field and deliberately unscored, further down the page.
Show task
Create ONE self-contained HTML file (STRICT LIMIT: max 120 lines total) that shows the double-slit experiment building up an interference pattern particle by particle on a <canvas>. Fire one particle at a time from a source on the left through a barrier with exactly two slits; each particle lands as a single dot on a detector screen on the right, with the landing position drawn from the two-slit interference distribution. Dots accumulate and must visibly form the alternating bright and dark fringes over time. Show a running count of detected particles. Smooth requestAnimationFrame animation, NO user input, starts immediately and keeps running. No external libraries, no comments needed. Output ONLY the HTML file content, nothing else.
The answers
Show code
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Double-Slit Experiment</title>
<style>
body { margin: 0; display: flex; justify-content: center; align-items: center; height: 100vh; background-color: #000; color: #fff; }
canvas { border: 1px solid #fff; }
#count { position: absolute; top: 20px; left: 50%; transform: translateX(-50%); font-size: 24px; }
</style>
</head>
<body>
<canvas id="canvas" width="800" height="600"></canvas>
<div id="count">Particles Detected: 0</div>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const countDisplay = document.getElementById('count');
let particlesDetected = 0;
const slitWidth = 50;
const slits = [300, 450];
const screenStartX = 600;
function drawParticle() {
const particleX = Math.random() * canvas.width;
const particleY = Math.random() * canvas.height / 2 + canvas.height / 4;
ctx.fillStyle = 'white';
ctx.beginPath();
ctx.arc(particleX, particleY, 1, 0, Math.PI * 2);
ctx.fill();
++particlesDetected;
countDisplay.textContent = `Particles Detected: ${particlesDetected}`;
}
function animate() {
if (Math.random() < 0.01) drawParticle();
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
</script>
</body>
</html>
```Show code
```html
<!DOCTYPE html>
<html>
<head>
<title>Double Slit Interference</title>
<style>
body { background: #111; color: #eee; font-family: monospace; display: flex; justify-content: center; margin-top: 20px; }
canvas { border: 1px solid #333; background: #050505; }
#info { margin-left: 20px; font-size: 1.2em; line-height: 1.4; }
</style>
</head>
<body>
<canvas id="slitCanvas" width="900" height="300"></canvas>
<div id="info"></div>
<script>
const canvas = document.getElementById('slitCanvas');
const ctx = canvas.getContext('2d');
const infoDiv = document.getElementById('info');
let particlesDrawn = 0;
let runningParticles = [];
const MAX_PARTICLES = 5000; // Limit for simulation stability/performance
// Constants (Normalized to Canvas size)
const CANVAS_W = 900;
const SCREEN_X1 = CANVAS_W * 0.6; // Start of screen
const SLEET_WIDTH = 40;
const SLIT_SEP = 20;
const NUM_SLITS = 2;
// Interference Constants (Controls the pattern visibility)
// These values simulate a specific wavelength/slit spacing ratio:
const K = Math.PI / 150; // Wave number scaling factor
const A = Math.sin(K * 1); // Amplitude scaling factor for probability calculation
function drawSetup() {
ctx.clearRect(0, 0, CANVAS_W, canvas.height);
// Draw Source/Slits (Conceptual)
ctx.fillStyle = '#444';
ctx.fillRect(20, 50, 10, 200); // Source area
ctx.strokeStyle = '#AAA';
ctx.lineWidth = 3;
// Barrier Area and Slits
ctx.beginPath();
ctx.rect(200, 0, 100, canvas.height);
ctx.fillStyle = '#222';
ctx.fill();
ctx.strokeStyle = '#AAA';
ctx.strokeRect(200, 0, 100, canvas.height);
// Draw the two slits (Slit centers at X=220 and X=280)
const slitCenter1 = 220;
const slitCenter2 = 280;
ctx.fillStyle = '#666';
ctx.fillRect(slitCenter1 - SLEET_WIDTH/2, 0, SLEET_WIDTH, canvas.height);
ctx.fillRect(slitCenter2 - SLEET_WIDTH/2, 0, SLEET_WIDTH, canvas.height);
// Draw Detector Screen Grid (Conceptual)
ctx.strokeStyle = '#333';
for (let i = 0; i < 10; i++) {
ctx.beginPath();
ctx.moveTo(SCREEN_X1 + i * 25, 0);
ctx.lineTo(SCREEN_X1 + i * 25, canvas.height);
ctx.stroke();
}
}
// Probability Density Function (PDF) for the interference pattern
function getProbability(y) {
const x = y; // Use vertical position as proxy for angular dependence
// Interference term: cos^2(k*x) * cos^2(k*x) -> simplified to sin^2/cos^2 product
let intensity1 = Math.pow(Math.cos((K + 0.5) * x), 2);
let intensity2 = Math.pow(Math.cos((K - 0.5) * x), 2);
// Total probability (weighted sum of two slits' contributions)
let P_total = (intensity1 + intensity2) / 2;
return Math.max(0, P_total); // Ensure non-negative
}
function fireParticle() {
if (particlesDrawn >= MAX_PARTICLES) return null;
// 1. Determine landing position Y based on probability distribution
let y = 0;
let attempts = 0;
const maxAttempts = 50;
let P = 0;
// Iteratively find a weighted random point
while (attempts < maxAttempts) {
y = Math.random() * canvas.height;
P = getProbability(y);
if (Math.random() < P / 2) { // Scale down the probability check for density
break;
}
attempts++;
}
// 2. Simulate particle landing at (X, Y) on the screen
const x = SCREEN_X1 + Math.random() * (CANVAS_W - SCREEN_X1); // Random X along the screen width
return { x: x, y: y };
}
function animate(time) {
if (particlesDrawn >= MAX_PARTICLES) {
infoDiv.innerHTML = `Simulation complete. Total particles detected: ${MAX_PARTICLES}.`;
return;
}
drawSetup(); // Redraw the background/slits setup
// Draw all accumulated dots
ctx.fillStyle = 'rgba(100, 255, 100, 0.8)';
runningParticles.forEach(dot => {
ctx.fillRect(dot.x, dot.y, 1.5, 1.5);
});
// Fire a new particle
const newDot = fireParticle();
if (newDot) {
runningParticles.push(newDot);
particlesDrawn++;
// Update info panel
infoDiv.innerHTML = `Detected Particles: ${particlesDrawn} / ${MAX_PARTICLES}`;
// Keep the running particles array manageable to prevent memory overflow
if (runningParticles.length > 1000) {
runningParticles.shift();
}
}
requestAnimationFrame(animate);
}
// Start the animation loop
requestAnimationFrame(animate);
</script>
</body>
</html>
```Show code
```html
<!DOCTYPE html>
<html>
<head>
<title>Double Slit Interference</title>
<style>body { background: #000; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; }</style>
</head>
<body>
<canvas id="slitCanvas" width="800" height="400" style="border: 2px solid #333;"></canvas>
<script>
const canvas = document.getElementById('slitCanvas');
const ctx = canvas.getContext('2d');
const W = canvas.width;
const H = canvas.height;
let particleCount = 0;
let animationFrameId = null;
// Simulation Parameters (Visual representation)
const SLIT_WIDTH = 15;
const SLIT_GAP = 60;
const DETECTOR_START_X = W * 0.75;
const DETECTION_RANGE = W - DETECTOR_START_X;
/**
* Calculates the probability density function for interference at a given position (x).
* Uses a simplified sinusoidal model to simulate constructive/destructive interference fringes.
*/
function intensity(x) {
// Normalize x relative to the detection area
const normX = (x - DETECTOR_START_X);
if (normX < 0 || normX > DETECTION_RANGE) return 0;
// Interference pattern simulation: I(x) ~ cos^2(k * x / L)
// k controls the fringe spacing, L is the detection length.
const k = 10; // Controls frequency of fringes
return Math.cos(normX * (Math.PI / 30)) ** 2;
}
/**
* Generates a random position x on the detector based on the probability distribution I(x).
*/
function samplePosition() {
let target = Math.random();
let current_x = DETECTOR_START_X;
let prev_intensity = 0;
let accumulated_prob = 0;
// Simple Riemann sum approximation over the detection range
const steps = 1000; // Resolution of sampling
const stepSize = DETECTION_RANGE / steps;
for (let i = 0; i < steps; i++) {
const x = DETECTOR_START_X + (i + 0.5) * stepSize;
// Calculate probability density at this point
const p_density = intensity(x);
accumulated_prob += p_density * stepSize;
if (target < accumulated_prob) {
return x;
}
}
return DETECTOR_START_X + DETECTION_RANGE / 2; // Fallback
}
function drawParticle() {
const x = samplePosition();
// Draw the particle dot
ctx.fillStyle = 'rgba(255, 255, 200, 1)';
ctx.beginPath();
ctx.arc(x, H / 2, 2, 0, Math.PI * 2);
ctx.fill();
// Draw the running count (Top left corner)
ctx.fillStyle = '#FFF';
ctx.font = '24px Arial';
ctx.fillText(`Particles Detected: ${particleCount}`, 10, 30);
particleCount++;
}
function animate() {
// Clear previous particles but keep the background accumulation effect (optional)
// We must redraw the whole canvas to accumulate dots cleanly if we don't clear.
// Since performance is key and dots are small, clearing and redrawing all accumulated dots is too slow.
// Instead, we let the dot drawing function handle the visual buildup over time.
drawParticle();
animationFrameId = requestAnimationFrame(animate);
}
animate();
</script>
</body>
</html>
```Show code
```html
<!DOCTYPE html>
<html><body style="background:#1a1a1a;margin:0;display:flex;justify-content:center;height:100vh">
<canvas id=c width=800 height=400></canvas>
<div id=count style="position:absolute;top:20px;left:50%;color:white;">0</div>
<script>
const c=document.getElementById('c'), ctx=c.getContext('2d');
const countEl=document.getElementById('count');
let particles=[],count=0;
const d=0.1,λ=0.4,l=3,w=8,h=400;
const pi=Math.PI,pii=pi*2;
function draw(){
ctx.fillStyle='#1a1a1a';ctx.fillRect(0,0,c.width,c.height);
// Source
ctx.fillStyle='white';
ctx.beginPath();
ctx.arc(w-(w/3),h/2,5,0,pii); ctx.fill();
// Slits
const slitWidth=4;
ctx.strokeStyle='white';ctx.lineWidth=2;
ctx.beginPath();
ctx.moveTo((w/2)-slitWidth/2,l*1.5); ctx.lineTo((w/2)+slitWidth/2,l*1.5);
ctx.moveTo((w/2)-slitWidth/2,l*3.5); ctx.lineTo((w/2)+slitWidth/2,l*3.5);
ctx.stroke();
// Screen
ctx.strokeStyle='white';ctx.lineWidth=1;
ctx.beginPath();
ctx.moveTo(0, h/2); ctx.lineTo(c.width, h/2);
ctx.stroke();
for(let i=particles.length-1;i>=0--;{
const x=(w*2)-Math.cos(count/particles.length*(l/(λ)))%w;
particles.push(x);
const y=h/2 + Math.sin(count/particles.length*(l/(λ))) * h/4;
ctx.fillStyle='white';ctx.fillRect(x-1,y-1,3,3);
}
count++;
countEl.textContent=count;
}
setInterval(draw,10);
</script>
</body></html>
```Show code
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Double-Slit Experiment</title>
<style>
canvas {
border: 1px solid black;
}
</style>
</head>
<body>
<canvas id="canvas" width="800" height="400"></canvas>
<script>
const ctx = document.getElementById('canvas').getContext('2d');
let particles = [];
let detectedParticles = 0;
function random(x, y) {
return Math.random() * (y - x) + x;
}
function particle() {
const x = 50;
const y1 = random(150, 300);
const y2 = random(250, 350);
particles.push({x: x, y1: y1, y2: y2});
}
function drawParticle(p) {
ctx.beginPath();
ctx.arc(p.x, p.y1, 5, 0, Math.PI * 2);
ctx.fill();
ctx.beginPath();
ctx.arc(p.x, p.y2, 3, 0, Math.PI * 2);
ctx.stroke();
}
function drawParticles() {
ctx.clearRect(0, 0, 800, 400);
particles.forEach(drawParticle);
const fringes = [];
for (let y = 200; y <= 300; y += 50) {
let intensity = 0;
let prevIntensity = 0;
for (const p of particles) {
if (p.y1 >= y - 25 && p.y1 <= y + 25) {
const delta = Math.abs(p.y2 - y);
intensity += Math.sin(delta * Math.PI / 50) / delta;
}
}
fringes.push({y: y, intensity: prevIntensity + intensity});
prevIntensity = intensity;
}
ctx.beginPath();
for (const f of fringes.slice(0, -1)) {
ctx.lineTo(f.y, f.intensity * 200);
}
ctx.stroke();
ctx.font = '24px Arial';
ctx.fillStyle = 'black';
ctx.textAlign = 'left';
ctx.textBaseline = 'top';
ctx.fillText(`Particles detected: ${particles.length}`, 20, 10);
requestAnimationFrame(drawParticles);
}
document.addEventListener('DOMContentLoaded', () => {
for (let i = 0; i < 500; i++) {
particle();
}
drawParticles();
});
</script>
</body>
</html>
```Show code
```html
<!DOCTYPE html>
<html>
<head>
<title>Double-Slit Experiment</title>
<style>body {background: #111; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0;} canvas {border: 2px solid #444; background: #0a0a15;}</style>
</head>
<body>
<canvas id="slitCanvas" width="900" height="300"></canvas>
<script>
const canvas = document.getElementById('slitCanvas');
const ctx = canvas.getContext('2d');
let particleCount = 0;
const screenWidth = canvas.width - 100;
const slitsHeight = 40;
const slitSeparation = 80;
const d = 50; // Distance between slits (effective)
const L = 700; // Screen distance
// Function to calculate the interference pattern position y, given a random angle theta.
// This simulates the distribution P(theta) ~ 1 + cos^2(d sin(theta)/λ)
function getInterferenceY() {
let r = Math.random();
let angle;
do {
angle = Math.acos(Math.random() * 2 - 1); // Random angle in [0, pi]
} while (angle < 0);
// Simplified formula for the intensity distribution based on angle/position
// sin^2(d sin(theta)/λ) -> Use a representative function of r to map density.
let y = Math.sin(Math.PI * Math.cos(r * Math.PI) / 0.4); // Pseudo-random mapping for visible fringes
return (y + 1) * 0.5 * 7; // Scale Y position to fit screen height
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// --- Static Elements ---
ctx.fillStyle = '#333';
// Source (Left)
ctx.fillRect(10, 125, 50, 5);
// Barrier/Slits (Center-Left)
ctx.fillStyle = '#888';
ctx.fillRect(200, 90, 30, 120); // Barrier block
ctx.fillStyle = '#444';
ctx.fillRect(205, 125 - slitsHeight / 2, 10, slitsHeight); // Slit 1
ctx.fillRect(205 + slitSeparation, 125 - slitsHeight / 2, 10, slitsHeight); // Slit 2
// Count Display
ctx.fillStyle = '#AAA';
ctx.font = '24px monospace';
ctx.fillText(`Particles: ${particleCount}`, 10, 30);
// --- Particle Simulation (Accumulation) ---
if (Math.random() < 0.5 || particleCount === 0) { // Trigger particle fire intermittently or at start
const yPos = getInterferenceY();
const xScreen = canvas.width - 40;
// Draw the dot
ctx.fillStyle = '#FFFFFF';
ctx.beginPath();
ctx.arc(xScreen, yPos, 1.5, 0, Math.PI * 2);
ctx.fill();
particleCount++;
}
requestAnimationFrame(draw);
}
// Start the animation loop
window.onload = draw;
</script>
</body>
</html>
```Show code
<think> Okay, I need to create an HTML file that demonstrates the double-slit experiment with particles building up an interference pattern over time. The user wants it self-contained, under 120 lines, with strict requirements. Let me start by breaking down the problem. First, the HTML structure. I'll need a canvas element and a div to show the particle count. The canvas should be positioned on the left, and the div on the right. Since it's a self-contained file, all the code must be in the HTML's script section. Next, the JavaScript part. The key is to simulate the double-slit interference pattern. Each particle's landing position must be based on the interference distribution. The double-slit formula for the intensity is I = I0 * (sin(β/2)/(β/2))² * cos²(α), where α and β are path differences depending on the slit positions and wavelength. But since we're dealing with individual particles, maybe a simpler approach using random numbers based on the probability distribution. Hmm, perhaps using a probability function that gives a higher chance near the bright fringes. The interference pattern has bright and dark fringes, so the probability density must vary accordingly. The distribution can be approximated by calculating the interference term sin^2(k*(d*sinθ)/2) and the diffraction term from each slit. But for simplicity, maybe just use a mathematical function that gives peaks at certain positions. Alternatively, generate a random y-coordinate between 0 and the canvas height, then compute the intensity at that y based on the interference pattern's equation. If the random number is below that intensity, accept the position; else, try again. Rejection sampling might be needed here. Wait, but for each particle, the position is chosen according to the probability distribution. The probability density at position y is proportional to the interference pattern's intensity at y. So, to simulate that, the probability of a particle landing at y should be proportional to the intensity at y. The interference pattern's intensity can be calculated as (sin(π * y / (λ * D / d)) / (π * y / (λ * D / d)))^2 * cos^2(π * y / (λ * d / (2 * D))) ? Not exactly sure. Maybe it's better to use a simplified version where the vertical coordinate corresponds to the path difference between the two slits. Alternatively, let's model it with a function that creates peaks separated by a certain distance. Maybe something like: intensity = (Math.cos( (2 * Math.PI * y) / (waveLength * distanceToScreen) ))^2 + ... Hmm, perhaps the standard double-slit equation. The standard formula for the interference pattern is: I(y) = I0 * (sin(π y / (λ D)) / (π y / (λ D)))^2 * cos^2(π y / (λ d)), where D is the distance between slits and screen, d is the slit separation. Wait, maybe I should parameterize it so that the peaks are spaced appropriately. Alternatively, for simplicity, let's choose parameters so that the intensity at position y is given by (sin(a * y))^2 * (cos(b * y))^2, where a and b are constants that control the spacing of the fringes. Not sure if exact, but it can create the alternating bright and dark bands needed. Alternatively, perhaps the interference term can be a cosine squared function for the two-slit interference, modulated by a sinc squared function for the single-slit diffraction. But that might complicate things. Alternatively, to keep it simple, let's model the interference as a cosine squared function. Let's assume that the vertical position y corresponds to the path difference between the two slits. So the intensity would be proportional to cos²( π * y / (λ * something) ), leading to alternating bright and dark fringes. Alternatively, since this is a simulation, maybe just use a function that creates peaks every certain number of pixels. For example, using Math.cos(y * k) squared, scaled and offset so that peaks occur at certain intervals. Alternatively, use a function that gives high probability at certain y positions. For example, if we set the probability of a particle landing at a certain y to be proportional to cos^2(y * some constant). That way, the bright fringes (where cosine squared is 1) will accumulate more dots. Alternatively, perhaps the probability distribution is such that the probability density at position y is given by (sin(π * y / w)/ (π * y / w))^2 * cos^2(π * y / (w * f)), where w is a width parameter and f controls the frequency of the fringes. But this might be overcomplicating. Alternatively, since we just need to simulate the buildup, maybe a simpler approach: for each particle, compute a random y position based on a distribution that has peaks where the bright fringes would be. For example, generate a random y between 0 and height, then compute a weight based on the interference function, and only accept it with that probability, repeating until accepted. But that might be inefficient. Alternatively, precompute a probability table for each y-coordinate, then pick a y based on that table. But in JavaScript, that might be feasible. Alternatively, perhaps use a mathematical function to determine the y for each particle. Let's think of it as follows: the interference pattern has maxima at positions y where the path difference between the two slits to that point is an integer multiple of the wavelength. The path difference is approximately (d * y) / (distance between slits and screen), where d is the slit separation, but maybe I can abstract this. Let me think in terms of the canvas. Let's say the canvas has a width, and the slit is on the left. The two slits are separated by a certain distance. Each particle goes through one of the slits (randomly?), but actually, in the real experiment, the particle goes through both slits, but here, since we are simulating particle by particle, maybe each particle chooses a slit randomly, then the direction to the detector is determined by that. Wait, but that would produce two separate distributions, not an interference pattern. So that approach is wrong. Ah right, interference requires the particle to go through both slits (in quantum terms). But classically, how is interference achieved? The wave goes through both slits and interferes. But in this particle-by-particle model, each particle must choose a path to the detector that contributes to the interference pattern. Hmm, maybe the particle's direction is determined such that it has a wave-like property leading to interference. But how to model this in a simple way? Alternatively, the position of the particle on the screen is determined by a probability distribution that has maxima and minima as in the interference pattern. So each particle's y coordinate is sampled from this distribution. So the plan is: - For each particle, generate a y-coordinate based on the interference pattern's probability distribution. - Draw a dot at that y on the canvas. - Accumulate the dots over time, showing the build-up of fringes. The key is to find a function that gives the probability of y, which has peaks (bright fringes) and troughs (dark fringes). The probability distribution for the double-slit interference is proportional to the square of the sum of the amplitudes from each slit. Assuming each slit contributes a wave, the total amplitude is A + B, where A and B are the amplitudes from slit 1 and 2. Assuming monochromatic light (fixed wavelength), the path difference between the two paths leads to a
Show code
```html
<!DOCTYPE html>
<html><head><title>Double Slit Experiment</title></head><body style="background:#000;display:flex;flex-direction:column;align-items:center;">
<canvas id="c" width=800 height=400></canvas>
<div id="count" style="color:#fff;font-family:sans-serif;">Particles detected: 0</div>
<script>
const canvas = document.getElementById('c');
const ctx = canvas.getContext('2d');
const slits = [ {x:350, y:180}, {x:450, y:180} ];
let particles = [];
let hits = [];
let count = 0;
let animationId;
ctx.fillStyle='#000';
ctx.fillRect(0,0,canvas.width,canvas.height);
ctx.strokeStyle='#fff';
ctx.lineWidth=2;
ctx.beginPath();
slits.forEach(s => {
ctx.moveTo(s.x-5,s.y-10);
ctx.lineTo(s.x+5,s.y+10);
});
ctx.stroke();
function fireParticle() {
const x = slits[0].x + (Math.random()-0.5)*25;
particles.push({x:x, y:slits[0].y+30, vx:4, vy:0});
}
function animate() {
ctx.fillStyle='#111';
ctx.fillRect(0,0,canvas.width,canvas.height);
// Draw slits
ctx.strokeStyle='#fff';
ctx.lineWidth=2;
ctx.beginPath();
slits.forEach(s => {
ctx.moveTo(s.x-5,s.y-10);
ctx.lineTo(s.x+5,s.y+10);
});
ctx.stroke();
// Update particles
for(let i=particles.length-1; i>=0; i--) {
let p = particles[i];
if(p.x+p.vx > canvas.width) {
const y = p.y;
hits.push({x:canvas.width, y:y});
count++;
document.getElementById('count').textContent = `Particles detected: ${count}`;
particles.splice(i,1);
} else {
p.x += p.vx;
p.y += p.vy;
}
}
// Draw particles
ctx.fillStyle='#fff';
for(let p of particles) {
ctx.beginPath();
ctx.arc(p.x,p.y,3,0,Math.PI*2);
ctx.fill();
}
// Draw hits
const step = 5;
const maxHits = Math.min(hits.length, canvas.height/step);
ctx.fillStyle='#fff';
for(let i=0; i<maxHits; i++) {
let y = hits[i].y;
ctx.beginPath();
ctx.arc(canvas.width - 10, y, 3, 0, Math.PI*2);
ctx.fill();
}
// Fire new particle
if(count % 5 === 0) {
fireParticle();
}
// Generate interference pattern
const prob = [];
for(let y=0; y<canvas.height; y++) {
let phase = Math.sin(y * 0.02 + Date.now() / 1000) * 5;
let amplitude = Math.pow(Math.cos(phase), 2);
prob[y] = amplitude * 20;
}
// Apply interference to hits
while(hits.length > canvas.height/step) {
hits.shift();
}
animationId = requestAnimationFrame(animate);
}
animate();
</script>
</body></html>
```Show code
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Double Slit Experiment</title>
<style>
body {
margin: 0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-color: black;
}
canvas {
border: 2px solid white;
}
</style>
</head>
<body>
<canvas id="myCanvas"></canvas>
<script>
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
let particleCount = 0;
const maxParticles = 10000; // Maximum number of particles to fire
function getRandomPosition() {
const a = Math.sin(particleCount * 0.4) + 1;
return (a - Math.floor(a)) * canvas.width;
}
function drawParticle() {
ctx.fillStyle = 'white';
ctx.beginPath();
ctx.arc(getRandomPosition(), canvas.height / 2, 3, 0, 2 * Math.PI); // Draw a white dot with some radius
ctx.fill();
particleCount++;
}
function animate() {
if (particleCount < maxParticles) {
drawParticle();
} else {
alert('Simulation complete!');
cancelAnimationFrame(animationFrameId);
}
animationFrameId = requestAnimationFrame(animate); // Keep animating until all particles are fired
}
let animationFrameId = requestAnimationFrame(animate);
</script>
</body>
</html>
```Show code
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Double Slit</title>
<style>
html,body{margin:0;height:100%;background:#08090c;color:#e8edf5;font:16px system-ui,sans-serif;overflow:hidden}
#wrap{height:100%;display:grid;place-items:center;background:radial-gradient(circle at 30% 50%,#182033,#08090c 58%)}
canvas{width:min(1100px,100vw);height:min(680px,100vh);display:block}
#count{position:fixed;left:18px;top:14px;padding:8px 12px;background:#111824cc;border:1px solid #304056;border-radius:6px}
</style>
</head>
<body>
<div id="wrap"><canvas id="c"></canvas></div>
<div id="count">Detected: 0</div>
<script>
const c=document.getElementById("c"),x=c.getContext("2d"),label=document.getElementById("count");
let W,H,dpr,particles=[],hits=[],n=0,fade=0;
function size(){
dpr=Math.min(devicePixelRatio||1,2); W=c.clientWidth*dpr; H=c.clientHeight*dpr; c.width=W; c.height=H;
}
addEventListener("resize",size); size();
function intensity(y){
let cy=H*.5, u=(y-cy)/(H*.42), env=Math.exp(-u*u*2.2), phase=u*36;
return env*Math.pow(Math.cos(phase),2);
}
function sampleY(){
for(;;){let y=H*(.09+.82*Math.random()); if(Math.random()<intensity(y))return y;}
}
function launch(){
let sy=sampleY(), slit=sy<H*.5?H*.43:H*.57;
particles.push({t:0,y:sy,slit});
}
function drawScene(){
x.fillStyle="rgba(8,9,12,.22)"; x.fillRect(0,0,W,H);
let sx=W*.09,bx=W*.38,dx=W*.84;
x.strokeStyle="#61708a"; x.lineWidth=2*dpr;
x.beginPath(); x.moveTo(sx,H*.5); x.lineTo(bx,H*.43); x.moveTo(sx,H*.5); x.lineTo(bx,H*.57); x.stroke();
x.fillStyle="#ffcf66"; x.beginPath(); x.arc(sx,H*.5,7*dpr,0,7); x.fill();
x.fillStyle="#a7b1c2"; x.fillRect(bx-5*dpr,H*.13,10*dpr,H*.74);
x.clearRect(bx-6*dpr,H*.405,12*dpr,H*.055); x.clearRect(bx-6*dpr,H*.545,12*dpr,H*.055);
x.fillStyle="#e9edf8"; x.fillRect(dx,H*.08,5*dpr,H*.84);
for(let i=0;i<hits.length;i++){
let h=hits[i], a=Math.min(1,h.a+=.025);
x.fillStyle=`rgba(82,180,255,${a})`; x.beginPath(); x.arc(dx+12*dpr,h.y,1.8*dpr,0,7); x.fill();
}
x.strokeStyle="rgba(90,170,255,.35)";
for(let y=H*.1;y<H*.9;y+=H*.012){
let a=intensity(y)*.42; x.strokeStyle=`rgba(90,170,255,${a})`; x.beginPath(); x.moveTo(dx+28*dpr,y); x.lineTo(W*.96,y); x.stroke();
}
}
function step(){
fade++;
if(fade%4===0)launch();
drawScene();
let bx=W*.38,dx=W*.84,sx=W*.09,alive=[];
for(const p of particles){
p.t+=.018; let t=Math.min(p.t,1), mid=t<.48, q=mid?t/.48:(t-.48)/.52;
let px=mid?sx+(bx-sx)*q:bx+(dx-bx)*q;
let py=mid?H*.5+(p.slit-H*.5)*q:p.slit+(p.y-p.slit)*q;
x.fillStyle="#fff8cf"; x.beginPath(); x.arc(px,py,3*dpr,0,7); x.fill();
if(t<1)alive.push(p); else{hits.push({y:p.y,a:0}); n++; label.textContent="Detected: "+n;}
}
particles=alive;
requestAnimationFrame(step);
}
requestAnimationFrame(step);
</script>
</body>
</html>Show code
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>Double Slit</title>
<style>
html,body{margin:0;height:100%;background:#000;overflow:hidden}
canvas{display:block}
</style></head>
<body>
<canvas id="c"></canvas>
<script>
const c=document.getElementById('c');
const ctx=c.getContext('2d');
const ac=document.createElement('canvas');
const actx=ac.getContext('2d');
function resize(){c.width=innerWidth;c.height=innerHeight;ac.width=innerWidth;ac.height=innerHeight;}
resize();
window.addEventListener('resize',resize);
let count=0;
let particles=[];
const f1=0.05,f2=0.007;
function sampleY(maxY){
while(true){
const y=(Math.random()*2-1)*maxY;
const pd=f1*y,pa=f2*y;
const sa=pa===0?1:Math.sin(pa)/pa;
const I=sa*sa*Math.cos(pd)*Math.cos(pd);
if(Math.random()<I)return y;
}
}
function geo(){
const cy=c.height/2, barrierX=c.width*0.25, screenX=c.width*0.85;
const slitSep=Math.min(60,c.height*0.08), slitH=Math.max(6,c.height*0.015);
return {cy,barrierX,screenX,slitSep,slitH};
}
function spawn(){
const g=geo();
const slitY=Math.random()<0.5?g.cy-g.slitSep/2:g.cy+g.slitSep/2;
const landY=g.cy+sampleY(c.height*0.4);
particles.push({t:0,sourceX:40,barrierX:g.barrierX,screenX:g.screenX,cy:g.cy,slitY,landY,dur:55+Math.random()*15});
}
function update(){
for(let i=particles.length-1;i>=0;i--){
const p=particles[i];
p.t++;
if(p.t>=p.dur){
actx.fillStyle='rgba(255,255,255,0.85)';
actx.beginPath();
actx.arc(p.screenX,p.landY,1.4,0,Math.PI*2);
actx.fill();
count++;
particles.splice(i,1);
}
}
}
function drawStatic(){
ctx.fillStyle='#050508';
ctx.fillRect(0,0,c.width,c.height);
const g=geo();
const y1=g.cy-g.slitSep/2-g.slitH/2, y2=g.cy-g.slitSep/2+g.slitH/2;
const y3=g.cy+g.slitSep/2-g.slitH/2, y4=g.cy+g.slitSep/2+g.slitH/2;
ctx.fillStyle='#999';
ctx.fillRect(g.barrierX-3,0,6,y1);
ctx.fillRect(g.barrierX-3,y2,6,y3-y2);
ctx.fillRect(g.barrierX-3,y4,6,c.height-y4);
ctx.fillStyle='#4af';
ctx.beginPath();
ctx.arc(40,g.cy,8,0,Math.PI*2);
ctx.fill();
ctx.strokeStyle='#444';
ctx.beginPath();
ctx.moveTo(g.screenX,0);
ctx.lineTo(g.screenX,c.height);
ctx.stroke();
ctx.drawImage(ac,0,0);
}
function drawParticles(){
ctx.fillStyle='#ffd24a';
for(const p of particles){
const half=p.dur/2;
let x,y;
if(p.t<half){
const k=p.t/half;
x=p.sourceX+(p.barrierX-p.sourceX)*k;
y=p.cy+(p.slitY-p.cy)*k;
}else{
const k=(p.t-half)/half;
x=p.barrierX+(p.screenX-p.barrierX)*k;
y=p.slitY+(p.landY-p.slitY)*k;
}
ctx.beginPath();
ctx.arc(x,y,3,0,Math.PI*2);
ctx.fill();
}
}
function drawText(){
ctx.fillStyle='#fff';
ctx.font='16px sans-serif';
ctx.fillText('Particles detected: '+count,20,26);
}
function loop(){
spawn();
update();
drawStatic();
drawParticles();
drawText();
requestAnimationFrame(loop);
}
loop();
</script>
</body>
</html>Show code
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>Double Slit</title>
<style>html,body{margin:0;background:#04040c;overflow:hidden}canvas{display:block;margin:0 auto}</style></head>
<body><canvas id="c" width="900" height="600"></canvas>
<script>
const cv=document.getElementById('c'),ctx=cv.getContext('2d');
const W=900,H=600,SRC=70,BAR=300,SCR=852,CY=H/2;
const acc=document.createElement('canvas');acc.width=W;acc.height=H;
const actx=acc.getContext('2d');
const gap=46,slitH=16,s1=CY-gap/2,s2=CY+gap/2;
const b=0.052,cEnv=0.011;
let count=0,parts=[];
function sinc(x){return x===0?1:Math.sin(x)/x}
function intensity(dy){const s=sinc(cEnv*dy);return Math.cos(b*dy)**2*s*s}
function sampleY(){
for(let i=0;i<300;i++){
const dy=(Math.random()*2-1)*270;
if(Math.random()<intensity(dy))return CY+dy;
}
return CY;
}
function spawn(){
const sl=Math.random()<0.5?s1:s2;
parts.push({x:SRC,y:CY+(Math.random()-0.5)*26,sy:sl+(Math.random()-0.5)*(slitH-4),ty:sampleY(),ph:0,sp:7+Math.random()*4});
}
function drawStatic(){
ctx.fillStyle="#04040c";ctx.fillRect(0,0,W,H);
ctx.drawImage(acc,0,0);
ctx.fillStyle="#888";
ctx.fillRect(BAR-5,0,10,s1-slitH/2);
ctx.fillRect(BAR-5,s1+slitH/2,10,s2-s1-slitH);
ctx.fillRect(BAR-5,s2+slitH/2,10,H-s2-slitH/2);
ctx.fillStyle="#334";ctx.fillRect(SCR+6,0,6,H);
ctx.fillStyle="#ffd54a";
ctx.beginPath();ctx.arc(SRC-14,CY,9,0,7);ctx.fill();
ctx.fillStyle="#cfd6ff";ctx.font="16px monospace";
ctx.fillText("particles detected: "+count,20,28);
}
function tick(){
for(let k=0;k<3;k++)spawn();
for(let i=parts.length-1;i>=0;i--){
const p=parts[i];
if(p.ph===0){
const dx=BAR-p.x;
p.x+=p.sp;
p.y+=(p.sy-p.y)*Math.min(1,p.sp/Math.max(dx,1));
if(p.x>=BAR){p.x=BAR;p.ph=1;p.fy=p.sy;p.y=p.sy;}
}else{
p.x+=p.sp;
const t=(p.x-BAR)/(SCR-BAR);
p.y=p.fy+(p.ty-p.fy)*t;
if(p.x>=SCR){
count++;
actx.fillStyle="rgba(120,220,255,0.85)";
actx.fillRect(SCR-2+Math.random()*6,p.ty,2,2);
parts.splice(i,1);
}
}
}
drawStatic();
ctx.fillStyle="#8ff";
for(const p of parts){ctx.beginPath();ctx.arc(p.x,p.y,2,0,7);ctx.fill();}
requestAnimationFrame(tick);
}
requestAnimationFrame(tick);
</script>
</body></html>Show code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Double Slit Experiment</title>
<style>
body { margin: 0; padding: 10px; font-family: monospace; overflow: hidden; background: #000; color: #0f0; }
canvas { display: block; margin: 10px auto; background: #111; border: 1px solid #0f0; }
div { text-align: center; font-size: 14px; }
</style>
</head>
<body>
<div id="count">Particles: 0</div>
<canvas id="c" width="800" height="600"></canvas>
<script>
const canvas = document.getElementById('c');
const ctx = canvas.getContext('2d');
const w = canvas.width, h = canvas.height;
let particles = 0;
let dots = [];
const sourceX = 50;
const slitY1 = h / 2 - 40;
const slitY2 = h / 2 + 40;
const slitWidth = 10;
const detectorX = w - 50;
function sampleDetectorY() {
const y1 = slitY1 + slitWidth / 2;
const y2 = slitY2 + slitWidth / 2;
const d1 = Math.abs(y1 - (h / 2));
const d2 = Math.abs(y2 - (h / 2));
const dist = 0.8 * (detectorX - sourceX);
const wavelength = 30;
const phi1 = 2 * Math.PI * d1 / wavelength;
const phi2 = 2 * Math.PI * d2 / wavelength;
const I1 = Math.cos(phi1) ** 2;
const I2 = Math.cos(phi2) ** 2;
const I = I1 + I2 + 2 * Math.sqrt(I1 * I2) * Math.cos(phi1 - phi2);
const u = Math.random();
let y;
if (u < I / 4) y = h / 2 + (Math.random() - 0.5) * h * 0.4;
else if (u < I / 2) y = slitY1 + (Math.random() - 0.5) * 100;
else y = slitY2 + (Math.random() - 0.5) * 100;
return Math.max(0, Math.min(h, y));
}
function animate() {
ctx.fillStyle = '#111';
ctx.fillRect(0, 0, w, h);
ctx.strokeStyle = '#0f0';
ctx.lineWidth = 2;
ctx.moveTo(sourceX, h / 2);
ctx.lineTo(sourceX + 50, h / 2);
ctx.stroke();
ctx.fillStyle = '#444';
ctx.fillRect(w / 2 - 2, slitY1, 4, slitWidth);
ctx.fillRect(w / 2 - 2, slitY2, 4, slitWidth);
if (particles % 4 === 0 && particles < 1200) {
const y = sampleDetectorY();
dots.push({ x: detectorX, y: y });
particles++;
}
ctx.fillStyle = '#0f0';
for (let dot of dots) {
ctx.fillRect(dot.x - 1, dot.y - 1, 2, 2);
}
ctx.fillStyle = '#666';
ctx.font = '14px monospace';
ctx.fillText('Particles: ' + particles, 20, 30);
requestAnimationFrame(animate);
}
animate();
</script>
</body>
</html>Results at a glance— every model in this round with score, response time and status.
Who wrote what
| Model | Blind score | Latency | Status |
|---|---|---|---|
| qwen3:8b | — | — | harness |
| mistral-small:24b | — | 48.0 s | OK |
| qwen3.5:9b | — | 39.3 s | OK |
| qwen3:14b | — | 21.2 s | OK |
| gemma4:26b | — | — | harness |
| deepseek-r1:14b | — | 36.0 s | OK |
| llama3.1:8b | — | 58.4 s | OK |
| qwen3-coder:30b | — | 15.3 s | OK |
| qwq:32b | — | 119.0 s | OK |
| deepseek-r1:32b | — | 118.5 s | OK |
| command-r:35b | — | 121.0 s | OK |
Frontier reference — outside the blind field
These models answered the identical prompt outside the blind field. They are deliberately not scored and not part of the blind comparison — they are there so you can see where a frontier model lands on the same task.
Show code
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Double-Slit Interference</title>
<style>
html,body{margin:0;height:100%;background:#05070d;color:#cfe9f5;font:14px/1.4 ui-sans-serif,system-ui,Segoe UI,Roboto,sans-serif;display:flex;align-items:center;justify-content:center}
canvas{max-width:100%;height:auto;background:#05070d;box-shadow:0 0 60px #0af3;border-radius:8px}
</style>
</head>
<body>
<canvas id="c" width="960" height="560"></canvas>
<script>
const c=document.getElementById('c'),x=c.getContext('2d'),W=960,H=560,CY=H/2;
const SX=70,BX=380,DX=820,DW=95,SLIT=20,GAP=19,FR=26,ENV=150,YMAX=250;
const dl=document.createElement('canvas');dl.width=W;dl.height=H;
const d=dl.getContext('2d');d.globalCompositeOperation='lighter';d.fillStyle='rgba(80,185,255,0.40)';
const S1=CY-GAP,S2=CY+GAP;
let count=0,p=null;
function inten(y){const a=Math.PI*y/FR,b=Math.PI*y/ENV,s=b===0?1:Math.sin(b)/b;const cc=Math.cos(a);return cc*cc*s*s;}
function sampleY(){for(let i=0;i<400;i++){const y=(Math.random()*2-1)*YMAX;if(Math.random()<inten(y))return y;}return 0;}
function land(){const y=CY+sampleY();const px=DX+8+Math.random()*(DW-16);d.fillRect(px,y,1.9,1.9);count++;return{px:px,py:y};}
function fire(){const t=land();p={t:0,px:t.px,py:t.py};}
function bg(){
x.fillStyle='#05070d';x.fillRect(0,0,W,H);
const g=x.createRadialGradient(SX,CY,0,SX,CY,120);g.addColorStop(0,'rgba(255,190,90,0.25)');g.addColorStop(1,'rgba(255,190,90,0)');
x.fillStyle=g;x.fillRect(0,0,300,H);
x.strokeStyle='rgba(120,200,255,0.10)';x.lineWidth=1;
x.beginPath();x.moveTo(SX,CY);x.lineTo(BX,S1);x.moveTo(SX,CY);x.lineTo(BX,S2);
x.moveTo(BX,S1);x.lineTo(DX,CY-160);x.moveTo(BX,S1);x.lineTo(DX,CY+160);
x.moveTo(BX,S2);x.lineTo(DX,CY-160);x.moveTo(BX,S2);x.lineTo(DX,CY+160);x.stroke();
x.fillStyle='#ffd27a';x.beginPath();x.arc(SX,CY,7,0,7);x.fill();
x.fillStyle='#1a2333';
x.fillRect(BX-7,40,14,(S1-SLIT/2)-40);
x.fillRect(BX-7,S1+SLIT/2,14,(S2-SLIT/2)-(S1+SLIT/2));
x.fillRect(BX-7,S2+SLIT/2,14,H-40-(S2+SLIT/2));
x.fillStyle='#31435c';
x.fillRect(BX-7,40,14,3);x.fillRect(BX-7,H-43,14,3);
x.fillStyle='rgba(255,255,255,0.03)';x.fillRect(DX,40,DW,H-80);
x.strokeStyle='rgba(140,210,255,0.28)';x.strokeRect(DX+.5,40.5,DW-1,H-81);
}
function hud(){
x.fillStyle='rgba(5,10,18,0.72)';x.fillRect(20,20,232,58);
x.strokeStyle='rgba(120,200,255,0.25)';x.strokeRect(20.5,20.5,231,57);
x.fillStyle='#8fd6ff';x.font='12px ui-sans-serif,system-ui,sans-serif';
x.fillText('PARTICLES DETECTED',34,42);
x.fillStyle='#eaf7ff';x.font='700 26px ui-monospace,Menlo,Consolas,monospace';
x.fillText(String(count).padStart(6,'0'),34,68);
x.fillStyle='rgba(180,215,240,0.65)';x.font='12px ui-sans-serif,system-ui,sans-serif';
x.fillText('SOURCE',SX-24,CY+34);
x.fillText('DOUBLE SLIT',BX-38,H-20);
x.fillText('DETECTOR SCREEN',DX-26,H-20);
x.fillText('one particle at a time → interference emerges',34,H-20);
}
function glow(px,py,r,a){
const g=x.createRadialGradient(px,py,0,px,py,r);
g.addColorStop(0,'rgba(190,240,255,'+a+')');g.addColorStop(1,'rgba(120,200,255,0)');
x.fillStyle=g;x.beginPath();x.arc(px,py,r,0,7);x.fill();
}
function flight(){
if(!p)return;
const t=p.t;
if(t<0.5){
const u=t/0.5;
const ax=SX+(BX-SX)*u,a1=CY+(S1-CY)*u,a2=CY+(S2-CY)*u;
glow(ax,a1,7,0.85);glow(ax,a2,7,0.85);
}else{
const u=(t-0.5)/0.5;
const b1x=BX+(p.px-BX)*u,b1y=S1+(p.py-S1)*u;
const b2x=BX+(p.px-BX)*u,b2y=S2+(p.py-S2)*u;
glow(b1x,b1y,7,0.85);glow(b2x,b2y,7,0.85);
}
p.t+=0.09;
if(p.t>=1){glow(p.px,p.py,14,0.9);p=null;}
}
function loop(){
const extra=Math.min(24,Math.floor(count/90));
for(let i=0;i<extra;i++)land();
if(!p)fire();
bg();
x.globalCompositeOperation='lighter';
x.drawImage(dl,0,0);
flight();
x.globalCompositeOperation='source-over';
hud();
requestAnimationFrame(loop);
}
loop();
</script>
</body>
</html>