You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
128 lines
3.3 KiB
128 lines
3.3 KiB
|
|
use std::collections::HashSet;
|
|
|
|
#[derive(Clone, Hash, PartialEq, Eq)]
|
|
pub struct Board {
|
|
arr: [[u8; 9]; 9]
|
|
}
|
|
|
|
impl Board {
|
|
|
|
pub fn new() -> Board {
|
|
return Board { arr: [[0; 9]; 9] };
|
|
}
|
|
|
|
pub fn from_array(arr: &[u8;81]) -> Board {
|
|
let mut p = Board::new();
|
|
for y in 0..9 {
|
|
for x in 0..9 {
|
|
p.arr[y][x] = arr[y*9+x];
|
|
}
|
|
}
|
|
p
|
|
}
|
|
|
|
pub fn print(&self) {
|
|
println!("┌───────┬───────┬───────┐");
|
|
for y in 0..9 {
|
|
if y != 0 && y%3 == 0 {
|
|
println!("├───────┼───────┼───────┤");
|
|
}
|
|
print!("|");
|
|
for x in 0..9 {
|
|
if let Some(value) = self.get_value(x, y) {
|
|
print!(" {}", value);
|
|
} else {
|
|
print!(" ");
|
|
}
|
|
if (x + 1) % 3 == 0 {
|
|
print!(" |");
|
|
}
|
|
}
|
|
println!();
|
|
}
|
|
println!("└───────┴───────┴───────┘");
|
|
}
|
|
|
|
pub fn get_value(&self, x: usize, y: usize) -> Option<u8> {
|
|
match self.arr[y][x] {
|
|
1..=9 => Some(self.arr[y][x]),
|
|
_ => None
|
|
}
|
|
}
|
|
|
|
pub fn set_value(&mut self, x: usize, y: usize, value : u8) {
|
|
self.arr[y][x] = value;
|
|
}
|
|
|
|
pub fn is_solved(&self) -> bool {
|
|
return self.arr.iter()
|
|
.flat_map(|row| row.iter())
|
|
.all(|value| *value != 0u8);
|
|
}
|
|
|
|
/** Checks if the Board has failures (not neccesary solved) */
|
|
pub fn is_valid(&self) -> bool {
|
|
self.rows_valid() && self.columns_valid() && self.sections_valid()
|
|
}
|
|
|
|
fn rows_valid(&self) -> bool {
|
|
let mut rows_set : HashSet<u8> = HashSet::with_capacity(9);
|
|
|
|
for x in 0..9 {
|
|
rows_set.clear();
|
|
|
|
for y in 0..9 {
|
|
if !rows_set.insert(self.arr[y][x]) {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
true
|
|
}
|
|
|
|
fn columns_valid(&self) -> bool {
|
|
let mut cols_set : HashSet<u8> = HashSet::with_capacity(9);
|
|
|
|
for y in 0..9 {
|
|
cols_set.clear();
|
|
|
|
for x in 0..9 {
|
|
if !cols_set.insert(self.arr[y][x]) {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
true
|
|
}
|
|
|
|
fn sections_valid(&self) -> bool {
|
|
let mut sects_set : HashSet<u8> = HashSet::with_capacity(9);
|
|
|
|
for s in 0..9 {
|
|
sects_set.clear();
|
|
let ref_point = ((s * 3) % 9, s / 3 * 3);
|
|
|
|
for i in 0..9 {
|
|
let (ref_x,ref_y) = ref_point;
|
|
if !sects_set.insert(self.arr[ref_y + (i/3)][ref_x + (i%3)]) {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
true
|
|
}
|
|
|
|
pub fn contains(&self, other : &Board) -> bool {
|
|
for x in 0..9 {
|
|
for y in 0..9 {
|
|
if other.arr[y][x] != 0 && self.arr[y][x] != other.arr[y][x] {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
true
|
|
}
|
|
|
|
}
|