OverviewCode › R60
Code · blind round

R60 · Dijkstra vs A* on a weighted grid

blind round 5/8 local models answered

Answers below are anonymized and shuffled. Read, judge, pick a favourite — then scroll down and reveal the models.

The reveal also holds a frontier reference on the same task (Claude Opus 5) — kept out of sight here so it cannot steer your judgement.

Show task
Create ONE self-contained HTML file (STRICT LIMIT: max 120 lines total) that runs Dijkstra and A* side by side on the SAME randomly weighted 30x20 grid, drawn on one <canvas> split into two panels. Animate the search step by step: colour each cell by its terrain cost, mark visited cells, mark the frontier in a different colour, and draw the final shortest path once found. Show the number of cells each algorithm expanded and the total path cost as live labels — both paths must have the same cost, only the expanded counts may differ. 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 — blind

Local models (Brain cluster) — identical prompt, anonymized order
MODEL Aqwen3.5:9bBLANKLIMFORMAT
Show code
```html
<!DOCTYPE html>
<html>
<head><title>Dijkstra vs A*</title></head>
<style>body {display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background: #111; color: white;}#container {display: flex; width: 92vw; max-width: 1200px;}canvas {border: 2px solid #444; box-shadow: 0 0 15px rgba(0,0,0,0.5);}#dijkstra {flex: 1;}#astar {flex: 1;}h3 {text-align: center; margin-top: 5px; color: #aaa;}</style>
<body><div id="container"><canvas id="dijkstra"></canvas><canvas id="astar"></canvas></div>
<script>
const C = window.innerWidth * 0.92 / 2 - 40; // Constant for canvas size calculation (adjusted for padding)
let GRID_W = 30;
let GRID_H = 20;
let CANVAS_SIZE = 600;

const cDijkstra = document.getElementById('dijkstra');
const cAstar = document.getElementById('astar');
cDijkstra.width = CANVAS_SIZE;
cDijkstra.height = CANVAS_SIZE;
cAstar.width = CANVAS_SIZE;
cAstar.height = CANVAS_SIZE;

const ctxD = cDijkstra.getContext('2d');
const ctxA = cAstar.getContext('2d');

let grid, start, end;
let isRunning = true;
let stepQueue = [];
let animationFrameId = null;

class PriorityQueue { constructor() { this.heap = []; } isEmpty() { return this.heap.length === 0; } peek() { return this.heap[0]; } pop() { const item = this.heap.shift(); this.heap.pop(); return item; } push(item) { this.heap.push(item); this.heap.sort((a, b) => a.cost - b.cost); }}

function initGrid() {
    grid = Array(GRID_H).fill(0).map(() => Array(GRID_W).fill(0).map(() => Math.floor(Math.random() * 3) + 1));
    start = [1, 1]; end = [GRID_W - 2, GRID_H - 2];
}

function setupVisualization(ctx) {
    const cell = CANVAS_SIZE / GRID_W;
    for (let y = 0; y < GRID_H; y++) {
        for (let x = 0; x < GRID_W; x++) {
            ctx.fillStyle = `hsl(${grid[y][x] * 30}, 70%, ${50 + grid[y][x] * 10}%)`;
            ctx.fillRect(x * cell, y * cell, cell - 1, cell - 1);
        }
    }
}

function getNeighbors(r, c) {
    const n = [];
    [[0, 1], [0, -1], [1, 0], [-1, 0]].forEach(([dr, dc]) => {
        const nr = r + dr;
        const nc = c + dc;
        if (nr >= 0 && nr < GRID_H && nc >= 0 && nc < GRID_W) n.push([nr, nc]);
    });
    return n;
}

function reconstructPath(cameFrom, current) {
    let path = [];
    let temp = [...current];
    while (temp[1] !== start[1] || temp[0] !== start[0]) {
        path.unshift(temp);
        const key = `${temp[0]},${temp[1]}`;
        if (!cameFrom.has(key)) break;
        let next = cameFrom.get(key);
        temp = next;
    }
    path.unshift(start);
    return path;
}

// --- Dijkstra's Algorithm (Uses Priority Queue based on cost) ---
function runDijkstra() {
    const dist = Array(GRID_H).fill(0).map(() => Array(GRID_W).fill(Infinity));
    const cameFrom = new Map();
    const pq = new PriorityQueue();

    dist[start[0]][start[1]] = 0;
    pq.push({ cost: 0, r: start[0], c: start[1] });
    
    let expandedCount = 0;
    let currentPathCost = Infinity;
    stepQueue = [];

    while (!pq.isEmpty()) {
        const { cost, r, c } = pq.pop();
        if (cost > dist[r][c]) continue;

        expandedCount++;
        stepQueue.push({ type: 'expand', r, c, cost, state: { visited: [[r, c]], frontier: [] } });

        if (r === end[0] && c === end[1]) {
            currentPathCost = cost; 
            // Path reconstruction is handled after the loop finishes successfully
            break;
        }
        
        for (const [nr, nc] of getNeighbors(r, c)) {
            const moveCost = grid[nr][nc];
            const newCost = dist[r][c] + moveCost;

            if (newCost < dist[nr][nc]) {
                dist[nr][nc] = newCost;
                cameFrom.set(`${nr},${nc}`, [{ r, c }, { cost: newCost }]); // Store predecessor and path details
                pq.push({ cost: newCost, r: nr, c: nc });
            }
        }
    }

    return { expandedCount: expandedCount, finalCost: dist[end[0]][end[1]], cameFrom, ran: currentPathCost !== Infinity };
}

// --- A* Algorithm (Uses Priority Queue based on f(n) = g(n) + h(n)) ---
function runAStar() {
    const gScore = Array(GRID_H).fill(0).map(() => Array(GRID_W).fill(Infinity));
    const cameFrom = new Map();
    // Priority Queue stores {f: f_cost, r, c}
    const pq = new PriorityQueue();

    gScore[start[0]][start[1]] = 0;
    pq.push({ cost: 0, r: start[0], c: start[1] });

    let expandedCount = 0;
    let currentPathCost = Infinity;
    stepQueue = [];

    const heuristic = (r, c) => Math.abs(r - end[0]) + Math.abs(c - end[1]); // Manhattan distance

    while (!pq.isEmpty()) {
        const { cost: f_cost, r, c } = pq.pop();

        expandedCount++;
        stepQueue.push({ type: 'expand', r, c, cost: f_cost, state: { visited: [[r, c]], frontier: [] } });

        if (r === end[0] && c === end[1]) {
            currentPathCost = gScore[r][c]; 
            break;
        }
        
        for (const [nr, nc] of getNeighbors(r, c)) {
            const moveCost = grid[nr][nc];
            const tentative_gScore = gScore[r][c] + moveCost;

            if (tentative_gScore < gScore[nr][nc]) {
                gScore[nr][nc] = tentative_gScore;
                cameFrom.set(`${nr},${nc}`, [{ r, c }, { cost: tentative_gScore }]);
                const f_score = tentative_gScore + heuristic(nr, nc);
                pq.push({ cost: f_score, r: nr, c: nc });
            }
        }
    }

    return { expandedCount: expandedCount, finalCost: gScore[end[0]][end[1]], cameFrom, ran: currentPathCost !== Infinity };
}


function animate(ctx, pathFinder) {
    if (stepQueue.length === 0 || !isRunning) return;

    const step = stepQueue.shift();
    let currentState = step.state;
    let r = step.r, c = step.c;

    // Clear canvas and redraw costs
    ctx.clearRect(0, 0, CANVAS_SIZE, CANVAS_SIZE);
    setupVisualization(ctx);

    if (step.type === 'expand') {
        // Draw visited cells (black)
        currentState.visited.forEach(([vr, vc]) => {
            const cell = CANVAS_SIZE / GRID_W;
            ctx.fillStyle = '#333';
            ctx.fillRect(vc * cell, vr * cell, cell - 1, cell - 1);
        });

        // Draw frontier (green)
        currentState.frontier.forEach(([fr, fc]) => {
             const cell = CANVAS_SIZE / GRID_W;
            ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
            ctx.fillRect(fc * cell, fr * cell, cell - 1, cell - 1);
        });

        // Highlight current expanded node (yellow)
        const cell = CANVAS_SIZE / GRID_W;
        ctx.fillStyle = 'rgba(255, 255, 0, 0.8)';
        ctx.fillRect(c * cell, r * cell, cell - 1, cell - 1);
    }

    if (stepQueue.length === 0) {
        // Animation complete for this algorithm
        const results = pathFinder;
        let pathNodes = [];
        if (results.cameFrom && results.ran) {
             // Reconstruct the actual path using the stored sequence data structure
            let temp = [end[0], end[1]]; 
            while (temp[1] !== start[1] || temp[0] !== start[0]) {
                pathNodes.push(temp);
                const key = `${temp[0]},${temp[1]}`;
                if (!results.cameFrom.has(key)) break;
                let nextData = results.cameFrom.get(key);
                temp = [nextData[0][0], nextData[0][1]];
            }
            pathNodes.unshift(start);

            // Draw final path (blue)
            const cell = CANVAS_SIZE / GRID_W;
            ctx.strokeStyle = 'rgba(50, 170, 255, 1)';
            ctx.lineWidth = 3;
            for (let i = 0; i < pathNodes.length - 1; i++) {
                const [r1, c1] = pathNodes[i];
                const [r2, c2] = pathNodes[i+1];
                ctx.beginPath();
                ctx.moveTo(c1 * cell + cell / 2, r1 * cell + cell / 2);
                ctx.lineTo(c2 * cell + cell / 2, r2 * cell + cell / 2);
                ctx.stroke();
            }
        }

        // Final Drawing state: visited cells are marked on the last step of animation
    }


    animationFrameId = requestAnimationFrame(() => animate(ctx, pathFinder));
}

function runAlgorithmCycle(canvasCtx, algorithmFunc) {
    // Reset visualization and queue
    step
MODEL Bqwen3:8bDNF
No usable answer reached the harness (ERR). Counted as a did-not-finish.
MODEL Cgemma4:26bDNF
No usable answer reached the harness (TIMEOUT). Counted as a did-not-finish.
MODEL Dqwen3:14bBLANKLIMFORMAT
Show code
```html
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>Dijkstra vs A*</title></head>
<style>body{display:flex;align-items:center;height:100vh;margin:0;background:#222}canvas{border:1px solid #444;}</style>
<body><canvas id="canvas" width="600" height="400"></canvas><script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

let GRID_W = 30, GRID_H = 20;
let START = {x: 0, y: 0};
let END = {x: GRID_W - 1, y: GRID_H - 1};
let grid = [];

function generateGrid() {
    grid = [];
    for (let i = 0; i < GRID_H; i++) {
        let row = [];
        for (let j = 0; j < GRID_W; j++) {
            row.push({x: j, y: i, cost: Math.floor(Math.random() * 3) + 1});
        }
        grid.push(row);
    }
}

function getNeighbors(r, c) {
    const n = [];
    [[0, 1], [0, -1], [1, 0], [-1, 0]].forEach(([dr, dc]) => {
        const nr = r + dr;
        const nc = c + dc;
        if (nr >= 0 && nr < GRID_H && nc >= 0 && nc < GRID_W) n.push({r: nr, c: nc});
    }); return n;
}

function heuristic(a, b) { return Math.abs(a.x - b.x) + Math.abs(a.y - b.y); }

// Priority Queue implementation (simple array sort/shift for line count efficiency)
class PQ { constructor() { this.items = []; } isEmpty() { return this.items.length === 0; } push(item, priority) { this.items.push({item, priority}); this.items.sort((a, b) => a.priority - b.priority); } pop() { return this.items.shift().item; } }

function solveDijkstra() {
    let dist = Array.from({length: GRID_H}, () => new Array(GRID_W).fill(Infinity));
    let prev = Array.from({length: GRID_H}, () => new Array(GRID_W).fill(null));
    let pq = new PQ();

    dist[START.y][START.x] = 0;
    pq.push({r: START.y, c: START.x}, 0);

    let expandedCount = 0;
    while (!pq.isEmpty()) {
        const {r, c} = pq.pop();
        if (r === END.y && c === END.x) break;

        if (dist[r][c] < Infinity && dist[r][c] > 0) {
            expandedCount++;
        } else if (r !== START.y || c !== START.x) {
             // Only count nodes popped that aren't the start node, and are not already processed
             if (dist[r][c] === Infinity && !(r===START.y&&c===START.x)) continue;
        }


        getNeighbors(r, c).forEach(({r: nr, c: nc}) => {
            const newDist = dist[r][c] + grid[nr][nc].cost;
            if (newDist < dist[nr][nc]) {
                dist[nr][nc] = newDist;
                prev[nr][nc] = {r, c};
                pq.push({r: nr, c: nc}, newDist);
            }
        });
    }

    let path = []; let current = {r: END.y, c: END.x};
    while (current) { path.unshift(current); current = prev[current.r][current.c]); }
    return {path: path, cost: dist[END.y][END.x], expanded: Math.max(1, expandedCount)};
}

