// License: GPLv3 Copyright: 2026, Kovid Goyal, <kovid at kovidgoyal.net>

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
}
