// 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) } // encode_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: // 0. "a" // 1. "b" // 2. "c" // 3. "aa" // 4. "ab" // 5. "ac" // 6. "ba" // 7. "bb" // 8. "bc" // 9. "ca" // 10. "cb" // 11. "cc" // 12. "aaa" // ... // // Indices are 0-based on non-empty hints; index=0 the hint of length 1 with // the first character of the alphabet. func encode_hint(num int, alphabet string) (res string) { l := len(alphabet) for num >= 0 { mod := num % l res = string(alphabet[mod]) + res num /= l num -= 1 } return } func rune_to_index_map(alphabet string) *map[rune]int { runeToIndexMap := make(map[rune]int) for index, char := range alphabet { runeToIndexMap[char] = index } return &runeToIndexMap } // decode_hint converts a hint to its corresponding index as it would appear 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: // 0. "a" // 1. "b" // 2. "c" // 3. "aa" // 4. "ab" // ... // // hint is expected to be non-empty. func decode_hint(hint string, char_to_index *map[rune]int) (res int) { base := len(*char_to_index) for _, c := range hint { res = res*base + ((*char_to_index)[c] + 1) } return res - 1 }