function solveAStar() {
    let gScore = Array.from({length: GRID_H}, () => new Array(GRID_W).fill(Infinity)); // Cost from start
    let fScore = Array.from({length: GRID_H}, () => new Array(GRID_W).fill(Infinity)); // Estimated total cost
    let prev = Array.from({length: GRID_H}, () => new Array(GRID_W).fill(null));
    let pq = new PQ();

    gScore[START.y][START.x] = 0;
    fScore[START.y][START.x] = heuristic(START, END);
    pq.push({r: START.y, c: START.x}, fScore[START.y][START.x]);

    let expandedCount = 0;
    while (!pq.isEmpty()) {
        const {r, c} = pq.pop();
        if (r === END.y && c === END.x) break;

        if (gScore[r][c] < Infinity && gScore[r][c] > 0 || (r===START.y&&c===START.x)) {
             expandedCount++;
        }


        getNeighbors(r, c).forEach(({r: nr, c: nc}) => {
            const tentative_gScore = gScore[r][c] + grid[nr][nc].cost;
            if (tentative_gScore < gScore[nr][nc]) {
                prev[nr][nc] = {r, c};
                gScore[nr][nc] = tentative_gScore;
                fScore[nr][nc] = tentative_gScore + heuristic({x: nc, y: nr}, END);
                pq.push({r: nr, c: nc}, fScore[nr][nc]);
            }
        });
    }

    let path = []; let current = {r: END.y, c: END.x};
    while (current) { path.unshift(current); current = prev[current.r][current.c]); }
    return {path: path, cost: gScore[END.y][END.x], expanded: Math.max(1, expandedCount)};
}

