use genawaiter::sync::{Gen, GenBoxed};
#[inline]
pub const fn stirling2nd2(n: usize) -> usize {
if n <= 2 {
1
} else {
1 + 2 * stirling2nd2(n - 1)
}
}
pub fn set_bipart_gen(n: usize) -> GenBoxed<usize> {
Gen::new_boxed(|co| async move {
for i in gen0_even(n) {
co.yield_(i).await;
}
})
}
#[inline]
fn gen0_even(n: usize) -> GenBoxed<usize> {
Gen::new_boxed(|co| async move {
if n < 3 {
return;
}
co.yield_(n - 1).await;
for i in gen1_even(n - 1) {
co.yield_(i).await;
} co.yield_(n).await;
for i in neg1_even(n - 1) {
co.yield_(i).await;
} })
}
#[inline]
fn gen1_even(n: usize) -> GenBoxed<usize> {
Gen::new_boxed(|co| async move {
if n < 3 {
return;
}
co.yield_(2).await;
for i in neg1_even(n - 1) {
co.yield_(i).await;
}
co.yield_(n).await;
for i in gen1_even(n - 1) {
co.yield_(i).await;
}
})
}
#[inline]
fn neg1_even(n: usize) -> GenBoxed<usize> {
Gen::new_boxed(|co| async move {
if n < 3 {
return;
}
for i in neg1_even(n - 1) {
co.yield_(i).await;
}
co.yield_(n).await;
for i in gen1_even(n - 1) {
co.yield_(i).await;
}
co.yield_(2).await;
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_set_bipart_odd() {
const N: usize = 11;
let mut b = [0; N + 1];
b[N] = 1; let mut cnt = 1;
for x in set_bipart_gen(N) {
let old = b[x];
b[x] = 1 - b[x];
println!("Move {} from Block {} to Block {}", x, old, b[x]);
cnt += 1;
}
assert_eq!(cnt, stirling2nd2(N));
}
#[test]
fn test_set_bipart_even() {
const N: usize = 10;
let mut b = [0; N + 1];
b[N] = 1; let mut cnt = 1;
for x in set_bipart_gen(N) {
let old = b[x];
b[x] = 1 - b[x];
println!("Move {} from Block {} to Block {}", x, old, b[x]);
cnt += 1;
}
assert_eq!(cnt, stirling2nd2(N));
}
#[test]
fn test_set_bipart_special() {
const N: usize = 2;
let mut cnt = 1;
for _x in set_bipart_gen(N) {
cnt += 1;
}
assert_eq!(cnt, stirling2nd2(N));
}
}