use crate::{Board, BinBoard};
#[derive(Debug, Clone)]
pub struct SimilarSituations<'a, T: Board> {
board: &'a T,
mask: u8,
}
impl<'a, T: Board> SimilarSituations<'a, T> {
pub fn new(board: &'a T) -> Self {
Self {
board,
mask: if board.size().0 == board.size().1 { 16 } else { 8 },
}
}
pub fn reverse_v(board: &'a T) -> BinBoard {
let height = board.size().0;
let width = board.size().1;
BinBoard::from_iter(
&mut (0..height).map(|x| (0..width)
.map(move |y| board.get(height - x - 1, y))).flatten(),
width,
)
}
pub fn reverse_h(board: &'a T) -> BinBoard {
let height = board.size().0;
let width = board.size().1;
BinBoard::from_iter(
&mut (0..height).map(|x| (0..width)
.map(move |y| board.get(x, width - y - 1))).flatten(),
width,
)
}
pub fn negate(board: &'a T) -> BinBoard {
let height = board.size().0;
let width = board.size().1;
BinBoard::from_iter(
&mut (0..height).map(|x| (0..width)
.map(move |y| -board.get(x, y))).flatten(),
width,
)
}
pub fn transpose(board: &'a T) -> BinBoard {
let height = board.size().0;
let width = board.size().1;
BinBoard::from_iter(
&mut (0..width).map(|x| (0..height)
.map(move |y| board.get(y, x))).flatten(),
height,
)
}
}
impl<T: Board> Iterator for SimilarSituations<'_, T> {
type Item = BinBoard;
fn next(&mut self) -> Option<Self::Item> {
if self.mask == 0 {
None
} else {
self.mask -= 1;
let mut board = BinBoard::from(self.board);
if self.mask & 1 != 0 {
board = SimilarSituations::reverse_v(&board);
}
if self.mask & 2 != 0 {
board = SimilarSituations::reverse_h(&board);
}
if self.mask & 4 != 0 {
board = SimilarSituations::negate(&board);
}
if self.mask & 8 != 0 {
board = SimilarSituations::transpose(&board);
}
Some(board)
}
}
}