Numbers to Words
Level: Beginner 15–30 minConcepts: Strings
Solutions: C# | TypeScript | Python
There are varying opinions amongst writers as to when one should spell out a number vs. using figures. However there are a few generally agreed upon rules for doing so.
There are 2 of them we will follow for this kata:
- Numbers beginning a sentence should be spelt out.
- Hyphenate all compound numbers from twenty-one through ninety-nine
Write an implementation of these rules for numbers starting a sentence. It should take an input of figures and return the number spelt out. Assume all the numbers given start sentences and your code will be used like a spell checker for grammar issues related to numbers.
Only worry about up numbers up to 4 digits long. Assume all numbers are positive.
Examples
| 1 digit | 2 digits | 3 digits | 4 digits |
|---|---|---|---|
| 0 = zero | 10 = ten | 100 = one hundred | 2000 = two thousand |
| 5 = five | 21 = twenty-one | 303 = three hundred three | 3466 = three thousand four hundred sixty-six |
| 8 = eight | 77 = seventy-seven | 555 = five hundred fifty-five | 2400 = two thousand four hundred |
Hint
Solve for 1 digit, then move to 2 digits and so on.
Bonus
The simplest way to express large numbers is usually best. Instead of 5300 being equal to five thousand three hundred it should return fifty-three hundred. This new rule only applies to 4 digit numbers.
Reference Walkthrough
Reference implementations in C#, TypeScript, and Python live at tddbuddy-reference-katas/numbers-to-words. Fifteen scenarios cover one-, two-, three-, and four-digit cases — teens that are a single word (nineteen), hyphenated compounds from twenty-one through ninety-nine, hundreds that name the leading one (one hundred), and the “no ‘and’” join between hundreds and the remainder (three hundred three, not three hundred and three). The API in all three languages is the same shape: toWords(n) for TypeScript, ToWords(int n) for C#, to_words(n) for Python — each returning the English-words spelling for 0..9999. The bonus “fifty-three hundred” four-digit shorthand is out of scope; the reference uses the canonical "five thousand three hundred" form.
- C# (.NET 8, xUnit, FluentAssertions 6.12.0) — walkthrough
- TypeScript (Node 20, Vitest 1.6, TS 5 strict) — walkthrough
- Python (3.11, pytest) — walkthrough
This kata ships in Agent Full-Bake mode at high gear (F1 tier): a pure integer-to-string transform small enough to land as one commit per language, with a brief walkthrough noting there are no builders because the input (an int) and output (a string) are the domain. Two lookup tables — ones for 0..19 (so teens are one word) and tens for twenty..ninety — plus a thousands/hundreds/sub-hundred split carry the whole grammar. See the repo’s Gears section for when high gear is the right call.
Related reading
- Katas Are Rehearsal, Not Performance
You don't practice TDD on production code. You practice on katas and bring the muscle memory to production. The gap between knowing TDD and doing TDD is reps. - The Contract Test Is the Only Witness the Agent Cannot Author
A test the agent wrote against code the same agent wrote shares the agent's blind spot: a misunderstanding in the implementation becomes a matching misunderstanding in the test, the bar goes green, and the bug ships certified. Consumer-driven contract tests are the only category where a second team publishes the assertion the first team has to satisfy. That separation of authorship is exactly what tamper-resistant test design demanded, applied at the integration seam. - Cohesion Is the Coverage of the Agent Era
Agent-generated codebases pass every structural-modularity metric while fragmenting the domain concept the team was trying to encode. Coverage measured whether a line ran. Mutation score measured whether an assertion pinned behavior. Cohesion is the next axis, and it measures whether the codebase's concepts are traversable end-to-end.