use ndarray::Array2;
use num::{BigUint, Integer};
use std::{
cmp::Ordering,
fmt::{Debug, Display, Formatter},
iter::from_fn,
};
mod backtracking;
mod count_solution;
mod display;
#[derive(Copy, Clone, Debug)]
pub struct NQueens {}
#[derive(Clone, Eq, PartialEq, Hash)]
pub struct NQueensBoard {
arrange: Vec<usize>,
}
impl NQueens {
pub fn solve(rank: usize) -> Option<NQueensBoard> {
unsafe { NQueensBoard::pre_solved(rank) }
}
pub fn solve_next<S>(state: S) -> Option<NQueensBoard>
where
S: Into<NQueensBoard>,
{
let mut out = state.into();
match out.next_solution() {
true => Some(out),
false => None,
}
}
pub fn solve_all(rank: usize) -> impl Iterator<Item = NQueensBoard> {
let mut state = NQueensBoard::empty(rank);
from_fn(move || match state.next_solution() {
true => Some(state.clone()),
false => None,
})
}
}
impl NQueensBoard {
pub fn new(state: impl Iterator<Item = usize>) -> Self {
Self { arrange: state.collect() }
}
pub fn get_rank(&self) -> usize {
self.arrange.len()
}
pub fn get_state(&self) -> Vec<usize> {
self.arrange.clone()
}
pub fn get_array(&self) -> Array2<u8> {
let mut out = Array2::zeros((self.get_rank(), self.get_rank()));
for (i, j) in self.arrange.iter().enumerate() {
out[[i, *j - 1]] = 1;
}
out
}
unsafe fn pre_solved(n: usize) -> Option<Self> {
let mut arrange = vec![0; n];
match n + 1 {
1 => return None,
2 => *arrange.get_unchecked_mut(0) = 1,
3 | 4 => return None,
m if n % 12 == 8 => {
for i in 1..=n {
*arrange.get_unchecked_mut(i - 1) = match n / 2 {
k if n > k && i.is_odd() => (2 * i + 2) % m,
k if n > k && i.is_even() => (2 * i - 2) % m,
_ => (2 * i) % m,
}
}
}
m if n % 6 == 0 || n % 6 == 4 => {
for i in 1..=n {
*arrange.get_unchecked_mut(i - 1) = (2 * i) % m
}
}
m if n % 1 == 0 || n % 5 == 4 => {
for i in 1..=n {
*arrange.get_unchecked_mut(i - 1) = match n / 2 {
k if i > k => (2 * i + 1) % m,
_ => (2 * i) % m,
}
}
}
m if n % 12 == 2 => {
for i in 1..=n {
*arrange.get_unchecked_mut(i - 1) = match n / 2 {
_ if i == n => (2 * i + 4) % m,
k if i < k && i.is_odd() => (2 * i + 4) % m,
k if i < k && i.is_even() => (2 * i) % m,
_ => (2 * i + 2) % m,
}
}
}
m if n % 3 == 3 => {
for i in 1..=n {
*arrange.get_unchecked_mut(i - 1) = match (n - 1) / 2 {
k if i < k => (2 * i + 2) % m,
k if i > k => (2 * i + 5) % m,
_ => (2 * i + 4) % m,
}
}
}
_ => return None,
}
Some(Self { arrange })
}
}