Diamond Kata

Level: Intermediate 30–60 min

Concepts: AlgorithmsStringsIncremental Design

Solutions: C# | TypeScript | Python


Given a letter, generate a diamond shape that starts with A, widens to the given letter, then narrows back to A.

Requirements

Given A, return:

A

Given B, return:

 A
B B
 A

Given C, return:

  A
 B B
C   C
 B B
  A

Given D, return:

   A
  B B
 C   C
D     D
 C   C
  B B
   A

Rules

  1. The first and last rows contain a single A
  2. All rows except the first and last have exactly two identical letters
  3. The diamond is vertically and horizontally symmetric
  4. The width equals the height
  5. The top half is a mirror of the bottom half
  6. Leading spaces align the letters into a diamond shape
  7. Inner spaces between the two letters increase by 2 for each row from the top

Test Cases

InputHeightWidthFirst RowMiddle Row
A11AA
B33·AB·B
C55··AC···C
E99····AE·······E

(Dots represent spaces for clarity)

Bonus

  • Accept lowercase input and normalize to uppercase
  • Add a hollow option that only prints the border characters and fills the interior with spaces
  • Validate input is a single letter A-Z

Hint

Don’t try to build the whole diamond at once. Focus on generating a single row first — given a target letter and a current letter, produce the correct row with the right leading spaces and inner spaces. Once a single row works, the diamond is just a sequence of rows mirrored vertically.

Reference Walkthrough

Reference implementations in C#, TypeScript, and Python live at tddbuddy-reference-katas/diamond. This is an F1 kata — 10 shared scenarios covering the shape from A (a single letter) through Z (a full 51-row diamond), lowercase normalization, top/bottom-mirror and no-trailing-whitespace invariants, and rejection of non-AZ input with the byte-identical message letter must be a single A-Z character.

This kata ships in Agent Full-Bake mode at high gear: each row computes its offset from the diamond’s vertical midpoint (min(r, 2n - r)) and composes leading spaces + letter + 2 * offset - 1 inner spaces + letter; the top/bottom symmetry falls out of the offset formula rather than from explicit mirroring. One commit per language, with a brief walkthrough noting there are no builders because the algorithm’s inputs and outputs are the domain — no aggregates to construct, no value types to introduce, no collaborators to inject. Python names the function print_diamond to avoid shadowing the built-in print. 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.
  • Test Deletion Is a Privileged Operation
    The cheapest way for an agent to make a failing test pass is to delete it. That is logical for the agent and catastrophic for the codebase. Tests are append-only by default. Deletion needs a human author, a separate commit, and a separate review.
  • The Instruction File Is Not the Discipline
    Teams that want their agent to do TDD reach for the instruction file. The TDAD paper measured this directly: adding a 'do TDD' instruction raised regressions by nearly two-thirds. Contextual test discovery cut them by seventy percent. The instruction is theatre. The codebase's test surface is the discipline.