Text Justification

Level: Advanced 60–90 min

Concepts: StringsAlgorithms

Solutions: C# | TypeScript | Python


Create a program that justifies text to fit a specified width.

Requirements

  1. Implement text justification rules:
    • Break text into lines of specified width
    • Distribute spaces evenly between words
    • Left-align the last line of text
    • Handle single words per line
  2. Handle edge cases:
    • Empty input
    • Input shorter than line width
    • Words longer than line width
    • Multiple consecutive spaces
  3. Return appropriate results:
    • Justified text as an array of strings
    • Error message for invalid inputs

Test Cases

InputWidthExpected OutputNotes
”This is a test”16[“This is a”, “test”]Even space distribution
”This is a test”14[“This is a”, “test”]Uneven space distribution
”This is a test”20[“This is a test”]No justification needed
”This is a very long word”10[“This is a”, “very long”, “word”]Multiple line breaks
”Word”10[“Word”]Single word
”This is a test”16[“This is a”, “test”]Handle multiple spaces

Edge Cases to Consider

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

Tips

  • Start with simple cases (no justification needed)
  • Add basic line breaking next
  • Then implement space distribution
  • Finally add special case handling
  • Consider using a helper method for space distribution

Reference Walkthrough

Reference implementations in C#, TypeScript, and Python live at tddbuddy-reference-katas/text-justification. This is an F1 kata — ten scenarios covering empty and whitespace-only input, single-word lines, multi-line greedy packing, uneven and even space distribution, collapsing consecutive whitespace, single-word right-padding, and oversize words — shared across all three languages, each a single pure function justify(text, width).

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 accumulates words, distributes padding evenly across the gaps (remainder left-heavy, the LeetCode-68 convention), right-pads single-word non-last lines, lets oversize words overflow rather than splitting them mid-word, and emits the last line left-aligned with single spaces — not right-padded, matching the typeset convention that the closing line of a paragraph sits flush-left. See the repo’s Gears section for when high gear is the right call.