use super::*;
impl Default for NQueensBoard {
fn default() -> Self {
Self { arrange: vec![6, 4, 7, 1, 8, 2, 5, 3] }
}
}
impl Iterator for NQueensBoard {
type Item = bool;
fn next(&mut self) -> Option<Self::Item> {
match next_permutation(&mut self.arrange) {
true => Some(self.is_solution()),
false => None,
}
}
}
impl NQueensBoard {
pub fn empty(rank: usize) -> Self {
Self { arrange: (1..=rank).collect() }
}
pub fn is_solution(&self) -> bool {
let iter = self.arrange.iter().enumerate();
iter.clone().all(|(col, &row)| {
iter.clone().filter(|&(c, _)| c != col).all(|(o_col, &o_row)| {
col as isize - row as isize != o_col as isize - o_row as isize && col as usize + row != o_col as usize + o_row
})
})
}
pub fn next_solution(&mut self) -> bool {
loop {
match self.next() {
None => return false,
Some(true) => return true,
Some(false) => continue,
}
}
}
}
pub fn next_permutation(arrange: &mut [usize]) -> bool {
let last_ascending = match arrange.windows(2).rposition(|w| w[0] < w[1]) {
Some(i) => i,
None => {
arrange.reverse();
return false;
}
};
let swap_with = arrange[last_ascending + 1..]
.binary_search_by(|n| usize::cmp(&arrange[last_ascending], n).then(Ordering::Less))
.unwrap_err();
arrange.swap(last_ascending, last_ascending + swap_with);
arrange[last_ascending + 1..].reverse();
true
}