use crate::cyclotomic::{IsRing, Units};
use crate::geom::snake::Snake;
pub struct ClosureKeyPrune {
pub max_l: usize,
pub keys: rustc_hash::FxHashSet<(Vec<i64>, i8)>,
}
fn collect_closure_keys_dfs<ZZ: IsRing>(
snake: &mut Snake<ZZ>,
max_l: usize,
keys: &mut rustc_hash::FxHashSet<(Vec<i64>, i8)>,
) {
if snake.angles().len() >= max_l {
return;
}
let turn = ZZ::turn();
for direction in ((-ZZ::hturn() + 1)..ZZ::hturn()).rev() {
if !snake.add(direction) {
continue;
}
let facing = snake.direction().rem_euclid(turn);
keys.insert((snake.offset().int_coeffs_slice().to_vec(), facing));
collect_closure_keys_dfs::<ZZ>(snake, max_l, keys);
snake.pop();
}
}
pub fn collect_closure_keys<ZZ: IsRing>(max_l: usize) -> rustc_hash::FxHashSet<(Vec<i64>, i8)> {
let mut keys = rustc_hash::FxHashSet::default();
let phi = <ZZ as Units>::unit(0).int_coeffs_slice().len();
keys.insert((vec![0i64; phi], 0));
let mut snake: Snake<ZZ> = Snake::new();
collect_closure_keys_dfs::<ZZ>(&mut snake, max_l, &mut keys);
keys
}
pub fn collect_closure_keys_for_ring(
ring: u8,
max_l: usize,
) -> rustc_hash::FxHashSet<(Vec<i64>, i8)> {
crate::dispatch_ring!(ring, collect_closure_keys::<ZZ>(max_l))
}