agentlang-index · task easy

Per-byte frequency table sorted by byte value

010-byte-frequency. Read all bytes from standard input.

Prompt

This is the natural-language brief given to every model, verbatim. The harness prefixes a language-specific calling-convention block and suffixes a "return only the source code" instruction. Nothing else.

# Task 010 — byte-frequency

## Problem

Read all bytes from standard input. Count how often each byte value
(0 through 255) appears. For every byte value with a non-zero count,
write one line of the form `<byte_decimal> <count>\n` to standard
output. The lines must be in ascending byte-value order. Exit with
status 0.

## Output format

- Each line is `<byte_decimal>` (the byte value 0..255 rendered in
  decimal, no padding), one ASCII space (0x20), `<count>` (the
  occurrence count in decimal, no padding), one newline (0x0A).
- No header, no trailing extra newline beyond the per-record one.

## Edge cases

- Empty input → empty output (no header, no `0\n`, nothing).
- Single byte input → one line.
- Repeated identical bytes → one line with the matching count.
- High-bit bytes (0x80..0xFF) appear with their decimal value
  (128..255) just like ASCII bytes.

## Acceptance

The stdout produced by your program must match the expected bytes
exactly for every test case. Stderr must be empty and the process
must exit 0.

## Input convention

- **stdin** (TypeScript, Rust, Go, Python): read all bytes until EOF.
- **argv[1]** (Zero 0.1.2 has no exposed stdin capability): read the
  bytes from the first command-line argument.

## Token budget

1600 tokens.

Acceptance

A task counts as passed only when every public and hidden test case agrees on these fields. No fuzzy matching, no "off by one trailing newline is fine."

stdout (byte-exact, per case) true
stderr (exact bytes) ""
exit code 0
wall time max (ms) 5000
tags io, counting, sorting, multi-record-output

Results

Each cell is one attempt. Pass means stdout matched byte-exact on every test case, stderr empty, exit zero. Hover a failure to see the captured first line of the diagnostic.

Model ZeroTypeScriptRustGoPython
gpt-4o compile
gpt-4o-mini compile wrong output wrong output
gpt-5 compile
opus compile
sonnet wrong output

Failure excerpts

7 of 25 attempts failed. Each card is one attempt, with the captured first line of the diagnostic.

  1. gpt-4o Zero compile
    ref.zero:6:8 PAR100: expected '{' before block
  2. gpt-4o-mini Zero compile
    ref.zero:1:15 PAR100: expected expression
  3. gpt-4o-mini Rust wrong output
    (no diagnostic captured)
  4. gpt-4o-mini Python wrong output
    (no diagnostic captured)
  5. gpt-5 Zero compile
    ref.zero:1:1 IMP001: unknown package-local import 'std'
  6. opus Zero compile
    ref.zero:1:8 PAR100: expected '{' before block
  7. sonnet Zero wrong output
    (no diagnostic captured)

Reference implementations

The hand-written reference each language ships with. Every reference passes the same public and hidden test suite under the pinned toolchain before any model touches the task.

Click a language to expand

Zero n/a

No reference implementation in this language.

TypeScript 22 lines
// Per-byte frequency table, TypeScript reference.

import { readFileSync } from "node:fs";

function main(): void {
  const data = readFileSync(0);
  const counts = new Uint32Array(256);
  for (let i = 0; i < data.length; i++) {
    counts[data[i]]++;
  }
  const out: string[] = [];
  for (let b = 0; b < 256; b++) {
    const c = counts[b];
    if (c > 0) {
      out.push(`${b} ${c}\n`);
    }
  }
  process.stdout.write(out.join(""));
}

main();
Rust 20 lines
// Per-byte frequency table, Rust reference.

use std::io::{self, Read, Write};

