OverviewCode › R97
Code · blind round

R97 · Circle packing without overlap

blind round 4/8 local models answered

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 8 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.

Show task
Create ONE self-contained HTML file (STRICT LIMIT: max 7000 characters in total — this is a budget on characters, not on lines, so removing line breaks does not help) that packs circles into a <canvas> without overlap: repeatedly pick a random free spot, grow a new circle there until it touches an existing circle or the border, then keep it and start the next one. Draw each circle as it grows, colour it by its final size, and show how many circles are placed and how much of the area is covered. Start over with a fresh pattern once the canvas is full. Smooth requestAnimationFrame animation, NO user input, starts immediately and keeps running (restart with a fresh random instance when finished). No external libraries, no comments needed. Output ONLY the HTML file content, nothing else.

The answers

Local models (Brain cluster) — identical prompt, shuffled order (the sequence is not a ranking)
gemma4:26bharness
No answer reached us (TIMEOUT) — and the reason lies with our setup, not with the model: reasoning consumed the entire token budget (3 min 28 s, zero characters of answer); larger budgets are refused by the gateway Counted as a did-not-finish, but it is not evidence about this model.
qwen3:14bERRBLANKFORMAT
Show code
```html
<!DOCTYPE html>
<html>
<body>
<canvas id="c"></canvas>
<script>
const c = document.getElementById('c');
const ctx = c.getContext('2d');
let circles = [];
let currentCircle = null;
let animationFrameId = null;

c.width = 800;
c.height = 600;

function init() {
    circles = [];
    currentCircle = null;
    draw();
    gameLoop();
}

function calculateMaxRadius(x, y) {
    let r = Math.min(x, c.width - x, y, c.height - y);
    for (const circ of circles) {
        const dx = x - circ.x;
        const dy = y - circ.y;
        const dist = Math.sqrt(dx * dx + dy * dy);
        r = Math.min(r, dist - circ.radius);
    }
    return r > 0 ? r : 1;
}

function placeCircle() {
    if (circles.length >= 50) { // Stop condition
        init(); 
        return false;
    }
    const x = Math.random() * c.width;
    const y = Math.random() * c.height;
    const maxR = calculateMaxRadius(x, y);

    if (maxR > 5) { // Ensure the circle is sizable enough to be visible/meaningful
        currentCircle = { x: x, y: y, radius: 0, targetRadius: maxR };
        return true;
    }
    return false;
}

function draw() {
    ctx.clearRect(0, 0, c.width, c.height);
    for (const circ of circles) {
        ctx.beginPath();
        ctx.arc(circ.x, circ.y, circ.radius, 0, Math.PI * 2);
        ctx.fillStyle = `hsl(${Math.floor(360 * (circ.radius / c.width))}, 70%, ${10 + Math.min(50, circ.radius / 2))}%)`;
        ctx.fill();
    }

    if (currentCircle) {
        const r = currentCircle.radius;
        const targetR = currentCircle.targetRadius;
        const growthRate = Math.max(r * 0.1, 0.5); // Ensures visible growth
        currentCircle.radius = Math.min(r + growthRate, targetR);

        ctx.beginPath();
        ctx.arc(currentCircle.x, currentCircle.y, currentCircle.radius, 0, Math.PI * 2);
        ctx.strokeStyle = '#333';
        ctx.lineWidth = 2;
        ctx.stroke();

        if (Math.abs(currentCircle.radius - targetR) < 1) {
            circles.push({ x: currentCircle.x, y: currentCircle.y, radius: currentCircle.targetRadius });
            currentCircle = null;
            // Attempt to place the next circle immediately when the current one finishes
            setTimeout(() => {
                placeNext();
            }, 50);
        }
    }
}

function updateMetrics() {
    const coveredArea = circles.reduce((sum, c) => sum + Math.PI * c.radius * c.radius, 0);
    const totalArea = c.width * c.height;
    const coveragePercent = (coveredArea / totalArea) * 100;

    let info = `Circles: ${circles.length}<br>`;
    info += `Coverage: ${coveragePercent.toFixed(2)}%`;
    document.body.innerHTML = `<canvas id="c" width="${c.width}" height="${c.height}"></canvas><div style="position:absolute; top:10px; left:10px; color:#333;">${info}</div>`;
    // Re-apply the canvas size after modifying innerHTML to keep context valid 
    // (Though in a real scenario, we'd use dedicated UI elements)
    c.width = c.width; 
}

function placeNext() {
    if (placeCircle()) {
        updateMetrics();
    } else {
        console.log("Canvas full or no viable spot found.");
    }
}


function gameLoop() {
    draw();
    updateMetrics();
    animationFrameId = requestAnimationFrame(gameLoop);
}

// Start the process
init();
</script>
</body>
</html>
```
No usable answer reached the harness (TIMEOUT). Counted as a did-not-finish.
qwen3.5:9bOKFORMAT
Show code
```html
<!DOCTYPE html>
<html>
<head>
<title>Circle Packing Simulation</title>
<style>
    body {margin:0;overflow:hidden;background:#222;}
    canvas {display:block;}
</style>
</head>
<body>
<canvas id="c"></canvas>
<script>
const c = document.getElementById('c');
const ctx = c.getContext('2d');
let W, H;
let circles = [];
let isRunning = true;

function resize() {
    W = H = window.innerWidth;
    c.width = W;
    c.height = H;
}
window.addEventListener('resize', resize);
resize();

let state = { count: 0, area: 0 };

function drawMetrics() {
    ctx.fillStyle = 'white';
    ctx.font = '12px Arial';
    ctx.fillText(`Circles: ${state.count}`, 10, 20);
    ctx.fillText(`Coverage: ${(state.area * 100).toFixed(1)}%`, W - 150, 20);
}

function draw() {
    ctx.clearRect(0, 0, W, H);
    circles.forEach(c => {
        // Color based on radius (normalized for visual effect)
        const hue = Math.min(360, c.r * 5);
        ctx.fillStyle = `hsl(${hue}, 70%, ${Math.max(40, c.r*10)}%)`;
        ctx.beginPath();
        ctx.arc(c.x, c.y, c.r, 0, Math.PI * 2);
        ctx.fill();
    });
    drawMetrics();
}

function tryPlaceCircle(startX, startY) {
    let r = Math.min(startX, W - startX, startY, H - startY);
    r *= 0.95; // Start slightly smaller than max possible

    while (true) {
        let canGrow = true;
        for (const c of circles) {
            const distSq = (startX - c.x)**2 + (startY - c.y)**2;
            const requiredDist = c.r + r;
            if (distSq < requiredDist**2) {
                canGrow = false;
                break;
            }
        }

        let maxPossibleR = Math.min(startX, W - startX, startY, H - startY);
        for (const c of circles) {
            const dist = Math.sqrt((startX - c.x)**2 + (startY - c.y)**2);
            maxPossibleR = Math.min(maxPossibleR, dist - c.r);
        }

        if (canGrow && r < maxPossibleR * 0.98) {
             // Check if we are close enough to the theoretical maximum
             let toleranceCheck = Math.abs(r - maxPossibleR);
             if (toleranceCheck > 1) { // If difference is significant, we can grow
                 r = maxPossibleR;
                 break;
             } else {
                // Stable size reached or near border/circle contact
                break;
             }
        }

        // Simple growth step for animation
        if (r < Math.min(startX, W - startX, startY, H - startY) * 0.98) {
            r *= 1.05;
        } else {
             break; // Cannot grow further
        }

        // Safety break to prevent infinite loops near boundaries
        if (r > Math.min(startX, W - startX, startY, H - startY)) break;
    }
    return r;
}

function placeCircle() {
    const x = Math.random() * (W - 100) + 50;
    const y = Math.random() * (H - 100) + 50;
    let newR = tryPlaceCircle(x, y);

    // Check if placement is viable or if we are too close to the edge/existing circles
    if (newR < 5) {
        return false; // Cannot place a circle here
    }

    circles.push({ x: x, y: y, r: newR });
    state.count++;
    state.area += Math.PI * newR**2;
    return true;
}

function gameLoop() {
    if (!isRunning) return;

    // Randomly attempt placement repeatedly until successful or failed many times
    let attempts = 0;
    while (attempts < 10 && placeCircle()) {
        attempts++;
    }

    draw();

    requestAnimationFrame(gameLoop);
}

function resetGame() {
    circles = [];
    state.count = 0;
    state.area = 0;
    placeCircle(); // Place the first circle immediately to start
}

// Start everything
resetGame();
gameLoop();
</script>
</body>
</html>
```
No usable answer reached the harness (TIMEOUT). Counted as a did-not-finish.
deepseek-r1:14bERRBLANKFORMAT
Show code
```html
<!DOCTYPE html>
<html><body style="background:#000;margin:0;display:flex;justify-content:center;align-items:center;height:100vh">
<canvas id=c></canvas>
<div id=i style="position:absolute;left:0;top:0;color:white;font-family:Arial">Circles: 0</div>
<div id=ia style="position:absolute;left:0;top:20;color:white;font-family:Arial">Coverage: 0%</div>
<script>
const c=document.getElementById('c'), ctx=c.getContext('2d');
const cw=800,ch=600;
c.width=cw;c.height=ch;

let circles=[],maxRadius=5,cells=40,minR=2,maxR=100;
let count=0,areaCovered=0;

class Circle{
  constructor(x,y,r){
    this.x=x;this.y=y;this.r=r;
    this.growing=false;
    this.color=`hsl(${Math.random()*360},70%,50%)`;
  }
  overlaps(other){
    const dx=this.x-other.x,dy=this.y-other.y,d=dx*dx+dy*dy;
    return d< (this.r+other.r)**2;
  }
  draw(){
    ctx.beginPath();
    if(this.growing)ctx.arc(this.x,this.y,this.r,0,Math.PI*2);
    else{
      ctx.fillStyle=this.color;ctx.fillRect(this.x-this.r,this.y-this.r,2*this.r,2*this.r);
    }
    ctx.strokeStyle='white';ctx.lineWidth=1;
    ctx.stroke();
  }
}

function getCell(x,y){
  return Math.floor(x/cellSize),Math.floor(y/cellSize);
}

let cellSize=cw/cells,chSize=ch/cells;

function checkCollision(x,y,r){
  for(let i of circles)if(i.x-i.r<=x+r &&i.x+i.r>=x-r &&i.y-i.r<=y+r &&i.y+i.r>=y-r &&Math.hypot(i.x-x,i.y-y)<r+i.r+1)c.fillStyle='white'; // Check collisions
  return false;
}

function growCircle(c,x,y,r,step){
  if(step>1000||c.x+c.r>=cw ||c.x-c.r<=0 ||c.y+c.r>=ch ||c.y-c.r<=0){c.growing=false;return;}
  for(let i of circles)if(i.overlaps(c)){
    c.growing=false;
    return;
  }
  ctx.clearRect(0,0,cw,ch);
  circles.forEach(c=>c.draw());
  count=circles.length;areaCovered=circles.reduce((a,c)=>a+Math.PI*c.r**2,0)/(cw*ch)*100;
  document.getElementById('i').textContent=`Circles: ${count}`;
  document.getElementById('ia').textContent=`Coverage: ${areaCovered.toFixed(1)}%`;
  requestAnimationFrame(()=>growCircle(c,x,y,r,step+1));
}

function placeNewCircle(){
  if(count>=cells*cells)clearCanvas();
  const x=Math.random()*(cw-2*minR)+minR;
  const y=Math.random()*(ch-2*minR)+minR;
  const r=minR+(Math.random()*(maxR-minR));
  const newC=new Circle(x,y,r);
  if(checkCollision(newC.x,newC.y,newC.r)){
    circles.push(newC);
    growCircle(newC,x,y,r,0);
  }else placeNewCircle();
}

function clearCanvas(){
  ctx.clearRect(0,0,cw,ch);
  circles=[];count=0;areaCovered=0;
  document.getElementById('i').textContent='Circles: 0';
  document.getElementById('ia').textContent='Coverage: 0%';
  placeNewCircle();
}

placeNewCircle();

setInterval(clearCanvas,3e4*1e6); // No, wait...
// Wait, no. The animation should restart when full.
</script>
</body></html>
```
qwen3:8bharness
No answer reached us (ERR) — and the reason lies with our setup, not with the model: reasoning consumed the entire token budget and the answer stayed empty; the gateway rejects budgets above 3000 tokens Counted as a did-not-finish, but it is not evidence about this model.
qwen3-coder:30bERRBLANKMINIFIEDFORMAT
Show code
```html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Circle Packing</title></head>
<body><canvas id="canvas" style="border:1px solid #333;"></canvas><script>const canvas=document.getElementById('canvas');const ctx=canvas.getContext('2d');let W=600,H=500;canvas.width=W;canvas.height=H;ctx.fillStyle='#111';ctx.fillRect(0,0,W,H);let circles=[];let animationFrameId=null;function init() {circles=[];let maxAttempts=200;for (let i=0;i<maxAttempts;++i){const x=Math.random()*W;const y=Math.random()*H;if(x-10>0&&y-10>0&&x+10<W&&y+10<H){const r_start=Math.min(Math.random()*20, Math.max(5, 1));let currentR=r_start;if(!isOverlapping(x, y, currentR)){circles.push({x:x,y:y,r:currentR,finalR:0});}else{break;}}drawStats();animate();/* The main loop */const animate=(t)=>{animationFrameId=requestAnimationFrame(()=>runCycle(t));};function runCycle(t){if (circles.length > 0) {const firstCircle=circles[0];if(firstCircle.finalR===0 && !isOverlapping(firstCircle.x, firstCircle.y, firstCircle.r*1.1)){// Grow check
                let newR = Math.min(W/2, H/2);while(!isOverlapping(firstCircle.x, firstCircle.y, newR)){newR+=0.5;}newR-=0.5;if(newR > firstCircle.r){firstCircle.finalR=newR;drawGrowth(firstCircle);else{/* Start new circle or finish */}}
            } else if (circles[circles.length-1].finalR>0 && circles.filter(c=>c.finalR===0).every(Boolean)){/* All finished, need restart check */const coverageRatio=(Math.PI*(circles.reduce((sum, c)=>sum+c.r*2*c.y/W,0)/3)+Math.PI*(circles.reduce((sum, c)=>sum+c.x*2*c.finalR/H,0)/3))/ (W*H);if(coverageRatio>0.8){/* Restart */init();drawGrowth(circles[0]);return;}} else { /* Start new circle if current one is small or finished */
                const lastCircle=circles[circles.length-1];if(!lastCircle||lastCircle.finalR===0 || Math.random()<0.2) {const x=Math.random()*W;const y=Math.random()*H;let r_start=Math.min(Math.random()*20, 15);if(x-r_start>0&&y-r_start>0&&x+r_start<W&&y+r_start<H){circles.push({x:x,y:y,r:r_start,finalR:0});}else{return;}}
            }
        drawGrowth(circles[0]);
    } else {/* First circle setup */if (Math.random() < 0.5) {const x=W/2;let y=Math.random()*H;let r_start=10;while(!isOverlapping(x,y,r_start*1.1)){y+=1;}circles.push({x:x,y:y,r:r_start,finalR:0});}else {const y=H/2;let x=Math.random()*W;let r_start=10;while(!isOverlapping(x,y,r_start*1.1)){x+=1;}circles.push({x:x,y:y,r:r_start,finalR:0});}}
    animationFrameId=requestAnimationFrame(()=>runCycle(t));}function isOverlapping(cx,cy,cr){let overlap=false;for(const c of circles){if(c.finalR>0&&Math.hypot(cx-c.x,cy-c.y)<c.r+cr-(c.finalR/2)){overlap=true;break;}if(c.finalR===0 && Math.hypot(cx-c.x,cy-c.y)<c.r+cr){overlap=true;break;}}return overlap}function drawGrowth(circle){ctx.beginPath();ctx.arc(circle.x,circle.y,circle.r*1.1,0,Math.PI*2);ctx.strokeStyle=`rgba(50, 50, 255, ${circle.finalR/W * 0.8 + 0.2})`;ctx.lineWidth=3;ctx.stroke();ctx.beginPath();ctx.arc(circle.x,circle.y,Math.min(canvas.width/2, canvas.height/2),0,Math.PI*2);ctx.clip();let alpha=Math.max(0,Math.min(1,(circle.finalR-circle.r)/5)));if(alpha>0){ctx.fillStyle=`rgba(255, 100, 0, ${alpha * 0.8})`;ctx.globalAlpha=alpha*0.8;ctx.fill();}}function drawStats(){let totalArea=0,count=circles.length;for(const c of circles){totalArea+=Math.PI*(c.finalR>0?c.finalR:c.r)*c.finalR/2;}let coverageRatio=(totalArea/(W*H)).toFixed(3);ctx.fillStyle='#fff';ctx.font='16px Arial';ctx.fillText(`Circles: ${count} | Coverage: ${coverageRatio}`, 10, 20);if (circles[0] && circles[0].finalR===0) ctx.fillText("Growing...", 10, 40);else if(count>=25){ctx.fillStyle='rgba(0,0,0,0.3)';ctx.fillRect(0,0,W,H);}else{ctx.fillStyle='#aaa';ctx.font='14px Arial';ctx.fillText("Click to start (or wait for auto-start)", 10, H-20);}}document.addEventListener('DOMContentLoaded',()=>init());</script></body></html>
```
Results at a glance— every model in this round with score, response time and status.

Who wrote what

ModelBlind scoreLatencyStatus
gemma4:26b harness
qwen3:14b 20.3 sOK
llama3.1:8b DNF
qwen3.5:9b 30.1 sOK
mistral-small:24b DNF
deepseek-r1:14b 91.8 sOK
qwen3:8b harness
qwen3-coder:30b 22.6 sOK