OverviewCode › R152
Code · blind round

R152 · Hash table with visible collision chains

blind round 9/11 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 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.

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 animates a hash table on a <canvas>: draw exactly 12 buckets side by side as vertical slots, continuously generate random integer keys, hash each one with a simple deterministic function (e.g. modulo 12) and drop it into its bucket, appending it to a visibly growing vertical chain of small labelled boxes linked by short connecting lines whenever a collision occurs (the bucket already holds one or more keys), so buckets that collide more often visibly grow longer chains than others. Colour each bucket by its current fill level (e.g. green for empty/low, yellow for a few keys, red for a long collision chain), and once enough keys have been inserted (roughly 40-60), clear all buckets and start over with a fresh random sequence. Show the current load factor (total keys inserted divided by 12). 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 (ERR) — 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.
llama3.1:8bBLANKFORMAT
Show code
```html
<!DOCTYPE html>
<html>
<head>
<title>Hash Table Animation</title>
<style>
body {
  margin: 0;
}
canvas {
  border: 1px solid black;
}
</style>
</head>
<body>
<canvas id="canvas" width="600" height="400"></canvas>

<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

const cols = 12;
let keys = new Array(cols);
for (let i = 0; i < cols; i++) {
  keys[i] = [];
}
let totalKeys = 0;

function hash(key) {
  return key % cols;
}

function draw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  const w = canvas.width / cols;
  for (let i = 0; i < cols; i++) {
    ctx.fillStyle = 'lightgray';
    ctx.fillRect(i * w, 20, w, 30);
    ctx.fillStyle = 'black';
    ctx.font = '16px Arial';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'top';
    ctx.fillText('Bucket ' + (i + 1), i * w + w / 2, 25);

    const klen = keys[i].length;
    let color = '';
    if (klen < 3) {
      color = 'green';
    } else if (klen < 10) {
      color = 'yellow';
    } else {
      color = 'red';
    }
    ctx.fillStyle = color;

    for (let j = 0; j < klen; j++) {
      const x = i * w + w / 2;
      const y = 50 + j * 20;
      ctx.fillRect(x - 5, y - 10, 10, 20);
      ctx.fillStyle = 'black';
      ctx.textAlign = 'center';
      ctx.fillText(keys[i][j], x, y - 10);

      if (j < klen - 1) {
        const px = i * w + w / 2;
        const py = 50 + j * 20 + 10;
        const qx = i * w + w / 2;
        const qy = 50 + (j + 1) * 20 - 10;
        ctx.beginPath();
        ctx.moveTo(px, py);
        ctx.lineTo(qx, qy);
        ctx.strokeStyle = 'black';
        ctx.lineWidth = 1;
        ctx.stroke();
      }
    }

    ctx.fillStyle = color;
    ctx.fillRect(i * w + w / 2 - 5, keychainY[i] + 50 + keys[i].length * 20 + 10, 10, 20);
  }

  ctx.fillStyle = 'black';
  ctx.font = '16px Arial';
  ctx.textAlign = 'left';
  ctx.textBaseline = 'top';
  ctx.fillText('Load factor: ' + (totalKeys / cols).toFixed(2), 0, 0);

  totalKeys++;
  if (totalKeys > cols * 60) {
    keys = new Array(cols);
    for (let i = 0; i < cols; i++) {
      keys[i] = [];
    }
    totalKeys = 0;
  }

  keychainY = new Array(cols);
  for (let i = 0; i < cols; i++) {
    const klen = keys[i].length;
    let yy = 50 + klen * 20 - 10;
    if (!keychainY[i]) {
      keychainY[i] = yy;
    } else {
      yy += Math.random() * 5 - 2.5;
      if (yy < 0) yy = 0;
      if (yy > canvas.height - 50) yy = canvas.height - 50;
      keychainY[i] = yy;
    }
  }

  requestAnimationFrame(draw);
}

let keychainY;

canvas.addEventListener('load', draw);

const randomKeys = [];
for (let i = 0; i < cols * 60 + 10; i++) {
  randomKeys.push(Math.floor(Math.random() * 100000) + 1);
}
</script>
</body>
</html>
```
qwen3-coder:30bERRBLANKFORMAT
Show code
```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hash Table Animation</title>
    <style>
        body { background: #111; display: flex; justify-content: center; align-items: center; margin: 0; height: 100vh; }
        canvas { border: 2px solid #444; background: #222; }
    </style>
</head>
<body>
    <canvas id="hashCanvas" width="800" height="600"></canvas>

    <script>
        const canvas = document.getElementById('hashCanvas');
        const ctx = canvas.getContext('2d');

        const NUM_BUCKETS = 12;
        const BUCKET_W = (canvas.width - 50 * NUM_BUCKETS) / NUM_BUCKETS;
        const SPACING = 40;
        const KEY_BOX_H = 20;
        const MAX_CHAIN_HEIGHT = 300;

        let buckets = Array(NUM_BUCKETS).fill(null).map(() => []);
        let totalKeys = 0;
        let isRunning = true;

        function getBucketX(index) {
            return (index * (BUCKET_W + SPACING)) + 25;
        }

        function getColor(count) {
            if (count === 0) return '#4CAF50'; // Green (Low/Empty)
            if (count < 3) return '#FFEB3B';  // Yellow (Few keys)
            return '#F44336';                  // Red (High collision chain)
        }

        function draw() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.font = '12px Arial';
            ctx.fillStyle = '#AAA';

            let loadFactorText = `Load Factor: ${totalKeys / NUM_BUCKETS || 0).toFixed(2)} / 12`;
            ctx.fillText(loadFactorText, 50, 30);

            for (let i = 0; i < NUM_BUCKETS; i++) {
                const keys = buckets[i];
                const x = getBucketX(i);
                const color = getColor(keys.length);

                // Draw bucket slot background
                ctx.fillStyle = '#333';
                ctx.fillRect(x, 0, BUCKET_W, canvas.height);
                ctx.strokeStyle = '#555';
                ctx.strokeRect(x, 0, BUCKET_W, canvas.height);

                // Draw chain/keys
                let yOffset = canvas.height - 20;
                const startY = Math.min(yOffset - (keys.length * KEY_BOX_H), MAX_CHAIN_HEIGHT / 2);

                for (let j = keys.length - 1; j >= 0; j--) {
                    const key = keys[j];
                    const y = startY + (j * (KEY_BOX_H + 5)); // Stacked vertically
                    
                    // Draw connection line (prev key to current key)
                    if (j < keys.length - 1) {
                        ctx.beginPath();
                        ctx.moveTo(x + BUCKET_W / 2, startY + (j + 1) * KEY_BOX_H);
                        ctx.lineTo(x + BUCKET_W / 2, startY + j * KEY_BOX_H);
                        ctx.strokeStyle = '#666';
                        ctx.lineWidth = 2;
                        ctx.stroke();
                    }

                    // Draw key box and number
                    ctx.fillStyle = color;
                    ctx.fillRect(x + 5, y - 10, BUCKET_W - 10, KEY_BOX_H);
                    ctx.strokeStyle = '#444';
                    ctx.lineWidth = 1;
                    ctx.strokeRect(x + 5, y - 10, BUCKET_W - 10, KEY_BOX_H);

                    ctx.fillStyle = '#FFF';
                    ctx.textAlign = 'center';
                    ctx.fillText(key, x + BUCKET_W / 2, y + 5);
                }
            }
        }

        function insertKey() {
            const key = Math.floor(Math.random() * 900) + 1; // Random key 1-999
            const index = key % NUM_BUCKETS;

            buckets[index].push(key);
            totalKeys++;
        }

        function resetSimulation() {
            alert("Simulation Finished! Resetting...");
            buckets = Array(NUM_BUCKETS).fill(null).map(() => []);
            totalKeys = 0;
            isRunning = true;
        }

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

            draw();
            
            // Insert a key every frame for continuous animation
            insertKey();

            if (totalKeys >= 50) { // Reset condition threshold
                resetSimulation();
            }

            requestAnimationFrame(animate);
        }

        animate();
    </script>
</body>
</html>
```
qwen3.5:9bSTATFORMAT
Show code
```html
<!DOCTYPE html>
<html>
<head><title>Hash Table Simulation</title></head>
<body><canvas id="c"></canvas><script>const c = document.getElementById('c');const ctx = c.getContext('2d');c.width=800;c.height=450;const NUM_BUCKETS=12;let buckets=[];let totalKeys=0;let animationRunning=true;let lastKey=null;

function initBuckets() {
    buckets = Array(NUM_BUCKETS).fill(null).map(() => []);
    totalKeys = 0;
}

function hash(key) {
    return key % NUM_BUCKETS;
}

function updateLoadFactor() {
    const loadFactor = totalKeys / NUM_BUCKETS;
    ctx.fillStyle = `rgba(0,0,0,0.7)`;
    ctx.fillRect(10, 10, 200, 30);
    ctx.fillStyle='#fff';
    ctx.font='14px monospace';
    ctx.fillText(`Load Factor: ${loadFactor.toFixed(2)}`, 20, 25);
}

function drawBucketColor(bucket) {
    if (bucket.length === 0) return 'rgba(144, 238, 144, 0.6)'; // Light Green
    if (bucket.length < 3) return 'rgba(255, 255, 0, 0.6)';   // Yellow
    return 'rgba(255, 99, 71, 0.6)'; // Reddish Orange
}

function draw() {
    ctx.clearRect(0, 0, c.width, c.height);
    updateLoadFactor();

    const bucketWidth = (c.width - 40) / NUM_BUCKETS;
    const startX = 20;
    const baseY = 50;
    const boxHeight = 25;
    const paddingY = 10;

    buckets.forEach((bucket, i) => {
        const x = startX + i * (bucketWidth + 5);
        ctx.fillStyle = drawBucketColor(bucket);
        ctx.fillRect(x, 0, bucketWidth, c.height - 40);
        ctx.strokeStyle = '#333';
        ctx.strokeRect(x, 0, bucketWidth, c.height - 40);

        let currentY = c.height - 40;
        const keysInBucket = bucket.length;
        
        // Draw the chain/boxes
        bucket.forEach((key, j) => {
            const boxX = x + 5;
            const boxY = currentY - (j * (boxHeight + paddingY));

            ctx.fillStyle = '#3498db'; // Blue boxes
            ctx.fillRect(boxX, boxY, bucketWidth - 10, boxHeight);
            ctx.strokeStyle = '#2980b9';
            ctx.strokeRect(boxX, boxY, bucketWidth - 10, boxHeight);

            // Label key
            ctx.fillStyle = '#fff';
            ctx.font = '14px monospace';
            ctx.fillText(key, boxX + 5, boxY + 20);
        });
    });
}

function insertKey(key) {
    const index = hash(key);
    if (!buckets[index]) buckets[index] = [];
    
    // Check for collision (always happens if length > 0) and append
    buckets[index].push(key);
    totalKeys++;
}

function runSimulationStep() {
    if (!animationRunning && totalKeys >= 50) {
        initBuckets();
        console.log("Restarting simulation.");
    }

    // Generate random key (1 to 99)
    const newKey = Math.floor(Math.random() * 98) + 1;
    
    if (!lastKey || lastKey !== newKey) {
        insertKey(newKey);
        lastKey = newKey;
    }

    draw();

    // Termination condition: Insert roughly 40 to 60 keys.
    if (totalKeys < 5 && !animationRunning) return; // Initial state only runs until first step
    if (totalKeys >= 50) {
        animationRunning = false;
    }

    requestAnimationFrame(runSimulationStep);
}

initBuckets();
requestAnimationFrame(runSimulationStep);
</script></body></html>
```
deepseek-r1:14bOKFORMAT
Show code
```html
<!DOCTYPE html>
<html><body style="margin:0;display:flex;justify-content:center;align-items:center;height:100vh;background:#f0f0f0;">
<canvas id="c"></canvas>
<div id="lf" style="position:absolute;top:20;left:20;font-family:'Arial';font-size:14px;"></div>
<script>
const canvas = document.getElementById('c');
const ctx = canvas.getContext('2d');
const lfElement = document.getElementById('lf');

canvas.width = 800;
canvas.height = 600;

let buckets = Array.from({length:12},()=>({
  height:0,
  color:'green',
  keys:[]
}));

let totalKeys =0;
let keyCount=0;
let needsReset=false;

function drawBucket(x, bucket){
  ctx.strokeStyle = 'black';
  ctx.lineWidth =3;
  ctx.strokeRect(x-4,bucket.height/2,8,canvas.height/3);
}

function drawKey(bucket, i){
  const y = canvas.height/3 + (bucket.keys.length -1 -i)*15;
  const x = bucket.x;
  ctx.fillStyle='white';
  ctx.fillRect(x-4,y+4,16,12);
  ctx.fillStyle='black';
  ctx.font='8px Arial';
  ctx.fillText(bucket.keys[i],x, y + 9);
}

function drawConnections(bucket){
  for(let i=0;i<bucket.keys.length-1;i++){
    const y1 = canvas.height/3 + (bucket.keys.length -1 -i)*15;
    const y2 = y1 +15;
    ctx.beginPath();
    ctx.moveTo(bucket.x, y1+6);
    ctx.lineTo(bucket.x, y2+6);
    ctx.stroke();
  }
}

function animate(){
  if(needsReset){
    buckets.forEach(b=>{b.height=0;b.color='green';b.keys=[]});
    totalKeys=0;
    needsReset=false;
  }

  ctx.fillStyle = 'white';
  ctx.fillRect(0,0,canvas.width,canvas.height);

  for(let i=0;i<12;i++){
    const x = (i+1)*80 -40;
    const bucket = buckets[i];
    bucket.x = x;

    drawBucket(i, bucket);
    if(bucket.keys.length>0){
      ctx.fillStyle = bucket.color;
      ctx.fillRect(x-4,bucket.height/2,8,bucket.height);
      for(let i=0;i<bucket.keys.length;i++)drawKey(bucket,i);
      drawConnections(bucket);
    }
  }

  const loadFactor = totalKeys /12;
  lfElement.textContent = `Load Factor: ${loadFactor.toFixed(3)}`;

  if(totalKeys>40){
    needsReset=true;
    totalKeys=0;
  }

  requestAnimationFrame(animate);
}

let keys = [];
function generateKey() {
  return Math.floor(Math.random()*12);
}

animate();

</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:14bSTATFORMAT
Show code
```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hash Table Animation</title>
    <style>
        body { background: #111; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; }
        canvas { border: 1px solid #333; background: #222; }
    </style>
</head>
<body>
    <canvas id="hashCanvas" width="800" height="450"></canvas>

    <script>
        const canvas = document.getElementById('hashCanvas');
        const ctx = canvas.getContext('2d');
        
        let buckets = [];
        let keysCount = 0;
        let animationRunning = true;
        const NUM_BUCKETS = 12;
        const BUCKET_W = (canvas.width - 40) / NUM_BUCKETS;
        const Y_START = 30;

        // State management and initial setup
        function init() {
            buckets = Array(NUM_BUCKETS).fill(null).map(() => []);
            keysCount = 0;
            animationRunning = true;
            draw();
        }

        // Hashing function (simple modulo)
        function hash(key) {
            return key % NUM_BUCKETS;
        }

        // Determines the color based on current load/chain length
        function getColor(bucketIndex) {
            const count = buckets[bucketIndex].length;
            if (count === 0) return '#4CAF50'; // Green (Low)
            if (count < 3) return '#FFC107'; // Yellow (Medium)
            return '#F44336'; // Red (High/Collision)
        }

        // Inserts a key into the table structure
        function insertKey(key) {
            const index = hash(key);
            buckets[index].push({ k: key, y: Y_START + buckets[index].length * 25 });
            keysCount++;
        }

        // Drawing function
        function draw() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.fillStyle = '#333';
            ctx.fillRect(10, 10, canvas.width - 20, canvas.height - 20);

            const loadFactor = keysCount / NUM_BUCKETS;
            ctx.font = '16px Arial';
            ctx.fillStyle = '#FFF';
            ctx.fillText(`Load Factor: ${loadFactor.toFixed(2)}`, 10, 25);

            for (let i = 0; i < NUM_BUCKETS; i++) {
                const xOffset = i * BUCKET_W + 30;
                const color = getColor(i);
                ctx.fillStyle = color;
                ctx.fillRect(xOffset, Y_START - (buckets[i].length * 25) + 10, BUCKET_W - 4, canvas.height - 30);

                // Draw bucket index label
                ctx.fillStyle = '#FFF';
                ctx.fillText(`${i}`, xOffset + 5, Y_START + 15);

                let currentY = Y_START;
                for (const item of buckets[i]) {
                    let boxX = xOffset + 10;
                    let boxW = BUCKET_W - 20;
                    let boxH = 20;

                    // Draw Key Box
                    ctx.fillStyle = '#444';
                    ctx.fillRect(boxX, item.y, boxW, boxH);
                    ctx.strokeStyle = color;
                    ctx.strokeRect(boxX, item.y, boxW, boxH);
                    
                    // Draw Key Label
                    ctx.fillStyle = '#FFF';
                    ctx.fillText(`Key: ${item.k}`, boxX + 5, item.y + 15);

                    // Draw Connection Line (only if not the first element)
                    if (buckets[i].indexOf(item) > 0) {
                        let prevItem = buckets[i][buckets[i].indexOf(item) - 1];
                        ctx.beginPath();
                        ctx.moveTo(boxX + boxW, prevItem.y + boxH);
                        ctx.lineTo(boxX + boxW, item.y);
                        ctx.strokeStyle = '#888';
                        ctx.lineWidth = 2;
                        ctx.stroke();
                    }
                }
            }
        }

        // Main animation loop
        function animate() {
            if (!animationRunning) {
                init(); // Restart simulation when finished
            } else if (keysCount < 50) {
                // Generate random key and insert it
                const randomKey = Math.floor(Math.random() * 1000);
                insertKey(randomKey);
                draw();
            }

            requestAnimationFrame(animate);
        }

        // Start the simulation
        init();
        animate();
    </script>
</body>
</html>
```
mistral-small:24bERRSTATFORMAT
Show code
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hash Table Animation</title>
<style>
canvas { border: 1px solid black; }
</style>
</head>
<body>
<canvas id="hashCanvas" width="800" height="600"></canvas>
<script>
// Canvas and context setup
const canvas = document.getElementById('hashCanvas');
const ctx = canvas.getContext('2d');
const buckets = Array(12).fill().map(() => []);
let keysInserted = 0;
let animationFrame;

// Drawing functions
function drawBucket(x, y, bucket) {
    const fillLevel = bucket.length / 4;
    ctx.fillStyle = fillLevel < 1 ? 'green' : fillLevel < 3 ? 'yellow' : 'red';
    ctx.fillRect(x - 20, y, 40, 5 * (bucket.length + 1));
    ctx.strokeRect(x - 20, y, 40, 5 * (bucket.length + 1));

    for (let i = 0; i < bucket.length; i++) {
        const textY = y + 30 + i * 60;
        ctx.fillStyle = 'black';
        ctx.fillText(bucket[i], x - 20, textY);
        if (i > 0) {
            ctx.beginPath();
            ctx.moveTo(x - 15, textY - 40);
            ctx.lineTo(x - 39, textY + 10);
            ctx.strokeStyle = 'black';
            ctx.stroke();
        }
    }
}

function clearCanvas() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
}

// Animation loop
function animate() {
    keysInserted++;
    if (keysInserted > 60) {
        buckets.fill().map(() => []);
        keysInserted = 0;
    }
    const randomKey = Math.floor(Math.random() * 120); // Random key between 0 and 119
    const hashIndex = randomKey % 12; // Simple modulo hashing
    buckets[hashIndex].push(randomKey);

    clearCanvas();
    for (let i = 0; i < 12; i++) {
        drawBucket(50 + i * 60, 50, buckets[i]);
    }
    ctx.fillStyle = 'black';
    ctx.font = '20px Arial';
    ctx.fillText(`Load Factor: ${keysInserted / 12}`, 10, 30);

    animationFrame = requestAnimationFrame(animate);
}

animationFrame = requestAnimationFrame(animate);
</script>
</body>
</html>
```
command-r:35bOKFORMAT
Show code
```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hash Table Animation</title>
    <style>
        body {
            margin: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background-color: #222;
            font-family: Arial, sans-serif;
            color: #fff;
        }
        canvas { border: 3px solid #4CAF50; }
    </style>
</head>
<body>

    <canvas id="myCanvas"></canvas>

    <script>

        const canvas = document.getElementById('myCanvas');
        const ctx = canvas.getContext('2d');
        let width = window.innerWidth, height = window.innerHeight;
        canvas.width = 800; // scale to fit a 16:9 aspect ratio with room for text at the bottom
        canvas.height = (canvas.width * 9) / 16;

        function drawSlot(x, y, fillLevel) {
            const slotWidth = canvas.width / 12 - 5; // subtract some padding between slots
            const chainLength = Math.round(fillLevel * 7);
            ctx.fillStyle = ['green', 'yellow', 'red'][Math.floor(fillLevel)]; // simpler colormap than the one in the prompt
            ctx.beginPath();
            ctx.rect(x, y, slotWidth, canvas.height - chainLength );
            ctx.stroke();
            ctx.fill();

            for (let i = 0; i < Math.min(chainLength, fillLevel); i++) {
                // draw boxes and connecting lines in the growing vertical chain
                const x1 = x + 2, y1 = canvas.height - i * 8 - 4;
                ctx.fillStyle = '#fff';
                ctx.beginPath();
                ctx.rect(x1, y1, slotWidth-4, 6); // each box is 6 pixels tall (half of the chain length)
                ctx.stroke();
                ctx.fill();

                if (i > 0) {
                    const x2 = x + slotWidth/2;
                    const y2 = canvas.height - i * 8 - 7;
                    const dy = Math.abs(y2 - y1); // length of the connecting line
                    ctx.beginPath();
                    ctx.moveTo(x1, y1+3);
                    ctx.lineTo(x2-dy/2, y2+3);
                    ctx.stroke();
                }
            }
        }

        let buckets = [];
        for (let i = 0; i < 12; i++) { 
            const newBucket = { keys: [], fillLevel: 0 };
            buckets.push(newBucket); // initialize all slots empty
            drawSlot(i * canvas.width / 12, 35, 0);
        }

        function insertKey(key) {
            let slotIndex = key % 12;

            if (buckets[slotIndex].keys.length > 0)
                buckets[slotIndex].fillLevel++; // grow collision chain length by one for each new key in the bucket 

            buckets[slotIndex].keys.push(key);
        }

        function animate() {  
            
            ctx.clearRect(0, 0, canvas.width, canvas.height);

            const keysInserted = Math.random() * 65 | 0; // generate a random number of keys to insert
            for (let i = 0; i < keysInserted; i++) {
                const key = Math.floor(Math.random() * 12345); 
                insertKey(key); 
            }

            for (let i = 0; i < 12; i++)
                drawSlot(i * canvas.width / 12, 35, buckets[i].fillLevel); // update all bucket graphics in a single pass to avoid flicker 

            const loadFactor = keysInserted / 12;
            ctx.font = 'bold 24px Arial'; 
            ctx.textAlign = 'center';
            ctx.fillText(`Load Factor: ${loadFactor.toFixed(3)}`, canvas.width/2, canvas.height - 60);

            // restart the animation when all buckets have been filled at least once to keep them short enough for the visualization
            if (buckets.filter(bucket => bucket.keys.length > 0).length === 12) {
                for (let i = 0; i < 12; i++)
                    buckets[i] = { keys: [], fillLevel: 0 }; // reset all slots to empty 
            }

            requestAnimationFrame(animate);
        }

        animate();
    </script>
</body>
</html>
```
qwq:32bBLANKLIM
Show code
<think>

Alright, so I need to create a self-contained HTML file that animates a hash table on a canvas. Let me start by understanding the requirements.

First, the hash table should have exactly 12 buckets arranged side by side as vertical slots. Each bucket is a vertical slot where keys are dropped. When a key is inserted into a bucket that already has keys, it forms a chain. The chains should be visible with small labeled boxes connected by lines. Each bucket's color should indicate its fill level: green for empty, yellow for a few keys, and red for longer chains. The load factor (total keys divided by 12) needs to be displayed. After inserting around 40-60 keys, the buckets should clear and restart with a new sequence. The animation should use requestAnimationFrame for smoothness, no user input, and start immediately. Also, no external libraries.

Okay, let's break this down step by step.

First, the HTML structure. We'll need a canvas element. The rest is JavaScript within a script tag. Since it's self-contained, all code must be in one HTML file.

Starting with the canvas setup. The canvas needs to be sized appropriately. Let's say each bucket is 50 pixels wide. With 12 buckets, that's 600px width. Height can be 400px, giving enough vertical space for the chains. So, canvas width=600, height=400.

Now, the JavaScript part. We'll need variables to track the state:

- An array to represent each bucket's chain. Maybe an array of arrays: buckets = [[], [], ..., []], each holding the keys inserted there.

- A counter for the total keys inserted (to calculate load factor).

- A timer or interval to generate new keys at intervals. Since we need to use requestAnimationFrame for animation, maybe we can trigger key generation within the animation loop.

The hashing function is simple: key modulo 12. So each key's bucket is key % 12.

Collision handling: when inserting a key into a bucket that's not empty, the chain grows. Each key in the chain should be represented as an object with its value and position.

Drawing the buckets: Each bucket is a vertical slot. The first key in the bucket is at the bottom, and each subsequent key is stacked above with some spacing. The vertical position should be calculated based on the chain length.

Coloring based on fill level: Need to decide thresholds. Maybe:

- Green if chain length is 0-1 (empty or single key).

- Yellow for 2-3 keys.

- Red for 4+ keys.

The load factor is total keys / 12. We'll display this as a number on the canvas.

Animation loop with requestAnimationFrame. In each frame, we first draw the buckets, then check if we need to add a new key (maybe every few frames), then redraw everything.

When to reset? Once total keys reach around 40-60. Let's pick 60 as a cutoff. So after 60 keys, reset the buckets and start over with new keys.

Generating random keys: Math.random() * max, but since modulo 12, the key can be an integer. Maybe generate integer keys between 0 and, say, 1000 to spread them out. Wait, actually, modulo 12 would map any key to 0-11. So generating keys as Math.floor(Math.random() * 1000) makes sense.

Now structuring the code:

Setup:

- Initialize the canvas context.

- Variables: buckets array, totalKeys, loadFactor.

- Function to draw the canvas: clear, draw each bucket with its chain, color based on chain length, draw load factor text.

In the main loop (requestAnimationFrame):

- Clear the canvas.

- Draw all buckets.

- If totalKeys < 60, add a new key (maybe every time, but throttle it so it's not too fast). Or, perhaps add a key every frame until totalKeys reaches the limit.

Wait, need to control the rate of key insertion. If we add a key on every frame, it might be too fast. Maybe add a timer where every 0.5 seconds a key is added. But since we can't use setInterval (or can we?), perhaps within the animation loop, we can track the time and increment a counter every so many milliseconds.

Alternatively, since requestAnimationFrame runs at ~60fps, every 10 frames (about 0.16 seconds) we can add a key. Wait, but for 60 keys, that would take 60 * (10 frames) = 600 frames, which is about 10 seconds. That might be okay.

Alternatively, increment a counter and every time the counter reaches, say, 10, we add a key and reset the counter. So:

let keyAddInterval = 10;
let addCounter = 0;
function animate() {
  addCounter++;
  if (addCounter >= keyAddInterval) {
    addNewKey();
    addCounter = 0;
    if (totalKeys >= 60) {
      reset();
    }
  }
  // draw everything
  requestAnimationFrame(animate);
}

Wait, but in this case, the key is added every 10 frames. So totalKeys would reach 60 in 600 frames (about 10 seconds). That might be acceptable.

Alternatively, to make it a bit faster or slower, adjust keyAddInterval. Let's see.

Alternatively, use a timestamp approach. But perhaps the counter approach is simpler for the scope here.

Now, adding a key:

- Generate a random integer key (maybe between 0 and 1000).

- Compute bucketIndex = key % 12.

- Push the key to the bucket's array.

- Increment totalKeys.

- Also, track the timestamp or something else? Maybe not needed.

Drawing each bucket:

Each bucket is at position x = bucketIndex * bucketWidth (bucketWidth = 50px).

The vertical slot is a rectangle at x, starting from the bottom of the canvas upwards. Wait, actually, the chain is drawn upwards from the bottom. So the first key is at the bottom, then each subsequent one is above.

Each key in the bucket's chain is represented as a small box (rectangle) with the key's value inside. The boxes are connected by lines between them.

The drawing steps for a bucket:

For bucket i, at x position:

- Determine the y position of each element in the chain.

Start at the bottom (canvas height - some offset), then each subsequent element is above by, say, 30 pixels.

Wait, let's think of each element (key) in the bucket's array as stacked upwards. The first element is at bottomY = canvas height - 20 (so it's 20px tall?), then each next is above by 30px (so 20px height + 10px spacing?).

Wait, the exact dimensions can be set as follows:

Each box is 20px tall and 30px wide. The spacing between boxes can be 5px, so each next box is 25px above (20+5).

Wait, let's decide on the box size:

Each key is a rectangle 20px tall and 30px wide. The spacing between boxes in a chain is 5px. So the vertical distance between elements is 25px (20+5).

The starting position for the first element (bottom-most) is at y = canvasHeight - 10 (since we want it centered vertically? Maybe the bottom of the box is at canvasHeight. Hmm, need to think in coordinates.

Canvas coordinate system: (0,0) is top-left.

So, the bottom of the canvas is at height = canvas.height.

Suppose each box is 20px tall. The bottom of the first box should be at canvas.height. So its top Y is canvas.height - 20, and bottom is canvas.height.

But then when drawing a line between boxes, the line should connect the bottom of the upper box to the top of the lower box.

Wait, perhaps it's better to have each box centered in the bucket's slot vertically as they stack. Alternatively, stack them from the bottom up.

Alternatively, the first element is drawn at the bottom of the bucket's slot, then each subsequent element is drawn above, connected with a line.

So for bucket i:

x = i * 50 + 25 (centered in the bucket's 50px width).

The starting Y for the first element is canvasHeight - 10 (so the center is at the bottom of the bucket).

Wait, maybe:

Each bucket is a vertical slot 50px wide and, say, 300px tall (since the canvas is 400px, leaving 100px at the top for labels or spacing).

But perhaps it's better to let the chains stack up as much as possible.

Alternatively, each bucket's vertical position starts at the bottom (y=canvas.height) and each element is drawn upward.

Wait, here's the plan:

Each bucket is represented as a vertical slot (a line or rectangle) at x = (bucket index * width) + (width/2). The vertical lines can be drawn as rectangles 5px wide and 300px tall, starting from y=20 (to leave some space at the top) to y=320 (total 300px). The vertical line is just a thin line to denote the bucket's position.

But actually, the chain elements will be drawn inside these slots.

Each key in a bucket's chain is a rectangle (box) placed vertically, starting from the bottom of the bucket's line, moving upwards each time.

So the first (bottom) element is at y = bucketYStart (e.g., 20 + 295) since bucket height is 300px? Hmm, perhaps:

The bucket slot is from y=20 (top) to y=320 (bottom), 300px tall. So the bottom of the bucket is at y=320.

The first key's box is placed so its bottom is at y=320 - (boxHeight/2), so centered vertically in the last row.

Wait, maybe the boxes are 15px tall and 30px wide, spaced 5px between them. Let me think of exact numbers.

Box dimensions:

- Width: 30px (so centered in the bucket's 50px width, so x at bucketX + (50-30)/2 = 10, but bucketX is centered at 25, so maybe better to have the boxes centered in the bucket's slot.

Wait, bucket width is 50px. The center is at x = (bucketIndex * 50) + 25.

Boxes should be centered horizontally in the bucket. So each box is 30px wide, so its x position is bucketXCenter - 15 (since 30/2 is 15).

Height of each box: 15px, so height = 15px.

The vertical spacing between boxes: let's say 20px (so 15px height + 5px spacing between).

Thus, for a bucket's chain of length N, starting from the bottom:

The bottom box is placed at y = 320 - (15/2) (so centered vertically in the bottom position), but actually, we need to stack them upwards.

Wait perhaps it's better to start from the bottom and go up each time.

Let me formalize:

For each bucket:

const bucketX = bucketIndex * 50; // left edge
const bucketCenterX = bucketX + 25;
const boxWidth = 30;
const boxHeight = 15;
const spacing = 5; // vertical space between boxes

The first box (bottom-most) is positioned so that its bottom is at the bottom of the bucket's slot (y=320).

Wait, bucket slot goes from y=20 to y=320 (height 300px). So the bottom is at 320. So the first box's bottom y is 320.

But since the box is 15px tall, its top is at 305, bottom at 320.

Wait, no, if the box's bottom is at 320, then top is 305 (since height is 15).

Then the next box above it is placed at a bottom y of 305 - spacing - boxHeight ?

Wait, the vertical distance between the bottom of the next box and the top of the previous one should be spacing.

So the bottom of the upper box is at previousTop - spacing - boxHeight?

Wait let's think:

Previous box top = bottom - boxHeight

Next box's bottom should be at previous top - spacing.

Thus, next box bottom = (previous box bottom - boxHeight) - spacing

So for the first box:

bottomY = 320

topY = bottomY - boxHeight

Second box:

bottomY = topY_prev - spacing = (320 - 15) -5 = 300

Then its top is 285, etc.

So for each element in the chain, starting from the bottom:

The bottomY of the first element is 320.

Second element's bottom is 320 - (15 + 5) = 300.

Third is 300 - (15 +5) = 280, etc.

So the bottomY for the nth element is 320 - (n-1)*(15+5) = 320 - (n-1)*20.

Thus, the top edge is bottomY - 15.

We can calculate this for each element in the stack.

The position of each box is:

x: bucketCenterX - 15 (since box is 30px width, centered at bucketCenterX)

y: bottomY - boxHeight (since we have the bottom at bottomY, so top is bottomY - boxHeight)

Wait, to clarify:

The box's y-coordinate in canvas is the top edge.

So if the bottom of the box is at bottomY, then y = bottomY - boxHeight.

Therefore, the box is drawn from y to y + boxHeight.

Thus for the first box, bottomY is 320, so y = 320 -15 = 305. The box is from y=305 to 320.

Second box: bottomY = 300, so y=285 to 300.

Thus, this way they are stacked above each other with 5px spacing between their boxes.

Now, when drawing the lines between the boxes, each line connects the bottom of the upper box to the top of the lower box.

Wait, actually, the line should connect the boxes above and below. For each box except the first, draw a line from its top to the bottom of the previous box.

Wait, between box n and box n-1 (since we are going up):

For the first box (bottom), there is no line below it. The second box has a line connecting its bottom (its bottomY) to the first box's top (first box's top is first's bottomY - boxHeight).

Wait, perhaps the line is drawn between the bottom of the upper box (the one above) to the top of the lower box (the one below). Wait, need to think carefully.

Alternatively, for each pair of consecutive boxes in the chain, draw a line between their centers vertically.

Alternatively, between each pair, draw a line from the center of the upper box to the center of the lower box.

Hmm, perhaps it's simpler to draw lines between the bottom of the upper box and the top of the lower box.

Wait, let's say for boxes in order from bottom to top:

For elements 0 to N-1:

For each element i from 1 to N-1:

draw a line from the bottom of element i-1 to the top of element i?

Wait, maybe:

The line between box i and box i-1 (the one below it):

The coordinates would be:

The bottom of box i-1 is at bottomY_i-1.

The top of box i is at y_i.

Wait, since box i is above box i-1, box i's bottomY is lower?

Wait no, the first element is the bottom-most, so its bottomY is the highest (like 320). The next is above, so bottomY is 300, which is less than 320.

Wait, numbers are decreasing as we go up.

So for element i (starting from 0 at the bottom), its bottomY is:

bottomY_i = 320 - (i) * (20) ?

Wait, for the first element (i=0): 320 - 0*20 =320.

Second element (i=1): 320-20=300, etc.

Thus, the bottomY for element i is 320 - i * 20.

Therefore, the top of element i is bottomY_i - boxHeight = 320 -20i -15.

Wait, perhaps better to calculate the y position as:

y = 320 - (i + 1)*20 + 5 ?

Not sure. Alternatively, perhaps track each element's position in an array as we iterate through the bucket's keys.

Now, for drawing each bucket:

Loop through its keys array.

For each key in the array, compute its position.

Then draw the box and label, and lines between boxes.

Let me structure this in code.

First, in the draw function:

ctx.clearRect(0,0,w,h); // clear the canvas.

Then, for each bucket (index):

draw the bucket's vertical line?

Maybe draw a thin line at bucketX to indicate the bucket:

ctx.fillStyle = 'black';

ctx.fillRect(bucketX, 20, 5, 300); // a vertical line at the left edge, but maybe better centered?

Alternatively, just draw the boxes and lines.

But perhaps first draw the vertical lines for each bucket.

Alternatively, just draw the boxes and lines, but maybe the vertical lines are unnecessary.

Alternatively, highlight each bucket area with a thin line.

But perhaps better to focus on the boxes and lines.

Now, for each bucket:

const bucketXCenter = bucketIndex * 50 + 25;

const keys = buckets[bucketIndex]; // assuming buckets is an array of arrays.

for (let i = 0; i < keys.length; i++) {

 const bottomY = 320 - i * 20;

 const y = bottomY - boxHeight;

 // draw the box

 ctx.fillStyle = 'lightblue';

 ctx.fillRect(bucketXCenter - 15, y, 30, 15);

 // label the box with the key's value?

 ctx.fillStyle = 'black';

 ctx.font = '10px Arial';

 ctx.fillText(keys[i], bucketXCenter - 15 + 5, y + 10);

 // draw lines between boxes

 if (i > 0) {

 const prevBottomY = 320 - (i -1)*20;

 const prevY = prevBottomY - boxHeight;

 // line from current box's top to previous bottom?

 // Or between centers?

 // For line between current and previous (the one below it):

 // the current box's position is above the previous.

 // the previous is at (i-1), so its bottomY is higher (since i-1 < i).

 // To connect between the boxes, perhaps draw a line between the bottom of the previous box and the top of the current.

 // The previous box's bottom is prevBottomY.

 // The current box's top is y.

So the line from (bucketXCenter, prevBottomY) to (bucketXCenter, y).

Wait, the current box's top is y, so the line connects the bottom of the previous (prevBottomY) to the top of the current (y).

Thus:

ctx.beginPath();

ctx.moveTo(bucketXCenter, prevBottomY);

ctx.lineTo(bucketXCenter, y);

ctx.strokeStyle = 'gray';

ctx.stroke();

}

}

Wait, but in this case, the line would be vertical, but since the boxes are stacked vertically, the lines would be between them.

Alternatively, since the boxes are stacked vertically, the lines can just be vertical lines connecting them.

This seems okay.

Now, the color of the boxes can indicate their value? Or maybe just color based on bucket index?

But the user didn't specify, so maybe just color all boxes the same.

Now, for the color based on the bucket's load to indicate load:

The color could be scaled based on the number of elements in the bucket.

To do that, we can compute a color gradient (e.g., from green to red as the count increases).

Alternatively, set the fill color based on the count.

Let's say maxCount is the maximum number of elements in any bucket. Then for each bucket's count, compute a shade between green and red.

But this might complicate, but manageable.

Alternatively, just set a color for each bucket based on its index, but that's less informative.

Alternatively, leave the buckets as lightblue, and just have the lines.

Alternatively, the user might just want to see the visualization without colors, just the structure.

Proceeding, let's code this step by step.

First, the setup:

We need to represent the buckets as an array of arrays. For the purpose of this problem, perhaps we can simulate some buckets or use a placeholder.

Wait, the user hasn't provided specific data, so the question is to create a function or code that visualizes a hash table's buckets, but since it's a creation, perhaps we can assume buckets is an array of arrays, and we need to code the visualization.

Alternatively, perhaps the user expects a textual representation, but the question says "Create...", so likely a code snippet that draws it.

But since this is a text-based interface, perhaps a pseudocode or code in JavaScript that draws using canvas?

Assuming the answer should be a code snippet in JavaScript that uses HTML Canvas to draw the buckets.

Alright, proceeding with that.

Let me outline the code:

First, setup the canvas:

<canvas id="hashTable" width="400" height="400"></canvas>

Then, in JavaScript:

const canvas = document.getElementById('hashTable');

const ctx = canvas.getContext('2d');

const buckets = [ /* array of arrays, each element is a bucket. For example, [[1,2], [3], [], [4,5,6]] */ ];

function drawHashTable(buckets) {

 const w = canvas.width;

 const h = canvas.height;

 ctx.clearRect(0,0,w,h);

 const numBuckets = buckets.length;

 const bucketWidth = w / numBuckets; // assuming buckets are arranged horizontally.

 // The vertical dimension:

 const bucketHeight = h - 40; // leaving space at the top for labels?

 // drawing each bucket:

 for (let i = 0; i < numBuckets; i++) {

 const bucket = buckets[i];

 const startX = i * bucketWidth;

 const centerX = startX + bucketWidth/2;

 const startY = 20; // y starts at 20, leaving space at top

 // Draw the bucket's vertical line:

 ctx.fillStyle = 'black';

 ctx.fillRect(startX + 2, startY, 2, bucketHeight); // thin line for the bucket's position.

 // Now draw the elements in the bucket:

 const elementSpacing = 20; // spacing between elements vertically

 const elementHeight = 15;

 const elementWidth = 30;

 const maxElements = bucket.length;

 let currentY = startY + bucketHeight; // bottom of the bucket area.

 // Iterate elements from bottom to top.

 for (let j = 0; j < maxElements; j++) {

 const elementY = currentY - elementHeight - j * elementSpacing;

 ctx.fillStyle = 'lightblue';

 ctx.fillRect(centerX - elementWidth/2, elementY, elementWidth, elementHeight);

 ctx.fillStyle = 'black';

 ctx.fillText(bucket[j], centerX - elementWidth/2 + 5, elementY + 10);

 // draw line to previous element (if not first)

 if (j > 0) {

 ctx.beginPath();

 ctx.moveTo(centerX, currentY - (j-1)*elementSpacing);

 ctx.lineTo(centerX, elementY);

 ctx.strokeStyle = 'gray';

 ctx.stroke();

 }

 }

 }

}

// Example usage:

const exampleBuckets = [ [1], [2,3], [], [4,5,6], [7] ];

drawHashTable(exampleBuckets);

But this is a rough draft. Need to adjust the coordinates to get it right.

Alternatively, to make sure the elements stack from the bottom up:

The bucket's area is from startY (20) to startY + bucketHeight (say 300), so total height 280.

The elements should be placed starting from the bottom (y= 20 + 280 = 300) and moving upwards.

Wait, perhaps:

currentY starts at the bottom of the bucket area: startY + bucketHeight (20 + 300 = 320?).

Then each element is placed upwards.

Let me adjust:

for (let j = 0; j < maxElements; j++) {

 const elementY = (startY + bucketHeight) - elementHeight - j * (elementHeight + spacingBetween);

}

Wait, let's define spacingBetween = 5, so total space between boxes is spacingBetween.

Thus, each element takes elementHeight + spacingBetween vertically.

Therefore, the first element (bottom) starts at:

startingY = startY + bucketHeight - elementHeight;

then next is startingY - (elementHeight + spacingBetween),

 etc.

Thus, in code:

const spacingBetween = 5;

for (let j = 0; j < maxElements; j++) {

 const elementY = (startY + bucketHeight) - (j * (elementHeight + spacingBetween)) - elementHeight;

 // x position:

 const x = centerX - elementWidth/2;

 ctx.fillRect(x, elementY, elementWidth, elementHeight);

 // draw text inside.

 // line between elements:

 if (j > 0) {

 // line from current element's top to previous' bottom.

 ctx.beginPath();

 ctx.moveTo(centerX, elementY + elementHeight);

 ctx.lineTo(centerX, previousElementY);

 ctx.stroke();

 }

 previousElementY = elementY;

}

This requires tracking previousElementY.

Alternatively, compute previous position.

Alternatively, for each j:

elementY = startingY - j*(elementHeight + spacingBetween).

Wait, let's recast:

Starting from the bottom, the first element's bottom is at startY + bucketHeight.

Thus, elementY is:

elementY = (startY + bucketHeight) - elementHeight - j*(elementHeight + spacingBetween);

Wait, perhaps it's better to compute starting from the bottom:

total space needed for elements: (elementHeight + spacingBetween) * (maxElements -1) + elementHeight.

This must be less than bucketHeight.

So the starting Y (top of the first element) is:

startY + bucketHeight - ( (elementHeight + spacingBetween)*(maxElements-1) + elementHeight )

Hmm, maybe it's getting too complex.

Alternatively, just let the elements stack upwards from the bottom, and if they exceed the bucketHeight, they just go beyond the bucket's area.

Alternatively, set the bucketHeight to accommodate.

But given that this is a visualization, perhaps it's okay if elements go beyond the bucket's line.

Alternatively, set the bucketHeight such that:

maxHeight = (maxElements * (elementHeight + spacingBetween)) - spacingBetween

bucketHeight = Math.max(bucketHeightBase, maxHeight);

But this complicates.

Alternatively, ignore the bucket's line height and just let elements stack upwards from the bottom of the canvas.

Perhaps the main thing is to have the elements stacked vertically in each bucket's column.

Here's an improved code snippet:

function drawHashTable(buckets) {

 const canvas = document.getElementById('hashTable');

 const ctx = canvas.getContext('2d');

 const w = canvas.width;

 const h = canvas.height;

 ctx.clearRect(0, 0, w, h);

 const numBuckets = buckets.length;

 const bucketWidth = w / numBuckets;

 const elementWidth = 30;

 const elementHeight = 15;

 const spacingBetween = 5;

 // Draw each bucket's elements:

 for (let i = 0; i < numBuckets; i++) {

 const bucket = buckets[i];

 const centerX = i * bucketWidth + bucketWidth / 2;

 // Draw elements starting from the bottom upwards:

 let currentY = h - 10; // start near the bottom

 for (let j = 0; j < bucket.length; j++) {

 const elementY = currentY - elementHeight;

 ctx.fillStyle = 'lightblue';

 ctx.fillRect(centerX - elementWidth / 2, elementY, elementWidth, elementHeight);

 ctx.fillStyle = 'black';

 ctx.fillText(bucket[j], centerX - elementWidth / 2 + 5, elementY + 10);

 // move up for the next element:

 currentY = elementY - spacingBetween;

 }

 // Draw a vertical line for the bucket's position:

 ctx.strokeStyle = 'black';

 ctx.beginPath();

 ctx.moveTo(centerX, 10);

 ctx.lineTo(centerX, currentY);

 ctx.stroke();

 }

}

This way, each bucket's elements start from the bottom (near the bottom of the canvas) and stack upwards, with each subsequent element above the previous, separated by spacingBetween.

The vertical line for the bucket starts from the top (y=10) down to where the elements end.

This might look better.

Testing this with sample buckets:

Example:

buckets = [[1,2], [3], [4,5,6], [7]]

Each bucket is a column, with elements stacked from bottom up.

The vertical lines go from the top to where the elements end.

This should give a clear visualization.

Thus, the code can be structured this way.

The final answer would be a JavaScript function that draws this visualization using canvas, along with the necessary HTML setup.

However, since the user might expect a textual description or pseudocode, but given the context, providing the JavaScript code in a boxed format is appropriate.

Thus, the final answer is a JavaScript function to visualize the hash table's buckets as described.
deepseek-r1:32bBLANKFORMAT
Show code
```html
<!DOCTYPE html><html><body style="background:#1a1a1a;margin:0;display:flex;justify-content:center;align-items:center;height:100vh"><canvas id=c width=840 height=420></canvas>
<script>
let ctx=c.getContext('2d'),buckets=[],keysInserted=0,keyCount=0,running=true,loadFactor=0;
function init(){c.width=840;c.height=420;ctx.fillStyle='#1a1a1a';ctx.fillRect(0,0,c.width,c.height);buckets=[];for(let i=0;i<12;++i)buckets[i]=[];keysInserted=0}
function drawBucket(x,bucket){
  ctx.strokeStyle='rgb('+Math.min(bucket.length*5,255)+', '+Math.max(255-5*(bucket.length),0)+', 0)';
  let yStart=40;
  if(bucket.length>0){yStart+=10;ctx.beginPath();ctx.arc(x+30,40,30,0,Math.PI*2);ctx.stroke()}
  for(let i=0;i<bucket.length;++i){
    ctx.fillStyle='white';let y=yStart+i*(50);
    ctx.fillRect(x+20,y-10,40,20);
    if(i>0){ctx.beginPath();ctx.moveTo(x+30,y-60);ctx.lineTo(x+30,y-50);ctx.stroke()}
    ctx.fillStyle='black';ctx.font='12px Arial';let txt=bucket[i].toFixed(0);ctx.fillText(txt,x+30-Math.max(txt.length*4,40)/2,y-9)}
}
function updateLoadFactor(){loadFactor=keysInserted/12;document.title='Load Factor: '+loadFactor.toFixed(2)}
function animate(t){
  if(!running)setTimeout(init,500);
  else{
    ctx.fillStyle='#1a1a1a';ctx.fillRect(0,0,c.width,c.height);
    for(let i=0;i<12;++i)drawBucket(70+60*i,buckets[i]);
    ctx.fillStyle='white';ctx.font='20px Arial';ctx.fillText('Load Factor: '+loadFactor.toFixed(2),10,30);
    if(keysInserted<=40){
      let key=Math.floor(Math.random()*1e6);let idx=bucketIdx(key);
      buckets[idx].push(key);keysInserted++;
      updateLoadFactor();requestAnimationFrame(animate)
    }else{
      running=false;init()
    }
  }
}
function bucketIdx(k){return k%12}
init();updateLoadFactor();animate()
</script></body></html>
```
Outside the Brain cluster — same task, same character budget, collected through their own tooling (response times not comparable)
Claude Opus 5frontier referenceOK
Show code
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Hash Table Chaining</title>
<style>html,body{margin:0;height:100%;background:#0d1117;display:flex;align-items:center;justify-content:center}canvas{max-width:100%;max-height:100%}</style></head><body><canvas id="c" width="960" height="600"></canvas>
<script>
const c=document.getElementById('c'),x=c.getContext('2d'),N=12,M='ui-monospace,SFMono-Regular,Menlo,monospace';
const BW=58,GAP=(960-N*BW)/(N+1),TOP=140,BH=22,VG=10;
let B,tot,goal,fly,timer,phase,fade;
function reset(){B=[];for(let i=0;i<N;i++)B.push([]);tot=0;goal=40+((Math.random()*21)|0);fly=null;timer=10;phase=0;fade=0;}
reset();
function col(n){if(n===0)return['#16241c','#2f6b45'];if(n<=2)return['#123a27','#3ddc84'];if(n<=4)return['#4a3b0f','#ffd23f'];return['#4d1a1a','#ff5d5d'];}
function rr(a,b,w,h,r){x.beginPath();x.roundRect(a,b,w,h,r);}
function bx(i){return GAP+i*(BW+GAP);}
function step(){
 if(phase===0){
  if(!fly){timer--;if(timer<=0){const k=(Math.random()*900|0)+100;fly={k:k,b:k%N,t:0};}}
  else{fly.t+=0.05;if(fly.t>=1){B[fly.b].push(fly.k);tot++;fly=null;timer=7;if(tot>=goal){phase=1;timer=80;}}}
 }else{timer--;if(timer<=0){fade+=0.05;if(fade>=1)reset();}}
}
function draw(){
 x.fillStyle='#0d1117';x.fillRect(0,0,960,600);
 x.globalAlpha=phase===1?Math.max(0,1-fade):1;
 x.textAlign='left';x.fillStyle='#e6edf3';x.font='bold 22px '+M;
 x.fillText('HASH TABLE  •  separate chaining  •  h(k) = k mod 12',30,44);
 x.font='15px '+M;x.fillStyle='#8b949e';
 x.fillText('keys inserted: '+tot+' / '+goal,30,78);
 x.fillText('load factor α = '+(tot/N).toFixed(2),30,102);
 x.fillStyle='#21262d';rr(340,68,300,12,6);x.fill();
 const r=tot/N;
 x.fillStyle=r>3.5?'#ff5d5d':r>2?'#ffd23f':'#3ddc84';rr(340,68,Math.max(2,Math.min(1,r/5)*300),12,6);x.fill();
 x.fillStyle='#8b949e';x.font='12px '+M;x.fillText(phase===1?'table full — clearing, new random run…':'inserting random keys…',340,100);
 x.textAlign='center';
 for(let i=0;i<N;i++){
  const a=bx(i),n=B[i].length,cc=col(n);
  x.lineWidth=2;x.fillStyle=cc[0];x.strokeStyle=cc[1];
  rr(a,TOP,BW,32,6);x.fill();x.stroke();
  x.fillStyle=cc[1];x.font='bold 14px '+M;x.fillText(i,a+BW/2,TOP+21);
  let y=TOP+32;
  for(let j=0;j<n;j++){
   x.strokeStyle=cc[1];x.lineWidth=2;
   x.beginPath();x.moveTo(a+BW/2,y);x.lineTo(a+BW/2,y+VG);x.stroke();
   const by=y+VG;
   x.fillStyle='#161b22';x.strokeStyle=cc[1];rr(a+7,by,BW-14,BH,4);x.fill();x.stroke();
   x.fillStyle='#e6edf3';x.font='12px '+M;x.fillText(B[i][j],a+BW/2,by+15);
   y=by+BH;
  }
  x.fillStyle='#484f58';x.font='11px '+M;x.fillText(n,a+BW/2,584);
 }
 if(fly){
  const a=bx(fly.b),n=B[fly.b].length,t=fly.t,e=t*t*(3-2*t);
  const ty=TOP+32+VG+n*(BH+VG)+BH/2;
  const px=480+(a+BW/2-480)*e,py=70+(ty-70)*e;
  x.lineWidth=2;x.fillStyle='#0f2439';x.strokeStyle='#58a6ff';
  rr(px-(BW-14)/2,py-BH/2,BW-14,BH,4);x.fill();x.stroke();
  x.fillStyle='#58a6ff';x.font='bold 12px '+M;x.fillText(fly.k,px,py+4);
  x.font='13px '+M;x.fillText(fly.k+' % 12 → bucket '+fly.b+(n>0?'   (collision, chain '+(n+1)+')':''),480,124);
 }
 x.globalAlpha=1;
}
(function loop(){step();draw();requestAnimationFrame(loop);})();
</script></body></html>
GPT-5.5 (Codex)frontier referenceOKMINIFIED
Show code
<!doctype html><html><head><meta charset="utf-8"><title>Hash Table</title><style>html,body{margin:0;height:100%;background:#111;color:#eee;font:16px system-ui}canvas{display:block;width:100%;height:100%}</style></head><body><canvas id="c"></canvas><script>
let c=document.getElementById('c'),x=c.getContext('2d'),d=devicePixelRatio||1,b=Array.from({length:12},()=>[]),n=0,t=0,next=0,drop=null,limit=48;
function R(){c.width=innerWidth*d;c.height=innerHeight*d;x.setTransform(d,0,0,d,0,0)}onresize=R;R();
function key(){return Math.floor(Math.random()*900)+100}
function reset(){b=Array.from({length:12},()=>[]);n=0;limit=40+Math.floor(Math.random()*21);next=performance.now()+400;drop=null}
function col(l){return l<2?'#35c46b':l<5?'#e6c84f':'#e45858'}
function add(now){let k=key(),h=k%12,top=b[h].length;drop={k,h,y:-34,to:126+top*34,st:now};n++;next=now+360}
function drawBox(cx,y,w,h,k,fill){x.fillStyle=fill;x.strokeStyle='#ffffffcc';x.lineWidth=2;x.beginPath();x.roundRect(cx-w/2,y,w,h,5);x.fill();x.stroke();x.fillStyle='#fff';x.textAlign='center';x.textBaseline='middle';x.font='13px system-ui';x.fillText(k,cx,y+h/2)}
function frame(now){let W=innerWidth,H=innerHeight;x.clearRect(0,0,W,H);x.fillStyle='#f2f2f2';x.font='18px system-ui';x.textAlign='left';x.fillText('load factor: '+(n/12).toFixed(2),24,32);let gap=8,sw=Math.min(54,(W-50)/12-gap),start=(W-(sw+gap)*12+gap)/2,base=72;for(let i=0;i<12;i++){let cx=start+i*(sw+gap)+sw/2,l=b[i].length;x.fillStyle=col(l);x.fillRect(cx-sw/2,base,sw,44);x.strokeStyle='#fff8';x.lineWidth=2;x.strokeRect(cx-sw/2,base,sw,44);x.fillStyle='#111';x.textAlign='center';x.font='14px system-ui';x.fillText(i,cx,base+25);for(let j=0;j<l;j++){let y=126+j*34;if(j){x.strokeStyle='#ddd';x.beginPath();x.moveTo(cx,y-10);x.lineTo(cx,y);x.stroke()}drawBox(cx,y,sw*.9,25,b[i][j],'#2f79d8')}}if(!drop&&now>next){if(n>=limit)setTimeout(reset,450);else add(now)}if(drop){let cx=start+drop.h*(sw+gap)+sw/2,p=Math.min(1,(now-drop.st)/520),e=1-(1-p)*(1-p),y=-34+(drop.to+34)*e;drawBox(cx,y,sw*.9,25,drop.k,'#f08a24');if(p>=1){b[drop.h].push(drop.k);drop=null}}requestAnimationFrame(frame)}reset();requestAnimationFrame(frame)
</script></body></html>
Claude Sonnet 5frontier referenceOK
Show code
<!DOCTYPE html><html><head><meta charset="utf-8"><title>Hash Table Animation</title>
<style>html,body{margin:0;height:100%;background:#0b0e14;overflow:hidden}canvas{display:block}</style>
</head><body>
<canvas id="c"></canvas>
<script>
const c=document.getElementById('c'),x=c.getContext('2d');
function rs(){c.width=innerWidth;c.height=innerHeight}
rs();addEventListener('resize',rs);
const N=12;
let buckets,total,limit,lastAdd;
function reset(){
 buckets=Array.from({length:N},()=>[]);
 total=0;
 limit=40+Math.floor(Math.random()*21);
 lastAdd=0;
}
reset();
function colorFor(n){
 if(n<=1)return '#2ecc71';
 if(n<=3)return '#f1c40f';
 return '#e74c3c';
}
function frame(t){
 if(t-lastAdd>150){
  lastAdd=t;
  if(total<limit){
   const key=1+Math.floor(Math.random()*999);
   const h=key%N;
   buckets[h].push(key);
   total++;
  } else {
   reset();
  }
 }
 draw();
 requestAnimationFrame(frame);
}
function draw(){
 x.fillStyle='#0b0e14';
 x.fillRect(0,0,c.width,c.height);
 const w=c.width, h=c.height;
 const bw=w/N;
 const top=90;
 const boxH=26, boxGap=8, boxW=Math.min(bw-20,70);
 for(let i=0;i<N;i++){
  const cx=i*bw+bw/2;
  const arr=buckets[i];
  x.strokeStyle='#445';
  x.lineWidth=2;
  x.beginPath();
  x.moveTo(cx,top);
  x.lineTo(cx,h-20);
  x.stroke();
  x.fillStyle='#8899aa';
  x.font='14px monospace';
  x.textAlign='center';
  x.fillText(i,cx,top-15);
  x.fillStyle=colorFor(arr.length);
  x.fillRect(cx-bw*0.4,top-8,bw*0.8,6);
  let py=top+20;
  for(let j=0;j<arr.length;j++){
   const y=py+j*(boxH+boxGap);
   if(j>0){
    x.strokeStyle='#889';
    x.beginPath();
    x.moveTo(cx,y-boxGap);
    x.lineTo(cx,y);
    x.stroke();
   }
   x.fillStyle=colorFor(arr.length);
   x.fillRect(cx-boxW/2,y,boxW,boxH);
   x.strokeStyle='#111';
   x.strokeRect(cx-boxW/2,y,boxW,boxH);
   x.fillStyle='#111';
   x.font='bold 12px monospace';
   x.fillText(arr[j],cx,y+boxH/2+4);
  }
 }
 x.fillStyle='#dde';
 x.font='20px monospace';
 x.textAlign='left';
 x.fillText('Hash Table  (mod 12)   keys: '+total+'   load factor: '+(total/N).toFixed(2),20,40);
 x.font='14px monospace';
 x.fillStyle='#889';
 x.fillText('h(key) = key mod 12 -- collisions chain downward',20,65);
}
requestAnimationFrame(frame);
</script></body></html>
Claude Fable 5frontier referenceOK
Show code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Hash Table Collision Animation</title>
<style>
html,body{margin:0;height:100%;background:#0e1116;overflow:hidden}
canvas{display:block;width:100vw;height:100vh}
</style>
</head>
<body>
<canvas id="c"></canvas>
<script>
const cv=document.getElementById("c"),ctx=cv.getContext("2d");
let W,H;
function rs(){W=cv.width=innerWidth;H=cv.height=innerHeight}
rs();addEventListener("resize",rs);
const NB=12;
let buckets,total,target,drops,timer,phase,fade;
function reset(){
buckets=Array.from({length:NB},()=>[]);
total=0;
target=40+Math.floor(Math.random()*21);
drops=[];
timer=0;
phase="run";
fade=0;
}
reset();
function spawn(){
const key=Math.floor(Math.random()*900)+100;
const b=key%NB;
drops.push({key,b,y:-30,t:0,landed:false});
}
function geom(){
const m=Math.min(W,H);
const bw=Math.min(70,(W-80)/NB-10);
const gap=(W-NB*bw)/(NB+1);
const topY=110;
const bh=Math.min(26,m/24);
return{bw,gap,topY,bh};
}
function slotX(i,g){return g.gap+i*(g.bw+g.gap)}
function fillCol(n){
if(n<=1)return["#1f8a4c","#2ecc71"];
if(n<=2)return["#8a7a1f","#e8d34a"];
if(n<=4)return["#a05a1a","#f39c3d"];
return["#a02525","#ff5b5b"];
}
function draw(dt){
ctx.clearRect(0,0,W,H);
const grd=ctx.createLinearGradient(0,0,0,H);
grd.addColorStop(0,"#10141c");grd.addColorStop(1,"#0a0d12");
ctx.fillStyle=grd;ctx.fillRect(0,0,W,H);
const g=geom();
ctx.textAlign="center";
ctx.fillStyle="#dfe7f0";
ctx.font="bold "+Math.min(24,W/34)+"px monospace";
ctx.fillText("HASH TABLE  ·  h(k) = k mod 12",W/2,40);
const lf=total/NB;
ctx.font=Math.min(17,W/50)+"px monospace";
ctx.fillStyle="#9fb3c8";
ctx.fillText("keys: "+total+" / "+target+"    load factor: "+lf.toFixed(2),W/2,70);
const bx=W/2-140,bx2=280;
ctx.fillStyle="#1d2530";
ctx.fillRect(bx,80,bx2,8);
ctx.fillStyle=lf<2?"#2ecc71":lf<3.5?"#e8d34a":"#ff5b5b";
ctx.fillRect(bx,80,Math.min(1,lf/5)*bx2,8);
for(let i=0;i<NB;i++){
const x=slotX(i,g);
const chain=buckets[i];
const n=chain.length;
const[edge,fill]=fillCol(n);
const slotH=H-g.topY-50;
ctx.strokeStyle=edge;
ctx.lineWidth=2;
ctx.strokeRect(x,g.topY,g.bw,slotH);
ctx.fillStyle=edge+"22";
ctx.fillRect(x,g.topY,g.bw,slotH);
ctx.fillStyle="#8fa3b8";
ctx.font="bold "+Math.min(14,g.bw/3)+"px monospace";
ctx.fillText(i,x+g.bw/2,g.topY-8);
for(let j=0;j<n;j++){
const by=g.topY+8+j*(g.bh+10);
if(j>0){
ctx.strokeStyle=fill;
ctx.lineWidth=2;
ctx.beginPath();
ctx.moveTo(x+g.bw/2,by-10);
ctx.lineTo(x+g.bw/2,by);
ctx.stroke();
}
ctx.fillStyle=fill;
ctx.strokeStyle=edge;
const bwx=g.bw-10;
ctx.beginPath();
ctx.roundRect(x+5,by,bwx,g.bh,4);
ctx.fill();ctx.stroke();
ctx.fillStyle="#0e1116";
ctx.font="bold "+Math.min(13,bwx/3.4)+"px monospace";
ctx.fillText(chain[j],x+g.bw/2,by+g.bh/2+4);
}
ctx.fillStyle=fill;
ctx.font="bold 13px monospace";
ctx.fillText(n,x+g.bw/2,H-28);
}
for(const d of drops){
if(d.landed)continue;
const x=slotX(d.b,g)+g.bw/2;
const ty=g.topY+8+buckets[d.b].length*(g.bh+10)+g.bh/2;
d.y+=(dt/1000)*Math.max(300,(ty-d.y)*4+200);
if(d.y>=ty){
d.landed=true;
buckets[d.b].push(d.key);
total++;
if(total>=target)phase="clear";
}else{
ctx.fillStyle="#7fd4ff";
ctx.strokeStyle="#2c9fd4";
ctx.beginPath();
ctx.roundRect(x-(g.bw-10)/2,d.y-g.bh/2,g.bw-10,g.bh,4);
ctx.fill();ctx.stroke();
ctx.fillStyle="#04222e";
ctx.font="bold "+Math.min(13,(g.bw-10)/3.4)+"px monospace";
ctx.fillText(d.key,x,d.y+4);
}
}
drops=drops.filter(d=>!d.landed);
if(phase==="clear"){
fade+=dt/900;
ctx.fillStyle="rgba(14,17,22,"+Math.min(1,fade)+")";
ctx.fillRect(0,0,W,H);
ctx.fillStyle="rgba(223,231,240,"+Math.min(1,fade)+")";
ctx.font="bold "+Math.min(26,W/30)+"px monospace";
ctx.fillText("TABLE FULL — REHASHING…",W/2,H/2);
if(fade>=1.4)reset();
}
}
let last=performance.now();
function loop(now){
const dt=Math.min(50,now-last);
last=now;
if(phase==="run"){
timer+=dt;
if(timer>260&&drops.length<3){timer=0;spawn()}
}
draw(dt);
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
</script>
</body>
</html>
Claude Haiku 4.5frontier referenceOKMINIFIED
Show code
<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Hash Table</title><style>body{margin:0;display:flex;justify-content:center;align-items:center;height:100vh;background:#1a1a1a}canvas{background:#000;border:1px solid #444}#i{position:absolute;top:10px;left:10px;color:#0f0;font-size:12px;font-family:monospace}</style></head><body><div id="i"></div><canvas id="c"></canvas><script>const c=document.getElementById('c'),t=c.getContext('2d');c.width=800;c.height=400;const B=12,W=c.width/B,H=300,Y=50;let h=Array(B).fill(null).map(()=>[]),cnt=0,tot=0;const hash=k=>k%B,clr=l=>l===0?'#0f0':l<4?'#ff0':'#f00';function d(){t.fillStyle='#000';t.fillRect(0,0,c.width,c.height);for(let i=0;i<B;i++){const bx=i*W,col=clr(h[i].length);t.strokeStyle=col;t.lineWidth=2;t.strokeRect(bx+4,Y,W-8,H);const k=h[i];for(let j=0;j<k.length;j++){const by=Y+10+j*22;t.fillStyle=col;t.fillRect(bx+W/2-18,by,36,18);t.fillStyle='#000';t.font='11px monospace';t.textAlign='center';t.textBaseline='middle';t.fillText(k[j]%100,bx+W/2,by+9);if(j>0){t.strokeStyle=col;t.lineWidth=1;t.beginPath();t.moveTo(bx+W/2,by-5);t.lineTo(bx+W/2,by);t.stroke()}}}t.fillStyle='#0f0';t.font='14px monospace';t.fillText('Load: '+(tot/B).toFixed(2),10,20);}function u(){if(cnt<55){const k=Math.floor(Math.random()*9999);h[hash(k)].push(k);cnt++;tot++}else{h=Array(B).fill(null).map(()=>[]);cnt=0}}(function l(){u();d();requestAnimationFrame(l)})();</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
llama3.1:8b 74.2 sOK
qwen3-coder:30b 28.3 sOK
qwen3.5:9b 40.6 sOK
deepseek-r1:14b 44.0 sOK
qwen3:8b harness
qwen3:14b 28.6 sOK
mistral-small:24b 102.6 sOK
command-r:35b 259.2 sOK
qwq:32b 224.0 sOK
deepseek-r1:32b 73.0 sOK