diff --git a/src/main.rs b/src/main.rs index 0e3282e..23d6609 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,13 +2,14 @@ #![recursion_limit = "1000000"] #![feature(int_roundings)] use rand::{thread_rng,Rng}; -use std::{io, collections}; +use std::io; mod cursor; +mod solver; mod linked; mod cells; mod matrix; mod sudoku; -use crate::sudoku::Sudoku; +use crate::sudoku::{Sudoku,Solver}; use std::env; fn main(){ @@ -17,7 +18,7 @@ let mut input = String::new(); io::stdin().read_line(&mut input).expect("give valid sudoku"); let split :Vec<&str> = input.split_whitespace().collect(); let mut sudoku_problem = Sudoku::new(split[0],split[1].parse::().unwrap(),split[2].parse::().unwrap()); -let res = sudoku_problem.time_to_solve(Sudoku::solver); +let res = sudoku_problem.time_to_solve(Solver::solver); if let Some(res) = res{ println!("found {} solutions to the problem",sudoku_problem.solutions); let index = thread_rng().gen_range(1..res.len()); diff --git a/src/matrix.rs b/src/matrix.rs index 59b8ab9..19a5ed1 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -1,8 +1,6 @@ -use rand::{thread_rng,Rng}; +use rand::Rng; use crate::cells::Cell; use crate::cells::CERO; -use crate::cursor; -use crate::cursor::Cursor; use crate::linked::Linked; pub struct Matrix { @@ -20,12 +18,8 @@ pub struct Matrix { impl Matrix { pub fn new(rows: usize, cols: usize) -> Matrix { let mut matrix = Matrix { - horizontal: crate::linked::Linked { - links: Vec::with_capacity(cols + 1), - }, - vertical: crate::linked::Linked { - links: Vec::with_capacity(rows + 1), - }, + horizontal: Linked::new_with_cap(cols+1), + vertical: Linked::new_with_cap(rows+1), sizes: Vec::new(), access: Vec::with_capacity(cols + 1), covered: Vec::new(), diff --git a/src/solver.rs b/src/solver.rs new file mode 100644 index 0000000..66b723b --- /dev/null +++ b/src/solver.rs @@ -0,0 +1,14 @@ +use crate::matrix::Matrix; +use crate::cells::Cell; + +pub trait Solver { + fn solver(&mut self) -> Option>>; + fn solve( + &mut self, + matrix: &mut Matrix, + partials: &mut Vec, + ans: &mut Vec>>, + ); +} + + diff --git a/src/sudoku.rs b/src/sudoku.rs index aa16217..c8e2e73 100644 --- a/src/sudoku.rs +++ b/src/sudoku.rs @@ -7,17 +7,26 @@ pub struct Sudoku { dimension: usize, pub(crate) solutions: usize, pub(crate) recursion_depth: usize, - pub(crate) wanted_ans_num:usize + pub(crate) wanted_ans_num: usize, +} +pub trait Solver { + fn solver(&mut self) -> Option>>; + fn solve( + &mut self, + matrix: &mut Matrix, + partials: &mut Vec, + ans: &mut Vec>>, + ); } impl Sudoku { - pub fn new(sudoku: &str, dimension: usize,answers_wanted:usize) -> Self { - Self{ + pub fn new(sudoku: &str, dimension: usize, answers_wanted: usize) -> Self { + Self { sudoku: sudoku.to_owned(), dimension: dimension, solutions: 0usize, recursion_depth: 0usize, - wanted_ans_num:answers_wanted, + wanted_ans_num: answers_wanted, } } fn small_sudoku(&self, sparse: &mut Vec>) { @@ -31,7 +40,7 @@ impl Sudoku { sparse.push(individual); } } else { - let temp = self.build_one_row(ind, (val_dig as usize)); + let temp = self.build_one_row(ind, val_dig as usize); let tempp: Vec = temp.into_iter().flatten().collect(); sparse.push(tempp); @@ -137,7 +146,50 @@ impl Sudoku { result } - pub fn solver(&mut self) -> Option>> { + fn decoder(&self, row: &Vec) -> (usize, usize) { + let possibilities = self.dimension * self.dimension; + let cell = row[0]; + let value = { + let ind = row[1] - (possibilities * possibilities); + let mut i = ind % possibilities; + if i == 0 { + i = possibilities + } + i + }; + (cell, value) + } + fn ans_to_sudoku_ans(&self, answers: &Vec>>, length: usize) -> Vec> { + let mut sudokus: Vec> = Vec::new(); + for answer in answers { + let mut sudoku = vec![0usize; length]; + let decoded: Vec<(usize, usize)> = answer + .into_iter() + .map(|row| self.decoder(row)) + .collect::>(); + + decoded + .into_iter() + .map(|info| sudoku[(info.0) - 1] = info.1) + .count(); + sudokus.push(sudoku); + } + sudokus + } + pub(crate) fn time_to_solve( + &mut self, + f: fn(&mut Sudoku) -> Option>>, + ) -> Option>> { + let start = SystemTime::now(); + let res = f(self); + let end = SystemTime::now(); + let duration = end.duration_since(start).unwrap(); + println!("execution time in milliseconds: {}", duration.as_millis()); + res + } +} +impl Solver for Sudoku { + fn solver(&mut self) -> Option>> { let length = self.sudoku.len() as f64; let sparse = self.sudoku_to_sparse(); @@ -158,7 +210,7 @@ impl Sudoku { println!("no answers"); return None; } - let result: Vec> = self.ans_to_sudoku_ans(&answers, (length as usize)); + let result: Vec> = self.ans_to_sudoku_ans(&answers, length as usize); return Some(result); } fn solve( @@ -168,7 +220,7 @@ impl Sudoku { ans: &mut Vec>>, ) { //println!("recursion depth: {}", self.recursion_depth); - self.recursion_depth +=1; + self.recursion_depth += 1; //check if matrix is empty let mut curr = matrix.horizontal.cursor(CERO); if curr.next(&matrix.horizontal) == None { @@ -180,16 +232,15 @@ impl Sudoku { self.solutions += 1; return; } - if self.wanted_ans_num <=ans.len() { - return; - + if self.wanted_ans_num <= ans.len() { + return } // println!("covered: {:?}",matrix.covered); // println!("partials: {:?}", partials); // println!("sizes : {:?}", matrix.sizes); //find the column with the lowest amount of 1s - let mut col = matrix.get_smallest(); + let col = matrix.get_smallest(); // println!("cell: {:?} covered",col); matrix.cover(col); let mut curr = matrix.vertical.cursor(col); @@ -206,46 +257,4 @@ impl Sudoku { //println!(" total uncover ops: {}",matrix.total_uncovered); // println!("total operations: {}",matrix.total_covered+matrix.total_uncovered); } - - fn decoder(&self, row: &Vec) -> (usize, usize) { - let possibilities = self.dimension * self.dimension; - let cell = row[0]; - let value = { - let ind = row[1] - (possibilities * possibilities); - let mut i = ind % possibilities; - if i == 0 { - i = possibilities - } - i - }; - (cell, value) - } - fn ans_to_sudoku_ans(&self, answers: &Vec>>, length: usize) -> Vec> { - let mut sudokus: Vec> = Vec::new(); - for answer in answers { - let mut sudoku = vec![0usize; length]; - let decoded: Vec<(usize, usize)> = answer - .into_iter() - .map(|row| self.decoder(row)) - .collect::>(); - - decoded - .into_iter() - .map(|info| sudoku[(info.0) - 1] = info.1) - .count(); - sudokus.push(sudoku); - } - sudokus - } - pub(crate) fn time_to_solve( - &mut self, - f: fn(&mut Sudoku) -> Option>>, - ) -> Option>> { - let start = SystemTime::now(); - let res = f(self); - let end = SystemTime::now(); - let duration = end.duration_since(start).unwrap(); - println!("execution time in milliseconds: {}", duration.as_millis()); - res - } }