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

  1. gpt-4o Zero compile
    ref.zero:1:1 IMP001: unknown package-local import 'std'
  2. gpt-4o-mini Zero compile
    ref.zero:3:8 PAR100: expected '{' before block
  3. gpt-5 Zero compile
    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:

  1. Scan. Walk left to right. Skip runs of spaces, then record each non-space run as a (start, length) pair. After this pass, nw is the word count.
  2. Emit. If nw == 0, write nothing and exit. Otherwise walk from nw - 1 down 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 is spaces 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 shape while i < n && bytes[i] == 32_u8 traps with SIGILL (exit 132) because the index expression is evaluated even when the guard is false. The fix is to split the loop into a while flag { if i >= n { flag = false } else { ... } } shape so the index is only evaluated under an explicit guard.
  • Word position arrays [500]u32 starts and [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.