let dijkstraState = { dist: Array.from({length: GRID_H}, () => new Array(GRID_W).fill(Infinity)), prev: [], pq: new PQ(), openSet: new Set(), visited: new Set(), currentPath: [] };
let aStarState = { gScore: Array.from({length: GRID_H}, () => new Array(GRID_W).fill(Infinity)), prev: [], pq: new PQ(), openSet: new Set(), visited: new Set(), currentPath: [] };

function initStates() {
    dijkstraState.prev = Array.from({length: GRID_H}, () => new Array(GRID_W).fill(null));
    aStarState.prev = Array.from({length: GRID_H}, () => new Array(GRID_W).fill(null));

    // Initialize Dijkstra state
    dijkstraState.dist[START.y][START.x] = 0;
    dijkstraState.pq = new PQ();
    dijkstraState.pq.push({r: START.y, c: START.x}, 0);

    // Initialize A* state
    aStarState.gScore[START.y][START.x] = 0;
    aStarState.pq = new PQ();
    aStarState.pq.push({r: START.y, c: START.x}, heuristic(START, END));

    dijkstraState.visited.clear();
    aStarState.visited.clear();
}


function drawGrid() {
    const cellSize = 20;
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    for (let i = 0; i < GRID_H; i++) {
        for (let j = 0; j < GRID_W; j++) {
            const x = j * cellSize;
            const y = i * cellSize;
            ctx.fillStyle = `rgb(${15 + grid[i][j].cost * 20}, ${150 - grid[i][j].cost * 10}, ${15 + grid[i][j].cost * 20})`;
            ctx.fillRect(x, y, cellSize, cellSize);
        }
    }
}

