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.

135 lines
3.4 KiB

use std::collections::HashSet;
#[derive(Clone)]
pub struct Playground {
arr: [[u8; 9]; 9]
}
impl Playground {
pub fn init(&mut self, data: String) {
let mut idx = 0;
for c in data.chars() {
idx = match c {
'1'..='9' => {
let value = c.to_digit(10).unwrap() as u8;
self.arr[idx / 9][idx % 9] = value;
idx + 1
},
'0' =>idx + 1,
_ => idx,
}
}
}
pub fn new() -> Playground {
return Playground { arr: [[0; 9]; 9] };
}
pub fn from(s: &str) -> Playground {
let mut p = Playground::new();
p.init(String::from(s));
p
}
pub fn print(&self) {
println!("-------------------------------------");
for y in 0..9 {
print!("|");
for x in 0..9 {
let value = self.get_value(x, y);
if value.is_some() {
print!(" {} |", value.unwrap());
} else {
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 playground 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 : &Playground) -> 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
}
}