Word Wrap

Level: Intermediate 30–60 min

Concepts: Strings

Solutions: C# | TypeScript | Python


Create a program that wraps text at a specified column width.

Requirements

  1. Implement text wrapping rules:
    • Break text at word boundaries when possible
    • Break words only if they exceed the column width
    • Preserve whitespace between words
    • Handle multiple spaces and tabs
  2. Handle edge cases:
    • Empty input
    • Input shorter than column width
    • Words longer than column width
    • Multiple consecutive spaces
  3. Return appropriate results:
    • Wrapped text as a string
    • Error message for invalid inputs

Test Cases

InputColumn WidthExpected OutputNotes
”Hello”5”Hello”No wrapping needed
”Hello World”5”Hello\nWorld”Break at word boundary
”Hello World”7”Hello\nWorld”Break at word boundary
”Hello World”20”Hello World”No wrapping needed
”Supercalifragilisticexpialidocious”10”Supercalif\nragilisti\ncexpiali\ndocious”Break long word
”Hello World”5”Hello\nWorld”Handle multiple spaces

Edge Cases to Consider

  • Empty string
  • Null input
  • Zero or negative column width
  • Very long words
  • Multiple consecutive spaces or tabs
  • Text with line breaks

Tips

  • Start with simple cases (no wrapping needed)
  • Add word boundary breaking next
  • Then handle long words
  • Finally add whitespace handling
  • Consider using regular expressions for word boundaries

Reference Walkthrough

Reference implementations in C#, TypeScript, and Python live at tddbuddy-reference-katas/word-wrap. This is an F1 kata — twelve scenarios covering empty and whitespace-only input, single-word lines, greedy word-boundary packing, oversize-word hard splitting, oversize-remainder joining with the next word, and whitespace collapsing — shared across all three languages, each a single pure function wrap(text, width) returning a \n-joined string.

This kata ships in Agent Full-Bake mode at high gear: the rules land as one commit per language, with a brief walkthrough noting there are no builders because the inputs and outputs are the domain. A greedy line-packer tokenizes on runs of whitespace, accumulates words until the next word would push the line past width, splits any oversize word hard at the width-th character before letting its remainder begin the next line (where following words may still join it if they fit), and joins the resulting lines with \n — matching the classic Kent Beck kata shape that returns a single string rather than a list. See the repo’s Gears section for when high gear is the right call.


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