diff --git a/Cargo.lock b/Cargo.lock index e2f817e..8b864e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12,6 +12,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" name = "dlx" version = "0.1.0" dependencies = [ + "radsort", "rand", ] @@ -38,6 +39,12 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "radsort" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17fd96390ed3feda12e1dfe2645ed587e0bea749e319333f104a33ff62f77a0b" + [[package]] name = "rand" version = "0.8.5" diff --git a/Cargo.toml b/Cargo.toml index 1cec675..4cf6e13 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,4 +6,5 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +radsort = "0.1.0" rand = "0.8.4" diff --git a/src/main.rs b/src/main.rs index 413ba6f..0fdbd8d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,7 +27,7 @@ fn main(){ let duration = start.elapsed(); println!("time elapsed: {:?}",duration); - println!("puzzles solved{:?}", _test.response.len()); + println!("puzzles solved {:?}", _test.response.len()); } @@ -39,7 +39,7 @@ fn public(){ env::set_var("RUST_BACKTRACE", "1"); 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].to_owned(),split[1].parse::().unwrap()); - let mut res: Option>> =None ; + let mut res: Option> =None ; if split.len()>2{ res = sudoku_problem.time_to_solve(Sudoku::solver,Some(split[2].parse::().unwrap()));} else{ diff --git a/src/solver.rs b/src/solver.rs index 2347ebd..37e0332 100644 --- a/src/solver.rs +++ b/src/solver.rs @@ -2,7 +2,7 @@ use crate::matrix::Matrix; use crate::cells::Cell; pub trait Solver { - fn solver(&mut self, wanted_ans: Option) -> Option>>; + fn solver(&mut self, wanted_ans: Option) -> Option>; fn solve( &mut self, matrix: &mut Matrix, diff --git a/src/sudoku.rs b/src/sudoku.rs index 32005e2..9344d05 100644 --- a/src/sudoku.rs +++ b/src/sudoku.rs @@ -1,8 +1,8 @@ use crate::solver::Solver; use crate::sudoku_gen::SudokuGenerator; use crate::{cells::Cell, cells::CERO, matrix::Matrix}; -use std::time::{SystemTime, Instant}; - +use std::time::{Instant, SystemTime}; +use radsort::sort_by_key; const HARD_CODED_MAX: usize = 100_000; pub struct Sudoku { pub(crate) sudoku: String, @@ -11,20 +11,23 @@ pub struct Sudoku { pub(crate) recursion_depth: usize, pub(crate) wanted_ans_num: WantedSolutions, } + pub(crate) enum WantedSolutions { MaxWanted(usize), None, } + impl Sudoku { pub fn new(sudoku: String, dimension: usize) -> Self { Self { - sudoku: sudoku, - dimension: dimension, + sudoku, + dimension, solutions: 0usize, recursion_depth: 0usize, wanted_ans_num: WantedSolutions::None, } } + fn small_sudoku(&self, sparse: &mut Vec>) { let n = self.dimension * self.dimension; for (ind, mut val) in self.sudoku.char_indices() { @@ -49,11 +52,10 @@ impl Sudoku { fn big_sudoku(&self, sparse: &mut Vec>) { let n = self.dimension * self.dimension; let sudoku_split: Vec<&str> = self.sudoku.split(".").collect(); - let mut sudoku_vec = Vec::new(); - sudoku_split - .iter() - .map(|v| sudoku_vec.push(v.parse::().unwrap())) - .count(); + let mut sudoku_vec = Vec::with_capacity(n*n); + for x in sudoku_split{ + sudoku_vec.push(x.parse::().unwrap()); + } for (ind, val) in sudoku_vec.iter().enumerate() { if *val == 0usize { let mut temp = self.build_n_rows(n, ind); @@ -61,12 +63,11 @@ impl Sudoku { sparse.push(row); } } else { - let row = self.build_one_row(ind, *val); - let mut temp: Vec = Vec::with_capacity(row[0].len()*4); + let row = self.build_one_row(ind, *val); + let mut temp: Vec = Vec::with_capacity(row[0].len() * 4); let flat_row = row.into_iter().flatten(); temp.extend(flat_row); sparse.push(temp) - } } } @@ -142,7 +143,7 @@ impl Sudoku { for i in 1..=dim { let row = self.build_one_row(cell_num, i); - let mut temp: Vec = Vec::with_capacity(row[0].len()*4); + let mut temp: Vec = Vec::with_capacity(row[0].len() * 4); let flat_row = row.into_iter().flatten(); temp.extend(flat_row); result.push(temp); @@ -163,28 +164,28 @@ impl Sudoku { }; (cell, value) } - fn ans_to_sudoku_ans(&self, answers: &Vec>>, length: usize) -> Vec> { - let mut sudokus: Vec> = Vec::new(); + 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 + let mut sudoku = String::new(); + let mut 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(); + radsort::sort_by_key(&mut decoded, |vals| vals.0); + for (i,x) in decoded.into_iter().enumerate(){ + + sudoku.insert(i,char::from_digit(x.1 as u32,10).unwrap()); + } sudokus.push(sudoku); } sudokus } pub(crate) fn time_to_solve( &mut self, - f: fn(&mut Sudoku, Option) -> Option>>, + f: fn(&mut Sudoku, Option) -> Option>, ans_wanted: Option, - ) -> Option>> { + ) -> Option> { let start = SystemTime::now(); let res = f(self, ans_wanted); @@ -199,7 +200,7 @@ impl Sudoku { } } impl Solver for Sudoku { - fn solver(&mut self, answers_wanted: Option) -> Option>> { + fn solver(&mut self, answers_wanted: Option) -> Option> { let length = self.sudoku.len() as f64; let sparse = self.sudoku_to_sparse(); @@ -224,7 +225,7 @@ impl Solver for 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( diff --git a/src/sudoku_gen.rs b/src/sudoku_gen.rs index 7df2dcd..3ef61dc 100644 --- a/src/sudoku_gen.rs +++ b/src/sudoku_gen.rs @@ -26,7 +26,7 @@ impl SudokuGenerator { dimension: size, } } - pub fn generate(&mut self) -> Option>> { + pub fn generate(&mut self) -> Option> { let sudokus = self.blank.solver(None); if let Some(sudokus) = sudokus { return Some(sudokus); diff --git a/src/sudoku_tester.rs b/src/sudoku_tester.rs index 878b311..f8ddbd1 100644 --- a/src/sudoku_tester.rs +++ b/src/sudoku_tester.rs @@ -1,9 +1,10 @@ use std::fs::File; use std::io::{BufReader,Read}; use std::path::Path; +use std::thread::{JoinHandle, self}; use crate::solver::Solver; use crate::sudoku::{Sudoku,WantedSolutions}; -use crate::utils; +use std::sync::{Arc,Mutex}; pub(crate) struct SudokuTester{ pub response: Vec } @@ -33,23 +34,36 @@ impl SudokuTester { } pub(crate)fn test_performance(&mut self){ - let mut result: Vec = Vec::new(); - let mut treated = self.treat_file(); - let mut unsolved = self.get_sudoku(&treated); + let mut results: Vec = Vec::new(); + let treated = self.treat_file(); + let unsolved = self.get_sudoku(&treated); let total = unsolved.len() as f32; - let mut sudoku_struct = Sudoku{sudoku:"".to_owned(),dimension:3usize,solutions:0usize,recursion_depth:0usize,wanted_ans_num: WantedSolutions::None,} ; - for (i ,sudoku) in unsolved.iter().enumerate(){ - if (i+1)%1000 == 0{ - println!("solved: {}, completed percentage: {}%",i+1,((i+1) as f32)/total*100f32); + let mut handles: Vec> = Vec::with_capacity(1000); + for (i ,sud) in unsolved.into_iter().enumerate(){ + let mut sudoku = Sudoku::new(sud,3usize); + if (i+1)%5000 == 0{ + for handle in handles{ + let answer = handle.join().unwrap(); + results.push(answer); + } + handles = Vec::new(); } - sudoku_struct.set_new_sudoku(&sudoku); - let solved = sudoku_struct.solver(None); - if let Some(solved) = solved{ - let solved_str = utils::vec_to_sudoku_string(&solved[0]); - result.push(solved_str); - } - } - self.response = result; + + let handle = thread::spawn(move || -> String{ + let answer = sudoku.solver(None); + if let Some(answer) = answer{ + return answer[0].clone(); + } + return "".to_owned() + }); + handles.push(handle); + } + for handle in handles{ + let answer = handle.join().unwrap(); + results.push(answer); + } + + self.response = results; }