function drawState(state, isDijkstra) {
    const ctxToUse = canvas; // Using one context for simplicity, drawing the two halves manually
    const cellSize = 20;
    let offset_x = isDijkstra ? 0 : canvas.width / 2 - (GRID_W * cellSize);

    // Draw background cost map first
    for (let i = 0; i < GRID_H; i++) {
        for (let j = 0; j < GRID_W; j++) {
            const x = j * cellSize + offset_x;
            const y = i * cellSize;
            ctx.fillStyle = `rgb(${15 + grid[i][j].cost * 20}, ${150 - grid[i][j].cost * 10}, ${15 + grid[i][j].cost * 20})`;
            ctx.fillRect(x, y, cellSize, cellSize);
        }
    }

    // Draw visited cells (Darker)
    for (let i = 0; i < GRID_H; i++) {
        for (let j = 0; j < GRID_W; j++) {
            if (state.visited.has(`${i},${j}`)) {
                const x = j * cellSize + offset_x;
                const y = i * cellSize;
                ctx.fillStyle = 'rgba(50, 50, 150, 0.6)';
                ctx.fillRect(x, y, cellSize, cellSize);
            }
        }
    }

    // Draw frontier/open set (Cyan)
    for (let i = 0; i < GRID_H; i++) {
        for (let j = 0; j < GRID_W; j++) {
            if (state.openSet.has(`${i},${j}`)) {
                const x = j * cellSize + offset_x;
                const y = i * cellSize;
                ctx.fillStyle = 'rgba(0, 255, 255, 0.4)';
                ctx.fillRect(x, y, cellSize, cellSize);
            }
        }
    }

    // Draw path (Green)
    for (const pos of state.currentPath) {
        if (!isDijkstra && pos[1] === START.y && pos[0] === START.x) continue; // Skip start node drawing on A* side if it is the start cell
        const x = pos[1] * cellSize + offset_x;
        const y = pos[0] * cellSize;
        ctx.fillStyle = 'rgba(0, 255, 0, 0.8)';
        ctx.fillRect(x, y, cellSize, cellSize);
    }

    // Draw Start/End
    const sX = START.x * cellSize + offset_x;
    const sY = START.y * cellSize;
    ctx.fillStyle = 'red'; ctx.fillRect(sX, sY
MODEL Eqwen3-coder:30bERRBLANKLIMFORMAT
Show code
```html
<!DOCTYPE html>
<html><head><title>Dijkstra vs A*</title></head><style>body{display:flex;justify-content:center;align-items:center;height:100vh;margin:0;background:#333;}#container{display:flex;gap:20px;}canvas{border:1px solid #ccc;background:#fff;}#stats{width:250px;color:#eee;font-family:monospace;}h3{margin-top:0;border-bottom:1px solid #444;}span{display:block;margin-bottom:5px;}</style></head><body><div id="container"><canvas id="canvas" width="600" height="480"></canvas><div id="stats"><h3>Dijkstra</h3><span id="d_exp">Exp: 0</span><span id="d_cost">Cost: N/A</span><h3>A*</h3><span id="a_exp">Exp: 0</span><span id="a_cost">Cost: N/A</span></div></div><script>
const C=document.getElementById('canvas');
const ctx=C.getContext('2d');
const W=30,H=20;
const CELL_W=C.width/W,CELL_H=C.height/H;

let grid=[],start=[1,1],end=[W-2,H-2];
let dijkstraState={cost:Infinity,expanded:0,visited:{},frontier:[{c,p},{c,p}],pathFound:false};
let aStarState={cost:Infinity,expanded:0,visited:{},frontier:[{c,p}],pathFound:false};

function init() {
    grid=[];for(let y=0;y<H;y++)grid[y]=[...Array(W)].map(()=>Math.floor(Math.random()*3)+1);
    dijkstraState={cost:Infinity,expanded:0,visited:{},frontier:[{c:start[0],p:start[1]},{c:end[0],p:end[1]}],pathFound:false};
    aStarState={cost:Infinity,expanded:0,visited:{},frontier:[{c:start[0],p:start[1]},{c:end[0],p:end[1]}],pathFound:false};
}

function draw() {
    ctx.clearRect(0,0,C.width,C.height);
    for(let y=0;y<H;y++)for(let x=0;x<W;x++){
        let color = '#9ccc65'; // Default terrain cost
        if (dijkstraState.visited[x]?dijkstraState.visited[x].y===y && dijkstraState.visited[x].x<=x:false) {
             color='#a2c1ad'; // Visited
        } else if (dijkstraState.frontier.some(f=>f.c===x&&f.p===y)) {
            color='#6aa84f'; // Frontier (Dijkstra)
        } else if (aStarState.visited[x]?aStarState.visited[x].y===y && aStarState.visited[x].x<=x:false) {
             color='#a2c1ad';
        } else if (aStarState.frontier.some(f=>f.c===x&&f.p===y)) {
            color='#6aa84f'; // Frontier (A*)
        }
        ctx.fillStyle = color;
        ctx.fillRect(x*CELL_W, y*CELL_H, CELL_W, CELL_H);

        // Draw Path (Simplification: path is only drawn when successful)
        if (dijkstraState.path && dijkstraState.path[y]===x) ctx.fillStyle='#0982c3';
        else if (aStarState.path && aStarState.path[y]===x) ctx.fillStyle='#cc6600';
        ctx.fillRect(x*CELL_W, y*CELL_H, CELL_W, CELL_H);
    }
    if (dijkstraState.path) {
         for(let y=0;y<H;y++)for(let x=0;x<W;x++){
            if (dijkstraState.path[y]===x) ctx.fillStyle='#0982c3'; // Path color
        }
    }
     if (aStarState.path) {
         for(let y=0;y<H;y++)for(let x=0;x<W;x++){
            if (aStarState.path[y]===x) ctx.fillStyle='#cc6600'; // Path color
        }
    }

    // Labels
    document.getElementById('d_exp').innerText=`Exp: ${dijkstraState.expanded}`;
    document.getElementById('d_cost').innerText=`Cost: ${Math.round(dijkstraState.cost)}`;
    document.getElementById('a_exp').innerText=`Exp: ${aStarState.expanded}`;
    document.getElementById('a_cost').innerText=`Cost: ${Math.round(aStarState.cost)}`;
}

function getNeighbors(x,y) {
    let n = [];
    [[0,1],[-1,1],[1,1],[0,-1],[0,1]].forEach(([dx,dy])=>{
        let nx=x+dx;let ny=y+dy;
        if (nx>=0&&nx<W&&ny>=0&&ny<H)n.push({c:nx,p:ny,cost:grid[ny][nx]});
    });
    return n;
}

function processDijkstra(queue){
    let current={c:-1,p:-1};
    if (queue.length === 0) return false;

    current = queue.shift();
    const {c:cx,p:cy}={c:current.c,p:current.p};

    dijkstraState.visited[cx] = {y:cy,x:cx}; // Mark visited (simple representation)
    dijkstraState.frontier.push({c:cx,p:cy});

    if (cx === end[0] && cy === end[1]) {
        dijkstraState.pathFound = true;
        // Reconstruct path (omitted complexity for line limit, assume path is found)
        return false; 
    }

    let neighbors=getNeighbors(cx,cy);

    for(const n of neighbors){
        if (!dijkstraState.visited[n.c] || (dijkstraState.visited[n.c].y !== n.p || dijkstraState.visited[n.c].x !== n.c)) {
            let newCost = dijkstraState.cost + n.cost; // Simplified cost tracking for animation
             if (!dijkstraState.frontier.some(f=>f.c===n.c&&f.p===n.p)) {
                dijkstraState.frontier.push({c:n.c,p:n.p});
            }
        }
    }
    dijkstraState.expanded++;
    return true;
}

function processAStar(queue){
    let current={c:-1,p:-1};
    if (queue.length === 0) return false;

    current = queue.shift();
    const {c:cx,p:cy}={c:current.c,p:current.p};

    aStarState.visited[cx] = {y:cy,x:cx}; // Mark visited
    aStarState.frontier.push({c:cx,p:cy});

     if (cx === end[0] && cy === end[1]) {
        aStarState.pathFound = true;
        return false; 
    }

    let neighbors=getNeighbors(cx,cy);
    for(const n of neighbors){
         // A* logic requires heuristic and cost updates (simplified for brevity)
    }
    aStarState.expanded++;
    return true;
}


function animate() {
    if (!dijkstraState.pathFound && dijkstraState.frontier.length > 0) {
        let nextD = [...dijkstraState.frontier];
        nextD.sort((a,b)=>1); // Simulate PQ extraction (simplification)
        processDijkstra(nextD);
    } else if (!dijkstraState.pathFound && dijkstraState.expanded > 50){
        // Force completion state for visualization when stuck in animation loop steps
        dijkstraState.cost=20; 
        dijkstraState.path = Array(H).fill(null); djkstraState.path[1][1]=1; dijkstraState.path[H-2][W-2]=1;
    }

     if (!aStarState.pathFound && aStarState.frontier.length > 0) {
        let nextA = [...aStarState.frontier];
        nextA.sort((a,b)=>1); // Simulate PQ extraction (simplification)
        processAStar(nextA);
    } else if (!aStarState.pathFound && aStarState.expanded > 50){
         dijkstraState.cost=20; 
         aStarState.cost = 20;
         aStarState.path = Array(H).fill(null); aStarState.path[1][1]=1; aStarState.path[H-2][W-2]=1;
    }


    draw();

    if (!dijkstraState.pathFound && !aStarState.pathFound) {
        setTimeout(()=>requestAnimationFrame(animate), 50);
    } else {
        // Loop restart on completion/stalling
        setTimeout(()=>{init();requestAnimationFrame(animate);},1500);
    }
}

init();
requestAnimationFrame(animate);
</script></body></html>
```
MODEL Fllama3.1:8bERRBLANKLIMFORMAT
Show code
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Dijkstra & A* Comparison</title>
<style>
  canvas {
    border: 1px solid black;
  }
  #dijkstra-panel, #a-star-panel {
    float: left;
    width: 49%;
    height: 500px;
  }
  .visited {
    fill: blue;
  }
  .frontier {
    fill: yellow;
  }
</style>
</head>
<body>
<canvas id="grid" width="980"></canvas>
<script>
  const grid = document.getElementById('grid');
  const ctx1 = grid.getContext('2d');
  const ctx2 = grid.getContext('2d', {offsetWidth: 490, offsetHeight: 500});
  let gridData = [];
  for (let i = 0; i < 30; i++) {
    gridData.push([]);
    for (let j = 0; j < 20; j++) {
      gridData[i].push(Math.random());
    }
  }
  const dijkstraExpanded = (count) => document.getElementById('dijkstra-expanded').textContent = `Dijkstra Expanded: ${count}`;
  const aStarExpanded = (count) => document.getElementById('a-star-expanded').textContent = `A* Expanded: ${count}`;
  let dijkstraCount = 0;
  let aStarCount = 0;
  let pathFound = false;
  function drawGrid() {
    ctx1.clearRect(0, 0, grid.width, grid.height);
    ctx2.clearRect(0, 0, grid.width, grid.height);
    const scale = 20 / Math.min(grid.width, grid.height);
    for (let i = 0; i < 30; i++) {
      for (let j = 0; j < 20; j++) {
        const cellX = j * scale;
        const cellY = i * scale;
        const terrainCost = gridData[i][j];
        ctx1.fillStyle = 'rgba(255, 128, 0, 0.5)'; // terrain cost
        ctx1.fillRect(cellX, cellY, scale, scale);
        if (pathFound && path[i][j] === 1) {
          ctx2.strokeStyle = 'black';
          ctx2.lineWidth = 2;
          ctx2.beginPath();
          ctx2.moveTo((j - path[0][j]) * scale + cellX, (i - path[0][i]) * scale + cellY);
          for (let k = 1; k < 20 * 30; k++) {
            const pI = Math.floor(k / 20);
            const pJ = k % 20;
            ctx2.lineTo((pJ - path[pI][pJ]) * scale + cellX, (pI - path[pI][pI]) * scale + cellY);
          }
          ctx2.stroke();
        }
      }
    }
  }
  function dijkstra() {
    const start = [0, 0];
    const end = [29, 19];
    const distances = Array(30).fill().map(() => Array(20).fill(Infinity));
    const cameFrom = Array(30).fill().map(() => Array(20).fill(null));
    const priorityQueue = [];
    let dijkstraCount = 0;
    distances[0][0] = gridData[0][0];
    priorityQueue.push([gridData[0][0], start]);
    while (priorityQueue.length > 0) {
      let [currentDistance, currentNode] = priorityQueue.shift();
      if (dijkstraCount !== dijkstraExpanded(dijkstraCount)) return;
      for (let i = -1; i <= 1; i++) {
        for (let j = -1; j <= 1; j++) {
          const neighborX = currentNode[0] + i;
          const neighborY = currentNode[1] + j;
          if (neighborX >= 0 && neighborX < 30 && neighborY >= 0 && neighborY < 20) {
            const newDistance = currentDistance + gridData[neighborX][neighborY];
            if (newDistance < distances[neighborX][neighborY]) {
              distances[neighborX][neighborY] = newDistance;
              cameFrom[neighborX][neighborY] = currentNode;
              priorityQueue.push([newDistance, [neighborX, neighborY]]);
              dijkstraCount++;
            }
          }
        }
      }
    }
    const shortestPath = [];
    let currentNode = end;
    while (currentNode) {
      shortestPath.unshift(currentNode);
      currentNode = cameFrom[currentNode[0]][currentNode[1]];
    }
    pathFound = true;
    return shortestPath;
  }
  function aStar() {
    const start = [0, 0];
    const end = [29, 19];
    const distances = Array(30).fill().map(() => Array(20).fill(Infinity));
    const cameFrom = Array(30).fill().map(() => Array(20).fill(null));
    const priorityQueue = [];
    let aStarCount = 0;
    distances[0][0] = gridData[0][0];
    priorityQueue.push([gridData[0][0], start]);
    while (priorityQueue.length > 0) {
      let [currentDistance, currentNode] = priorityQueue.shift();
      if (aStarCount !== aStarExpanded(aStarCount)) return;
      for (let i = -1; i <= 1; i++) {
        for (let j = -1; j <= 1; j++) {
          const neighborX = currentNode[0] + i;
          const neighborY = currentNode[1] + j;
          if (neighborX >= 0 && neighborX < 30 && neighborY >= 0 && neighborY < 20) {
            const heuristic = Math.abs(neighborX - end[0]) + Math.abs(neighborY - end[1]);
            const newDistance = currentDistance + gridData[neighborX][neighborY] + heuristic;
            if (newDistance < distances[neighborX][neighborY]) {
              distances[neighborX][neighborY] = newDistance;
              cameFrom[neighborX][neighborY] = currentNode;
              priorityQueue.push([newDistance, [neighborX, neighborY]]);
              aStarCount++;
            }
          }
        }
      }
    }
    const shortestPath = [];
    let currentNode = end;
    while (currentNode) {
      shortestPath.unshift(currentNode);
      currentNode = cameFrom[currentNode[0]][currentNode[1]];
    }
    pathFound = true;
    return shortestPath;
  }
  function drawStep(path, color) {
    ctx2.fillStyle = color;
    for (let i = 0; i < path.length; i++) {
      const x = path[i][1] * scale + cellX;
      const y = path[i][0] * scale + cellY;
      ctx2.fillRect(x, y, scale, scale);
    }
  }
  function drawVisited(color) {
    for (let i = 0; i < 30; i++) {
      for (let j = 0; j < 20; j++) {
        const x = j * scale;
        const y = i * scale;
        ctx1.fillStyle = color;
        ctx1.fillRect(x, y, scale, scale);
      }
    }
  }
  function drawFrontier(color) {
    for (let i = 0; i < 30; i++) {
      for (let j = 0; j < 20; j++) {
        const x = j * scale;
        const y = i * scale;
        ctx2.fillStyle = color;
        ctx2.fillRect(x, y, scale, scale);
      }
    }
  }
  let path = [];
  drawGrid();
  function animation() {
    if (dijkstraCount < dijkstraExpanded(dijkstraCount)) {
      dijkstra();
    }
    if (aStarCount < aStarExpanded(aStarCount)) {
      aStar();
    }
    if (!pathFound) return requestAnimationFrame(animation);
    const shortestPath = dijkstra();
    const aStarPath = aStar();
    path = shortestPath;
    for (let i = 0; i < 30; i++) {
      for (let j = 0; j < 20; j++) {
        const x = j * scale + cellX;
        const y = i * scale + cellY;
        if (path[i][j] === 1) {
          ctx2.fillStyle = 'black';
          ctx2.fillRect(x, y, scale, scale);
        }
      }
    }
    drawStep(path, 'red');
    let currentNode = path[0];
    while (currentNode) {
      const neighborX = currentNode[0];
      const neighborY = currentNode[1];
      if (neighborX >= 0 && neighborX < 30 && neighborY >= 0 && neighborY < 20) {
        ctx2.fillStyle = 'black';
        ctx2.fillRect(neighborY * scale + cellX, neighborX * scale + cellY, scale, scale);
      }
      currentNode = cameFrom[neighborX][neighborY];
    }
    drawVisited('blue');
    for (let i = 0; i < path.length - 1; i++) {
      const point1 = path[i];
      const point2 = path[i + 1];
      ctx2.strokeStyle = 'black';
      ctx2.lineWidth = 3;
      ctx2.beginPath();
      ctx2.moveTo((point1[1] - point1[0]) * scale + cellX, (point1[0] - point1[1]) * scale + cellY);
      ctx2.lineTo((point2[1] - point2[0]) * scale + cellX, (point2[0] - point2[1]) * scale + cellY);
      ctx2.stroke();
    }
    document.getElementById('cost').textContent = `Path Cost: ${distances[29][19]}`
    requestAnimationFrame(animation);
  };
  animation();
  for (let i = 0; i < 30; i++) {
    gridData[i].push(...gridData[i]);
  }
  for (let j = 0; j < 20 * 2; j++) {
    const row = [...gridData[j % 30]];
    gridData.push(row);
  }
  drawGrid();
</script>
<canvas id="dijkstra-panel" width="490"></canvas>
<div id="stats">
  <div id="cost">Path Cost: ?</div>
  <div id="dijkstra-expanded">Dijkstra Expanded: 0</div>
  <div id="a-star-expanded">A* Expanded: 0</div>
</div>
<canvas id="a-star-panel" width="490"></canvas>
```
MODEL Gdeepseek-r1:14bDNF
No usable answer reached the harness (TIMEOUT). Counted as a did-not-finish.
MODEL Hmistral-small:24bSTATFORMAT
Show code
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Dijkstra vs A*</title>
<style>
body { display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background-color: #f0f0f0; }
canvas { border: 1px solid black; }
#info { position: absolute; top: 10px; left: 10px; color: white; font-family: Arial, sans-serif; }
</style>
</head>
<body>
<canvas id="canvas" width="640" height="480"></canvas>
<div id="info"></div>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const cellSize = 10;
const rows = 30;
const cols = 20;
const terrainCosts = Array.from({ length: rows }, () => Array(cols).fill(0));
const dijkstraFrontier = [];
const aStarFrontier = [];
let dijkstraVisited = new Set();
let aStarVisited = new Set();
let dijkstraPath = [];
let aStarPath = [];
let dijkstraExpanded = 0;
let aStarExpanded = 0;

function getRandomCost() {
    return Math.floor(Math.random() * 10) + 5;
}

function drawTerrain() {
    for (let r = 0; r < rows; r++) {
        for (let c = 0; c < cols; c++) {
            terrainCosts[r][c] = getRandomCost();
            ctx.fillStyle = `rgb(${terrainCosts[r][c]}, ${255 - terrainCosts[r][c]}, 100)`;
            ctx.fillRect(c * cellSize, r * cellSize, cellSize, cellSize);
        }
    }
}

function drawFrontier(frontier) {
    ctx.strokeStyle = 'yellow';
    frontier.forEach(cell => {
        ctx.strokeRect(cell[1] * cellSize, cell[0] * cellSize, cellSize, cellSize);
    });
}

function djkstraStep() {
    if (dijkstraFrontier.length === 0) return;
    const [r, c] = dijkstraFrontier.shift();
    ctx.fillStyle = 'blue';
    ctx.fillRect(c * cellSize, r * cellSize, cellSize, cellSize);
    dijkstraVisited.add(`${r},${c}`);
    dijkstraExpanded++;

}

function aStarStep() {
    if (aStarFrontier.length === 0) return;
    const [r, c] = aStarFrontier.shift();
    ctx.fillStyle = 'red';
    ctx.fillRect(c * cellSize, r * cellSize, cellSize, cellSize);
    aStarVisited.add(`${r},${c}`);
    aStarExpanded++;
}

function drawPath(path, color) {
    path.forEach(cell => {
        const [r, c] = cell;
        ctx.strokeStyle = color;
        ctx.strokeRect(c * cellSize, r * cellSize, cellSize, cellSize);
    });
}

function animate() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    drawTerrain();
    drawFrontier(dijkstraFrontier);
    drawFrontier(aStarFrontier);

    djkstraStep();
    aStarStep();

    document.getElementById('info').innerHTML = `Dijkstra Expanded: ${dijkstraExpanded} <br> A* Expanded: ${aStarExpanded}`;
}

function init() {
    dijkstraFrontier.push([0, 0]);
    aStarFrontier.push([0, 0]);

    requestAnimationFrame(animate);
}

init();

</script>
</body>
</html>
```
Reveal the models— compare the answers first, then open. Names, blind scores and latencies are hidden until you do.

Who wrote what

Blind labelModelBlind scoreLatencyStatus
MODEL A qwen3.5:9b 38.4 sOK
MODEL B qwen3:8b DNF
MODEL C gemma4:26b DNF
MODEL D qwen3:14b 38.4 sOK
MODEL E qwen3-coder:30b 35.8 sOK
MODEL F llama3.1:8b 21.9 sOK
MODEL G deepseek-r1:14b DNF
MODEL H mistral-small:24b 110.0 sOK

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.

Collected differently from the blind field: the local models run through a plain API harness, the frontier references through a context-free agent, one shot, no retries. Response times are therefore not comparable and are not shown. On two English tasks the reference answer came back in German — an artefact of that harness, flagged on the affected rounds.
Claude Opus 5frontier reference
Show code
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Dijkstra vs A* on the same weighted grid</title>
<style>
html,body{margin:0;height:100%;background:#0b0f16;color:#e6edf3;display:flex;align-items:center;justify-content:center;
font:13px/1.4 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
canvas{background:#141b25;border-radius:12px;box-shadow:0 18px 60px #000a;max-width:98vw;height:auto}
</style>
</head>
<body>
<canvas id="c"></canvas>
<script>
const W=30,H=20,CS=18,N=W*H,PAD=16,TOP=48,PW=W*CS,PH=H*CS,S=0,G=N-1;
const c=document.getElementById('c'),x=c.getContext('2d');
c.width=PAD*3+PW*2;c.height=TOP+PH+PAD+26;
let cost,gmin,A,B,hold=0;
function gen(){
  let f=new Float64Array(N);
  for(let i=0;i<N;i++)f[i]=Math.random();
  for(let p=0;p<2;p++){const g=new Float64Array(N);
    for(let y=0;y<H;y++)for(let X=0;X<W;X++){let s=0,n=0;
      for(let dy=-1;dy<=1;dy++)for(let dx=-1;dx<=1;dx++){const a=X+dx,b=y+dy;
        if(a<0||b<0||a>=W||b>=H)continue;s+=f[b*W+a];n++}
      g[y*W+X]=s/n}
    f=g}
  let mn=1e9,mx=-1e9;for(const v of f){if(v<mn)mn=v;if(v>mx)mx=v}
  cost=new Int32Array(N);
  for(let i=0;i<N;i++)cost[i]=1+Math.round(Math.pow((f[i]-mn)/(mx-mn||1),1.35)*8);
  cost[S]=1;cost[G]=1;gmin=9;for(const v of cost)if(v<gmin)gmin=v;
}
function mk(useH){
  const st={dist:new Float64Array(N).fill(1e18),prev:new Int32Array(N).fill(-1),
    done:new Uint8Array(N),inOpen:new Uint8Array(N),open:[S],exp:0,path:null,fin:false,useH:useH};
  st.dist[S]=0;st.inOpen[S]=1;return st;
}
function hh(n){return (Math.abs(n%W-G%W)+Math.abs((n/W|0)-(G/W|0)))*gmin}
function trace(st){const p=[];let u=G;while(u>=0){p.push(u);u=st.prev[u]}return p.reverse()}
function step(st){
  if(st.fin)return;
  if(!st.open.length){st.fin=true;return}
  let bi=0,bf=1e18;
  for(let i=0;i<st.open.length;i++){const n=st.open[i],f=st.dist[n]+(st.useH?hh(n):0);
    if(f<bf){bf=f;bi=i}}
  const u=st.open[bi];st.open.splice(bi,1);st.inOpen[u]=0;
  if(st.done[u])return;
  st.done[u]=1;st.exp++;
  if(u===G){st.fin=true;st.path=trace(st);return}
  const ux=u%W,uy=u/W|0;
  const nb=[[1,0],[-1,0],[0,1],[0,-1]];
  for(const d of nb){const a=ux+d[0],b=uy+d[1];
    if(a<0||b<0||a>=W||b>=H)continue;
    const v=b*W+a,nd=st.dist[u]+cost[v];
    if(nd<st.dist[v]-1e-9){st.dist[v]=nd;st.prev[v]=u;
      if(!st.done[v]&&!st.inOpen[v]){st.inOpen[v]=1;st.open.push(v)}}}
}
function cell(i){return[(i%W)*CS,(i/W|0)*CS]}
function panel(ox,st,title){
  for(let i=0;i<N;i++){const p=cell(i),px=ox+p[0],py=TOP+p[1],v=cost[i];
    x.fillStyle='hsl('+(142-v*9)+','+(24+v*3)+'%,'+(80-v*6.6)+'%)';
    x.fillRect(px,py,CS-1,CS-1);
    if(st.done[i]){x.fillStyle='rgba(56,139,253,.46)';x.fillRect(px,py,CS-1,CS-1)}
    else if(st.inOpen[i]){x.fillStyle='rgba(255,193,58,.82)';x.fillRect(px,py,CS-1,CS-1)}}
  if(st.path){
    x.lineJoin='round';x.lineCap='round';x.beginPath();
    for(let k=0;k<st.path.length;k++){const p=cell(st.path[k]);
      const px=ox+p[0]+CS/2-.5,py=TOP+p[1]+CS/2-.5;k?x.lineTo(px,py):x.moveTo(px,py)}
    x.strokeStyle='#ff4f6d';x.lineWidth=5;x.stroke();
    x.strokeStyle='rgba(255,255,255,.9)';x.lineWidth=1.6;x.stroke()}
  for(const m of [[S,'#22e08a'],[G,'#ff2f6a']]){const p=cell(m[0]);
    x.fillStyle=m[1];x.fillRect(ox+p[0],TOP+p[1],CS-1,CS-1);
    x.strokeStyle='#fff';x.lineWidth=1.5;x.strokeRect(ox+p[0]+.75,TOP+p[1]+.75,CS-2.5,CS-2.5)}
  x.strokeStyle='rgba(255,255,255,.12)';x.lineWidth=1;
  x.strokeRect(ox-.5,TOP-.5,PW,PH);
  x.fillStyle='#e6edf3';x.font='bold 15px ui-monospace,monospace';x.fillText(title,ox,20);
  x.font='12px ui-monospace,monospace';x.fillStyle='#8fa3b8';
  x.fillText('expanded '+st.exp+'   ·   path cost '+(st.path?st.dist[G]:'…')+
    (st.fin&&!st.path?'  (no path)':''),ox,38);
}
function draw(){
  x.clearRect(0,0,c.width,c.height);
  panel(PAD,A,'Dijkstra');
  panel(PAD*2+PW,B,'A*  (Manhattan × '+gmin+')');
  const y=TOP+PH+19;
  const key=[['#5aa0f5','visited'],['#ffc13a','frontier'],['#ff4f6d','shortest path']];
  let kx=PAD;x.font='12px ui-monospace,monospace';
  for(const k of key){x.fillStyle=k[0];x.fillRect(kx,y-9,10,10);
    x.fillStyle='#8fa3b8';x.fillText(k[1],kx+15,y);kx+=25+x.measureText(k[1]).width}
  const same=A.path&&B.path&&Math.abs(A.dist[G]-B.dist[G])<1e-9;
  x.fillStyle=same?'#22e08a':'#8fa3b8';
  const msg=same?'identical cost '+A.dist[G]+'  ·  A* expanded '+(A.exp-B.exp)+' fewer cells ('+
    Math.round(100-B.exp/A.exp*100)+'% less work)':'searching the same random terrain (cost 1–9)…';
  x.fillText(msg,c.width-PAD-x.measureText(msg).width,y);
}
function frame(){
  requestAnimationFrame(frame);
  if(hold>0){if(--hold===0){gen();A=mk(0);B=mk(1)}}
  else{for(let k=0;k<7;k++){step(A);step(B)}
    if(A.fin&&B.fin)hold=120}
  draw();
}
gen();A=mk(0);B=mk(1);requestAnimationFrame(frame);
</script>
</body>
</html>