agentlang-index · task easy
Reverse the order of words on a line
008-word-reverse. Read one line of printable ASCII (at most 1000 characters) from standard
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: Reverse the order of words on a line
Read one line of printable ASCII (at most 1000 characters) from standard
input. A **word** is a maximal run of non-space characters; the only
delimiter is the ASCII space (0x20). Multiple consecutive spaces, leading
spaces, and trailing spaces are allowed in the input but produce no
empty words.
Write the words in reverse order, separated by single spaces, followed by
exactly one newline. If the input contains no words at all (empty input or
all-space input), write nothing — no output and no newline. Exit with
status 0.
## Acceptance
- Stdin: one line, at most 1000 printable-ASCII characters, terminated by
`\n`.
- Stdout: reversed words single-space separated and `\n`-terminated, OR
empty if no words were present.
- Stderr: empty.
- Exit code: 0.
## Examples
| input | output |
| ---------------------- | ------------------ |
| `hello world` | `world hello\n` |
| `the quick brown fox` | `fox brown quick the\n` |
| `single` | `single\n` |
| (empty) | (empty) |
| ` ` | (empty) |
| ` multi spaces ` | `spaces multi\n` |
| `a b c` | `c b a\n` |
Note: all runs of consecutive spaces collapse, and leading/trailing
spaces are stripped. The output always uses exactly one space between
adjacent words.
## Language scaffold
{language_scaffold}
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 | parsing, strings, tokenization |
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 | Zero | TypeScript | Rust | Go | Python |
|---|---|---|---|---|---|
| gpt-4o | compile | ✓ | ✓ | ✓ | ✓ |
| gpt-4o-mini | compile | ✓ | ✓ | ✓ | ✓ |
| gpt-5 | compile | ✓ | ✓ | ✓ | ✓ |
Failure excerpts
3 of 15 attempts failed. Each card is one attempt, with the captured first line of the diagnostic.
-
ref.zero:1:1 IMP001: unknown package-local import 'std' -
ref.zero:3:8 PAR100: expected '{' before block -
ref.zero:1:1 IMP001: unknown package-local import 'std'
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 94 lines
// Reverse the order of words on a line, Zero 0.1.2 direct backend.
//
// argv[1] is the line (Zero 0.1.2 has no exposed stdin capability).
// All logic stays inside `pub fun main` to avoid Span/MutSpan parameter
// restrictions.
//
// Two-pass design: first pass scans the input and records each word's
// (start, length) into two parallel [500]u32 arrays. Second pass walks
// from last word to first, appending bytes to an output buffer with
// single-space separators and a trailing newline. If zero words were
// found, nothing is written.
//
// Zero's `&&` is not assumed to short-circuit, so the inner loops are
// split into a `while true` with an explicit early-exit setting the
// loop index to n.
pub fun main(world: World) -> Void raises {
let line_opt = std.args.get(1)
let mut bytes: Span<u8> = std.mem.span("")
if line_opt.has {
bytes = std.mem.span(line_opt.value)
}
let n: usize = std.mem.len(bytes)
let mut starts: [500]u32 = [0_u32; 500]
let mut lens: [500]u32 = [0_u32; 500]
let mut nw: usize = 0
let mut i: usize = 0
while i < n {
// Skip spaces. Inner loop avoids relying on && short-circuit.
let mut skipping: Bool = true
while skipping {
if i >= n {
skipping = false
} else {
if bytes[i] == 32_u8 {
i = i + 1
} else {
skipping = false
}
}
}
if i < n {
let start: usize = i
let mut scanning: Bool = true
while scanning {
if i >= n {
scanning = false
} else {
if bytes[i] != 32_u8 {
i = i + 1
} else {
scanning = false
}
}
}
let len: usize = i - start
starts[nw] = start as u32
lens[nw] = len as u32
nw = nw + 1
}
}
if nw == 0 {
return
}
let mut out_buf: [1024]u8 = [0_u8; 1024]
let mut written: usize = 0
let mut w: usize = nw
while w > 0 {
w = w - 1
if written > 0 {
out_buf[written] = 32_u8
written = written + 1
}
let s: usize = starts[w] as usize
let l: usize = lens[w] as usize
let mut k: usize = 0
while k < l {
out_buf[written] = bytes[s + k]
written = written + 1
k = k + 1
}
}
out_buf[written] = 10_u8
written = written + 1
let out: Span<u8> = out_buf[0..written]
check world.out.write(out)
return
}
TypeScript 15 lines
// Reverse the order of words on a line, TypeScript reference.
import { readFileSync } from "node:fs";
function main(): void {
let line = readFileSync(0, "utf8");
if (line.endsWith("\n")) line = line.slice(0, -1);
const words = line.split(" ").filter((w) => w.length > 0);
if (words.length === 0) return;
words.reverse();
process.stdout.write(words.join(" ") + "\n");
}
main();
Rust 27 lines
// Reverse the order of words on a line, Rust reference.
use std::io::{self, Read, Write};
fn main() {
let mut input = String::new();
io::stdin().read_to_string(&mut input).unwrap();
if input.ends_with('\n') {
input.pop();
}
let words: Vec<&str> = input.split(' ').filter(|w| !w.is_empty()).collect();
if words.is_empty() {
return;
}
let mut out = String::with_capacity(input.len() + 1);
for (i, w) in words.iter().rev().enumerate() {
if i > 0 {
out.push(' ');
}
out.push_str(w);
}
out.push('\n');
let stdout = io::stdout();
let mut h = stdout.lock();
h.write_all(out.as_bytes()).unwrap();
}
Go 35 lines
// Reverse the order of words on a line, Go reference.
package main
import (
"bufio"
"os"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
line, _ := reader.ReadString('\n')
line = strings.TrimRight(line, "\n")
parts := strings.Split(line, " ")
words := parts[:0]
for _, w := range parts {
if w != "" {
words = append(words, w)
}
}
if len(words) == 0 {
return
}
var b strings.Builder
for i := len(words) - 1; i >= 0; i-- {
if i != len(words)-1 {
b.WriteByte(' ')
}
b.WriteString(words[i])
}
b.WriteByte('\n')
os.Stdout.WriteString(b.String())
}
Python 19 lines
"""Reverse the order of words on a line, Python reference."""
import sys
def main() -> None:
line = sys.stdin.readline()
if line.endswith("\n"):
line = line[:-1]
words = line.split(" ")
words = [w for w in words if w != ""]
if not words:
return
words.reverse()
sys.stdout.write(" ".join(words) + "\n")
if __name__ == "__main__":
main()
Design notes
Algorithm, failure modes, cross-language parity, and where Zero needed a workaround. From corpus/008-word-reverse/notes.md.
Algorithm
Two-pass over the input bytes:
- Scan. Walk left to right. Skip runs of spaces, then record each
non-space run as a
(start, length)pair. After this pass,nwis the word count. - Emit. If
nw == 0, write nothing and exit. Otherwise walk fromnw - 1down to 0, copying each word's bytes to the output buffer and inserting a single space between adjacent words. Append a single\n.
Edge cases
- Empty input (
n == 0) → no words → no output. - All spaces (e.g.
" ") → no words → no output. - Single word (
"single") → one word → output is the word plus\n. - Multiple internal/leading/trailing spaces (
" multi spaces ") → two words → output isspaces multi\n.
The "no output for zero words" rule is the trap. Models often emit a
bare \n for empty input, which fails the byte-exact check.
Zero-specific notes
- argv[1] is the line; an absent argv falls back to an empty span.
&&is NOT short-circuit in the Zero 0.1.2 direct backend. The natural shapewhile i < n && bytes[i] == 32_u8traps with SIGILL (exit 132) because the index expression is evaluated even when the guard is false. The fix is to split the loop into awhile flag { if i >= n { flag = false } else { ... } }shape so the index is only evaluated under an explicit guard.- Word position arrays
[500]u32 startsand[500]u32 lens(500 is the upper bound on words for a 1000-char input of alternating single-char + space). - Output buffer
[1024]u8. Worst case: same total length as input plus one trailing newline; the per-word write loop never overflows because the words' total byte count is<= n.
Cross-implementation parity
All five references produce byte-exact output on every case in both stdin (TS/Rust/Go/Python) and argv (Zero) input modes.
Cost
| Model | Prompt tokens | Completion tokens | API ms |
|---|---|---|---|
| gpt-4o | 3,020 | 645 | 7,727 |
| gpt-4o-mini | 3,020 | 623 | 10,937 |
| gpt-5 | 3,015 | 10,321 | 114,270 |
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 . Back to the leaderboard and methodology.