fn main() {
    let mut data = Vec::new();
    io::stdin().read_to_end(&mut data).expect("read stdin");
    let mut counts = [0u32; 256];
    for &b in &data {
        counts[b as usize] += 1;
    }
    let stdout = io::stdout();
    let mut stdout = stdout.lock();
    for (b, &c) in counts.iter().enumerate() {
        if c > 0 {
            writeln!(stdout, "{} {}", b, c).expect("write stdout");
        }
    }
}
Go 29 lines
// Per-byte frequency table, Go reference.

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
)

func main() {
	data, err := io.ReadAll(os.Stdin)
	if err != nil {
		os.Exit(1)
	}
	var counts [256]uint32
	for _, b := range data {
		counts[b]++
	}
	w := bufio.NewWriter(os.Stdout)
	defer w.Flush()
	for b := 0; b < 256; b++ {
		if counts[b] > 0 {
			fmt.Fprintf(w, "%d %d\n", b, counts[b])
		}
	}
}
Python 22 lines
#!/usr/bin/env python3
"""Per-byte frequency table, Python reference."""

import sys


def main() -> None:
    data = sys.stdin.buffer.read()
    counts = [0] * 256
    for b in data:
        counts[b] += 1
    out_parts = []
    for b in range(256):
        c = counts[b]
        if c > 0:
            out_parts.append(f"{b} {c}\n")
    sys.stdout.write("".join(out_parts))


if __name__ == "__main__":
    main()

Design notes

Algorithm, failure modes, cross-language parity, and where Zero needed a workaround. From corpus/010-byte-frequency/notes.md.

Algorithm

Two phases:

  1. Count. Walk every input byte, incrementing counts[byte] in a length-256 table. counts is u32 everywhere; the spec caps input at 100000 bytes, so the max single-byte count is 100000 (well inside u32 range).
  2. Emit. Walk byte values 0..255 in ascending order; for every entry with a non-zero count, emit <byte_decimal> <count>\n.

The byte value itself is rendered in decimal (range 0..255 → 1..3 digits), so a 4-byte temp buffer is sufficient. The count renderer uses a 16-byte temp buffer (max u32 = 4294967295 = 10 digits).

Edge cases

  • Empty input → no bytes counted → emit nothing.
  • Single byte → one line.
  • All identical bytes → one line.
  • High-bit bytes (0x80..0xFF, decimal 128..255) appear with their decimal values; no special handling.

Zero-specific notes

  • argv[1] is the input bytes; an absent argv falls back to an empty span. Embedded tabs, newlines, and high-bit bytes in argv[1] pass through unchanged.
  • Decimal rendering is inlined twice (once for the byte value with a 4-byte temp, once for the count with a 16-byte temp) because Zero 0.1.2 does not support Span<u8>/MutSpan<u8> as function parameters; the function-extraction shape is unavailable, so the buffer-write code lives inline.
  • Output buffer sized at [4096]u8: the worst case is all 256 byte values present, each line "<3 digits> <10 digits>\n" = 15 bytes, total 3840 bytes. The spec's 100000-byte input cap caps the max count at 6 digits (100000), so realistic worst case is 11 bytes per line × 256 = 2816, well under 4096.
  • Uses the small-divisor u32 divmod renderer (% 10_u32 / / 10_u32) which dodges the 2^32-divisor narrowing-cast SIGFPE.

Cross-implementation parity

All five references walk the input byte-by-byte and emit one record per non-zero byte value in ascending byte order. TypeScript uses Uint32Array(256) for the counts table; Rust uses [0u32; 256]; Go uses [256]uint32; Python uses a 256-element list. The output format is the same across all of them: <byte_decimal> <count>\n per record, no header, no trailing extra newline.


Cost

Model Prompt tokens Completion tokens API ms
gpt-4o 2,875 872 10,021
gpt-4o-mini 2,875 612 11,239
gpt-5 2,870 12,779 128,318
opus 14 875 68,854
sonnet 14 4,683 109,391

Tokens and API ms are summed across the five languages this model attempted for this task.


Compare

Model deep-dives: gpt-4o · gpt-4o-mini · gpt-5 · opus · sonnet . Back to the leaderboard and methodology.