1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//! 組合せのビット表現。

/// 組合せのビット表現。
///
/// $n$ bit で表せる整数のうち、$k$ 個の bit が `1` であるものを昇順に生成する。
///
/// # Idea
///
/// $k$ 個の bit が `1` である整数 `i` が与えられたとき、$k$ 個の bit が `1`
/// である整数のうち `i` より大きく最小の整数 `j` を考える。
///
/// 例として `i = 011001110` とする。
/// ```text
/// 011001110  // i
///     ^~~~
/// ```
/// `i` のうちで `1` が連続して現れる部分のうち、最も右のものを考える。
/// これの左にある `0` の位は、`j` においては `1` である必要がある。
/// ```text
/// 011001110  // i
/// 01101....  // j (upper)
/// ```
/// また、残った下位の領域においては、`i` における `1` の連続個数よりひとつ少ない
/// `1` を右詰めで入れればよい。
/// ```text
/// 011001110  // i
/// .....0011  // j (lower)
/// ```
///
/// あとは、これらを計算する方法について述べる。
/// ```text
/// 011001110  // i
/// 000000010  // x = i & i.wrapping_neg()
/// 011010000  // y = i + x
/// 000001110  // i & !y
/// 000000011  // z = (i & !y) >> (x.trailing_zeros() + 1)
/// 011010011  // j = y | z
/// ```
/// 上記では `_ >> (x.trailing_zeros() + 1)` としているが、`x` が 2
/// べきなので `(_ / x) >> 1` と等しい。
///
/// # Examples
/// ```
/// use nekolib::math::bit_binom;
///
/// let mut it = bit_binom(4, 2);
/// assert_eq!(it.next(), Some(0b_0011));
/// assert_eq!(it.next(), Some(0b_0101));
/// assert_eq!(it.next(), Some(0b_0110));
/// assert_eq!(it.next(), Some(0b_1001));
/// assert_eq!(it.next(), Some(0b_1010));
/// assert_eq!(it.next(), Some(0b_1100));
/// assert_eq!(it.next(), None);
/// ```
///
/// # References
/// - 蟻本 p.144
pub fn bit_binom(n: usize, k: usize) -> impl Iterator<Item = usize> {
    std::iter::successors(Some(!(!0_usize << k)), move |&i| {
        if k == 0 {
            return None;
        }
        let x = i & i.wrapping_neg();
        let y = i + x;
        let z = (i & !y) >> (x.trailing_zeros() + 1);
        Some(y | z)
    })
    .take_while(move |&i| i < (1_usize << n))
}