Three Input Parsing Mistakes
Day 6's "cephalopod math worksheet" taught me three painful lessons about input parsing. All from the same puzzle.
Mistake 1: Assuming Uniformity From Test Input
Treating test input as the specification instead of one example.
My Gloomy Reality
The test input looked beautifully uniform:
123 328 51 64 45 64 387 23 6 98 215 314 * + * +
Four columns. Each exactly 4 characters wide. My brain immediately latched onto this pattern: "Ah, columns are fixed-width! I'll just slice the string every 4 characters."
Then I ran it on the real input:
79 338 2 956 3311 92 29 93 4 878 76 988 3 1 76 8 758 ... 84 921 4 2238 3478 849 36 65 1 359 57 673 6333 5 55 62 846 ... 562 5154 8 2186 1 769 41 59 49 371 77 927 5961 15 45 798 961 ... * + + + + * + * * + + * + + * * + ...
Variable-width columns. Some are 2 characters, some are 4, some are 5. My hardcoded "slice every 4 chars" approach was completely wrong.
Mistake 2: Line-Wrapping Illusion
Your terminal wraps long lines. 5 rows can look like 50+.
My Gloomy Reality
When I first opened the real input, my terminal showed what looked like dozens of rows of numbers. I started panicking—"wait, the problem said there's only one operator row at the bottom, but I see numbers everywhere!"
Turns out the input was just 5 rows. But each row was ~1800 characters wide, and my terminal was wrapping them into visual chaos.
I wasted time trying to understand a "complex multi-row structure" that didn't exist.
Mistake 3: Premature Input Transformation
Don't TrimSpace, ToLower, or transform input until you understand WHY.
My Gloomy Reality
My first instinct was to clean up the input:
// ❌ "Let me just clean this up..." line = strings.TrimSpace(line)
This destroyed the column alignment. The leading spaces in 79 338 2 ... weren't noise—they were data. They indicated that position 0 was part of a column, and the number 79 was right-aligned within it.
By trimming, I shifted all the numbers left and broke the positional relationship with the operator row.
The Insight
All three mistakes had the same root cause: I was imposing structure instead of reading structure.
The breakthrough came when I stopped looking at the numbers and started looking at the operators:
* + + + + * + * * + ...
The operators weren't evenly spaced! Each operator marks the start of its column, and the spaces after it define that column's width. The operator row is the column specification.
Once I understood that, everything clicked:
- Don't assume column widths—discover them from the operator positions
- Don't trust what your terminal shows—measure with
wc -l - Don't "clean" data until you understand what's noise vs signal
The Fix
First, understand the input before touching it:
wc -l input # 5 rows, not 50 head -1 input | wc -c # 1847 chars wide less -S input # view without wrapping
Then, discover structure from the data itself:
// ❌ Before: hardcoded assumptions columnWidth := 4 // "every column is 4 chars, right?" line = strings.TrimSpace(line) // "whitespace is noise, right?" // ✅ After: discover columns from the operator row func findColumns(opRow string) []Column { var cols []Column i := 0 for i < len(opRow) { if opRow[i] == ' ' { i++ continue } op := rune(opRow[i]) start := i i++ for i < len(opRow) && opRow[i] == ' ' { i++ } cols = append(cols, Column{Op: op, Start: start, End: i}) } return cols }
Lessons Learned
1. Test input is ONE example, not THE specification. The test exists to show the rules, not the scale or edge cases.
2. Always wc -l before you trust your eyes.
Your terminal lies. Line-wrapping creates phantom structure.
3. Parse raw first, transform only what you KNOW needs transforming.
Whitespace might be data. Don't TrimSpace until you're sure it's noise.
4. Look for structure in the data, don't impose structure on the data. The operator row told me exactly where the columns were—I just wasn't listening.
Original puzzle: Advent of Code 2025 Day 6