Function nekolib::algo::bisect

source ·
pub fn bisect(_: Range<usize>, pred: impl FnMut(usize) -> bool) -> usize
Expand description

二分探索で境界を探す。

pred(i)false となる最小の i を返す。 ただし start..end 内の全ての itrue の場合は end を返す。

Requirements

pred(i)false となる i が存在するとき、i < j なる全ての jpred(j)false となる。

Complexity

区間の長さを $n$ として、高々 $\lceil\log_2(n+1)\rceil$ 回の pred の呼び出しを行う。

Suggestions

範囲の型を PrimInt なり Ord なりにしたい気もする。区間長と中間値の取得をよしなにできると助かる。

Examples

use nekolib::algo::bisect;

let floor_sqrt = |i| if i <= 1 { i } else {
    bisect(0..i, |j| match (j + 1).overflowing_pow(2) {
        (x, false) if x <= i => true,
        _ => false
    })
};
assert_eq!(floor_sqrt(8), 2);
assert_eq!(floor_sqrt(9), 3);
assert_eq!(floor_sqrt(10), 3);
assert_eq!(floor_sqrt(1 << 60), 1 << 30);