String Calculator
Level: Intermediate 30–60 minConcepts: Strings
Solutions: C# | TypeScript | Python
Create a simple String calculator with a method that takes a string of numbers and returns their sum.
Requirements
- The method can take 0, 1 or 2 numbers, and will return their sum (for an empty string it will return 0).
- Allow the Add method to handle an unknown amount of numbers.
- Allow the Add method to handle new lines between numbers (instead of commas).
- Support different delimiters by starting the string with ”//[delimiter]\n[numbers…]”.
- Calling Add with a negative number will throw an exception “negatives not allowed” - and the negative that was passed.
- Numbers bigger than 1000 should be ignored.
- Delimiters can be of any length with the following format: ”//[delimiter]\n”.
- Allow multiple delimiters like this: ”//[delim1][delim2]\n”.
- Make sure you can also handle multiple delimiters with length longer than one char.
Test Cases
| Input | Result | Notes |
|---|---|---|
| "" | 0 | Empty string returns 0 |
| ”1” | 1 | Single number returns itself |
| ”1,2” | 3 | Two numbers separated by comma |
| ”1,2,3” | 6 | Multiple numbers separated by comma |
| ”1\n2,3” | 6 | New line as delimiter |
| ”//;\n1;2” | 3 | Custom delimiter |
| ”-1,2” | Exception: “negatives not allowed: -1” | Negative numbers not allowed |
| ”2,1001” | 2 | Numbers > 1000 are ignored |
| ”//[]\n12***3” | 6 | Delimiter of any length |
| ”//[][%]\n12%3” | 6 | Multiple delimiters |
Tips
- Start with the simplest test case first (empty string)
- Add one requirement at a time
- Refactor after each passing test
- Consider edge cases like invalid input
- Think about how to handle the delimiter parsing
Reference Walkthrough
Full C#, TypeScript, and Python implementations live at tddbuddy-reference-katas/string-calculator. This is a Pedagogy mode kata: the commit log is the teaching, stepping through the TDD cycle commit-by-commit — red, green, refactor, reflect — with the gear visibly shifting from low (fake-it, triangulate) to middle (one scenario per cycle) to high (obvious implementation; later scenarios pass on arrival).
- C# (.NET 8, xUnit, FluentAssertions) — walkthrough
- TypeScript (Node 20, Vitest, strict types) — walkthrough
- Python (3.11, pytest) — walkthrough
Unlike Bank Account (which ships in middle gear, one commit per language), String Calculator ships as the TDD arc itself: roughly twenty commits per language, each labeled with its cycle phase and gear. See the repo’s Gears section for why the gear shift is the real teaching point.
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. - 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. - Refactor Was Always Where Compounding Lived
Red and green were the visible two thirds of TDD. Refactor was the optional polish. Codebases that compound did the refactor pass; codebases that accrete did not. Agents skip refactor by default because it has no green-bar reward, and a year of skipped refactors is how a codebase loses its shape.