Skip to content

Fix Alphabet enumerator producing non-letters for large lists#715

Open
winklemad wants to merge 1 commit into
charmbracelet:mainfrom
winklemad:fix-alphabet-enumerator-base26
Open

Fix Alphabet enumerator producing non-letters for large lists#715
winklemad wants to merge 1 commit into
charmbracelet:mainfrom
winklemad:fix-alphabet-enumerator-base26

Conversation

@winklemad

Copy link
Copy Markdown

Description

list.Alphabet implements spreadsheet-style bijective base-26 labels (A..Z, AA..ZZ, AAA..), but used a naive per-digit div/mod formula that ignores the "no zero digit" borrow. Past index 1352 the middle digit underflows to '@' ('A'-1) when (i/26)%26 == 0, and the leading digit overflows past 'Z' to '['; the 4+ letter range isn't handled at all. So a long list renders non-letter enumerators:

list.Alphabet(nil, 1352)  // "B@A."  (want "AZA.")
list.Alphabet(nil, 18277) // "[@Z."  (want "ZZZ.")
list.Alphabet(nil, 18278) // "[AA."  (want "AAAA.")

First corruption is at index 1352 (the 1353rd item); a broad check finds 156 wrong outputs in 0..4999. This is reachable through the public API (list.New(...).Enumerator(list.Alphabet)).

Fix

Replace the hard-coded 1/2/3-letter branches with a correct bijective base-26 conversion (decrement-before-divide borrow, digits built least-significant-first then reversed). It's behavior-preserving for the previously-correct range (0..1351, which the existing tests cover) and correct for all indices beyond.

Test

Added regression rows to the existing TestBullet table (1352→AZA, 1377→AZZ, 1378→BAA, 18277→ZZZ, 18278→AAAA), which fail on the old code and pass with the fix. go test ./... is green; gofmt/go vet clean.

list.Alphabet used a naive per-digit div/mod formula that ignored the
"no zero digit" borrow of bijective base-26 (spreadsheet-style A..Z,
AA..ZZ, AAA..). Past index 1352 the middle digit underflowed to '@'
('A'-1) and the leading digit overflowed past 'Z' to '[', and the 4+
letter range was not handled at all, so large lists rendered enumerators
like "B@A." instead of "AZA.".

Replace the hard-coded branches with a correct bijective base-26
conversion (decrement-before-divide borrow, digits built least-
significant first then reversed). Behavior-preserving for the
previously-correct range and correct for all indices thereafter.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant