use crate::Position;
use fixedbitset::FixedBitSet;
#[derive(Debug)]
pub struct Coverage {
n: usize,
uncovered_rows: FixedBitSet,
uncovered_columns: FixedBitSet,
}
impl Coverage {
#[inline]
pub fn n(&self) -> usize {
self.n
}
pub fn new(n: usize) -> Coverage {
assert!(n > 0);
let mut all_rows_uncovered = FixedBitSet::with_capacity(n);
all_rows_uncovered.set_range(.., true);
let all_columns_uncovered = all_rows_uncovered.clone();
Coverage {
n: n,
uncovered_rows: all_rows_uncovered,
uncovered_columns: all_columns_uncovered,
}
}
#[inline]
pub fn find_uncovered_cell_column_row_order<F>(&self, mut f: F) -> Option<Position>
where
F: FnMut(Position) -> bool,
{
for column in self.uncovered_columns.ones() {
for row in self.uncovered_rows.ones() {
let pos = Position { row, column };
if f(pos) {
return Some(pos);
}
}
}
return None;
}
#[inline]
pub fn iter_uncovered_row_column_order<F>(&self, mut f: F)
where
F: FnMut(Position),
{
for row in self.uncovered_rows.ones() {
for column in self.uncovered_columns.ones() {
f(Position { row, column });
}
}
}
#[inline]
pub fn iter_uncovered_row_column_and_cover<F>(&mut self, mut f: F)
where
F: FnMut(Position) -> bool,
{
let n = self.n();
for row in 0..n {
if self.is_row_covered(row) {
continue;
}
'column: for column in 0..n {
if self.is_column_covered(column) {
continue;
}
let pos = Position { row, column };
if f(pos) {
self.cover(pos);
break 'column;
}
}
}
}
#[inline]
pub fn is_row_covered(&self, row: usize) -> bool {
debug_assert!(row < self.n());
!self.uncovered_rows.contains(row)
}
#[inline]
pub fn is_column_covered(&self, column: usize) -> bool {
debug_assert!(column < self.n());
!self.uncovered_columns.contains(column)
}
#[inline]
pub fn cover(&mut self, pos: Position) {
self.cover_row(pos.row);
self.cover_column(pos.column);
}
#[inline]
pub fn cover_column(&mut self, column: usize) {
debug_assert!(column < self.n());
self.uncovered_columns.set(column, false);
}
#[inline]
pub fn uncover_column(&mut self, column: usize) {
debug_assert!(column < self.n());
self.uncovered_columns.set(column, true);
}
#[inline]
pub fn cover_row(&mut self, row: usize) {
debug_assert!(row < self.n());
self.uncovered_rows.set(row, false);
}
pub fn clear(&mut self) {
self.uncovered_rows.set_range(.., true);
self.uncovered_columns.set_range(.., true);
}
pub fn all_uncovered(&self) -> bool {
self.uncovered_rows.count_ones(..) + self.uncovered_columns.count_ones(..)
== (self.n + self.n)
}
}