import ( "fmt" "math/rand" "sort" ) // Return leftmost offset where val can be inserted in sl while // maintaining sorted orter. Assumes sl is sorted. func bisectLeftInt(sl []int, val int) int { return sort.Search(len(sl), func(i int) bool {return sl[i] >= val}) } // Same but for rightmost offset func bisectRightInt(sl []int, val int) int { return sort.Search(len(sl), func(i int) bool {return sl[i] > val}) } // Same as bisectLeftInt but where val and sl contain strings func bisectLeftStr(sl []string, val string) int { return sort.Search(len(sl), func(i int) bool {return sl[i] >= val}) } // Same but for rightmost offset func bisectRightStr(sl []string, val string) int { return sort.Search(len(sl), func(i int) bool {return sl[i] > val}) } a := []int{1, 2, 3, 3, 3, 4, 5} bisectLeftInt(a, 3) bisectRightInt(a, 3) a = []int{2, 4, 6, 8, 10} bisectLeftInt(a, 5) bisectRightInt(a, 5) // Make a list of pseudo-random integers in [1, 99] rand.Seed(77) ls := make([]int, 30) for i := range ls { ls[i] = rand.Intn(100) + 1 } ls sort.Ints(ls) ls // The number 30 is not in the sorted list // If it were, where would it go? val := 30 insPt := bisectLeftInt(ls, val) insPt // Insert it ls = append(ls, 0) copy(ls[insPt+1:], ls[insPt:]) ls[insPt] = val ls // 62 appears multiple times st := bisectLeftInt(ls, 62) en := bisectRightInt(ls, 62) st en ls[st:en] // Of course, there also exists a total ordering over strings // (lexicographical ordering), so we can do all the same things // with strings strls := []string{"a", "awkward", "awl", "awls", "axe", "axes", "bee"} st = bisectLeftStr(strls, "awl") en = bisectRightStr(strls, "awl") st en // Say we want to get the range of elements that have some prefix, // e.g. 'aw' and say that 'z' is the lexicographically greatest // character in the alphabet. st, en = bisectLeftStr(strls, "aw"), bisectLeftStr(strls, "ax") st en strls[st:en] // If we can do this for any sorted list of strings, we can do it for // a sorted list of suffixes t := "abaaba$" suffixes := []string{t, t[1:], t[2:], t[3:], t[4:], t[5:], t[6:]} sort.Strings(suffixes) suffixes // Search for suffixes starting with aba st = bisectLeftStr(suffixes, "aba") en = bisectLeftStr(suffixes, "abb") st en