// License: GPLv3 Copyright: 2026, Kovid Goyal, package hints // hints_to_skip calculates how many hints to skip based on the given n and // alphabet size so that the next n hints generated by expanding the prefix tree // of an alphabet of size alphabetSize will be prefix-free. // // The result is 1-based, meaning that the first hint to be skipped is the first // non-empty hint. // // For example, if alphabet was "abc" and n was 5, the first non-empty hints // from that alphabet would be: "a", "b", "c", "aa", "ab", "ac", ... // the result of hints_to_skip would be 1, and this would mean that if you skip // "a" from the list above, the next 5 hints are prefix-free: // "b", "c", "aa", "ab", "ac". // // See issue #10195 for an informal proof on why this function works. func hints_to_skip(n int, alphabetSize int) int { if n < 2 { n = 2 } return (n - 2) / (alphabetSize - 1) } // generate_prefix_free_hint generates the hint corresponding to the given index // in the breadth-first traversal of the prefix tree generated by the given // alphabet. // // For example, given the alphabet "abc", the hints would be generated in // the following order: // 1. "a" // 2. "b" // 3. "c" // 4. "aa" // 5. "ab" // 6. "ac" // 7. "ba" // 8. "bb" // 9. "bc" // 10. "ca" // 11. "cb" // 12. "cc" // 13. "aaa" // ... // // Indices are 1-based on non-empty hints; index=0 returns an empty (invalid) // hint. func generate_prefix_free_hint(index int, alphabet string) string { l := len(alphabet) hint := "" index -= 1 for index >= 0 { mod := index % l char := string(alphabet[mod]) index /= l hint = char + hint index -= 1 } return hint }