From cc28ade82aab11f38267ef2aa6d86e609beb5aef Mon Sep 17 00:00:00 2001 From: BAXYCode Date: Wed, 26 Apr 2023 10:57:13 -0400 Subject: [PATCH] optimised the generation of sparse matrices, time down to around 6s to solve 49k down from 16s, pretty good:) --- src/main.rs | 7 ++-- src/matrix.rs | 21 ++++++++--- src/sudoku.rs | 85 ++++++++++++++++++-------------------------- src/sudoku_tester.rs | 10 +++--- 4 files changed, 56 insertions(+), 67 deletions(-) diff --git a/src/main.rs b/src/main.rs index 0fdbd8d..1ced004 100644 --- a/src/main.rs +++ b/src/main.rs @@ -34,12 +34,12 @@ fn main(){ -fn public(){ env::set_var("RUST_BACKTRACE", "1"); +fn djfkh(){ env::set_var("RUST_BACKTRACE", "1"); 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].to_owned(),split[1].parse::().unwrap()); - let mut res: Option> =None ; + let res: Option> ; if split.len()>2{ res = sudoku_problem.time_to_solve(Sudoku::solver,Some(split[2].parse::().unwrap()));} else{ @@ -47,9 +47,6 @@ fn public(){ env::set_var("RUST_BACKTRACE", "1"); if let Some(res) = res{ println!("found {} solutions to the problem",sudoku_problem.solutions); let index = thread_rng().gen_range(0..res.len()); - //for x in 0..sudoku_problem.solutions{ - //if x >10{break;} println!("{:?}",res[index]); - // } } } diff --git a/src/matrix.rs b/src/matrix.rs index 05942a1..43b20e5 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -2,6 +2,7 @@ use rand::Rng; use crate::cells::Cell; use crate::cells::CERO; use crate::linked::Linked; +use crate::sudoku::RowConditions; pub struct Matrix { pub(crate) horizontal: Linked, pub(crate) vertical: Linked, @@ -55,13 +56,23 @@ impl Matrix { cell } - pub fn add_row(&mut self, row: &Vec) { + pub fn add_row(&mut self, row: RowConditions) { + let mut conditions = Vec::with_capacity(4); + conditions.push(row.0); + conditions.push(row.1); + conditions.push(row.2); + conditions.push(row.3); + + let mut col = CERO; let mut prev = None; - for val in row { - col = self.horizontal[col].next; - if *val == 1usize { + + for val in conditions { + + while val+1 != col.0 { + col = self.horizontal[col].next; + } self.sizes[col] += 1; let new_cell = self.allocate_cell(col); //fetch column and add new cell as cols new previous cell @@ -70,7 +81,7 @@ impl Matrix { self.horizontal.insert(prev, new_cell); } prev = Some(new_cell); - } + } } pub(crate) fn cover(&mut self, cell: Cell) { diff --git a/src/sudoku.rs b/src/sudoku.rs index 9344d05..c2ebb36 100644 --- a/src/sudoku.rs +++ b/src/sudoku.rs @@ -1,8 +1,7 @@ use crate::solver::Solver; use crate::sudoku_gen::SudokuGenerator; use crate::{cells::Cell, cells::CERO, matrix::Matrix}; -use std::time::{Instant, SystemTime}; -use radsort::sort_by_key; +use std::time:: SystemTime; const HARD_CODED_MAX: usize = 100_000; pub struct Sudoku { pub(crate) sudoku: String, @@ -12,6 +11,9 @@ pub struct Sudoku { pub(crate) wanted_ans_num: WantedSolutions, } +#[derive(Debug)] +pub struct RowConditions(pub(crate) usize,pub(crate) usize, pub(crate) usize, pub(crate) usize); + pub(crate) enum WantedSolutions { MaxWanted(usize), None, @@ -28,7 +30,7 @@ impl Sudoku { } } - fn small_sudoku(&self, sparse: &mut Vec>) { + fn small_sudoku(&self, sparse: &mut Vec) { let n = self.dimension * self.dimension; for (ind, mut val) in self.sudoku.char_indices() { if val == '.' { @@ -42,18 +44,18 @@ impl Sudoku { sparse.push(individual); } } else { - let temp = self.build_one_row(ind, val_dig as usize); + + let row = self.build_one_row(ind, val_dig as usize); - let tempp: Vec = temp.into_iter().flatten().collect(); - sparse.push(tempp); + sparse.push(row); } } } - fn big_sudoku(&self, sparse: &mut Vec>) { + 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::with_capacity(n*n); - for x in sudoku_split{ + 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() { @@ -64,10 +66,7 @@ impl Sudoku { } } else { 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) + sparse.push(row) } } } @@ -75,8 +74,8 @@ impl Sudoku { self.solutions = 0usize; self.sudoku = sudoku.to_owned(); } - fn sudoku_to_sparse(&self) -> Vec> { - let mut sparse: Vec> = Vec::new(); + fn sudoku_to_sparse(&self) -> Vec { + let mut sparse: Vec = Vec::new(); if self.dimension < 4 { self.small_sudoku(&mut sparse); } else { @@ -97,11 +96,10 @@ impl Sudoku { dim * (constraint_ind) + val } - fn build_one_row(&self, ind: usize, val: usize) -> Vec> { + fn build_one_row(&self, ind: usize, val: usize) -> RowConditions{ //total number of cells in the sudoku puzzle let dimension = self.dimension * self.dimension * self.dimension * self.dimension; let n = self.dimension * self.dimension; - let mut completed_row = Vec::new(); //these are the "constraint indices" i.e. in which block of 1-9 //the 1 should be placed to represent respecting a constraint //(let's say we have the first block of 81 columns represent the row @@ -114,39 +112,21 @@ impl Sudoku { //this is the index of the 1 in inside of the specific block inside //the constraint. - let row_index = self.get_index(n, val, row) - 1; - let col_index = self.get_index(n, val, col) - 1; - let box_index = self.get_index(n, val, box_con) - 1; + let row_index = (self.get_index(n, val, row) - 1)+dimension; + let col_index = (self.get_index(n, val, col) - 1)+ 2*dimension; + let box_index = (self.get_index(n, val, box_con) - 1) + 3*dimension; let digit_index = ind; //----------------------------------------------------------------------------- - let mut row_vec = Vec::with_capacity(dimension); - let mut col_vec = Vec::with_capacity(dimension); - let mut box_vec = Vec::with_capacity(dimension); - let mut digit_vec = Vec::with_capacity(dimension); - - for i in 0..dimension { - self.push_to_constraint_vec(&mut digit_vec, &i, &(&digit_index)); - self.push_to_constraint_vec(&mut row_vec, &i, &(&row_index)); - self.push_to_constraint_vec(&mut col_vec, &i, &(&col_index)); - self.push_to_constraint_vec(&mut box_vec, &i, &(&box_index)); - } - - completed_row.push(digit_vec); - completed_row.push(row_vec); - completed_row.push(col_vec); - completed_row.push(box_vec); - completed_row + + RowConditions(digit_index, row_index, col_index, box_index) } - fn build_n_rows(&self, dim: usize, cell_num: usize) -> Vec> { + fn build_n_rows(&self, dim: usize, cell_num: usize) -> Vec { let mut result = Vec::new(); 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 flat_row = row.into_iter().flatten(); - temp.extend(flat_row); - result.push(temp); + result.push(row); } result } @@ -168,14 +148,17 @@ impl Sudoku { let mut sudokus: Vec = Vec::new(); for answer in answers { let mut sudoku = String::new(); - let mut decoded: Vec<(usize, usize)> = answer - .into_iter() - .map(|row| self.decoder(row)) - .collect::>(); + let mut decoded: Vec<(usize, usize)> = Vec::with_capacity(length); + + for cells in answer.into_iter() { + let decoded_cell = self.decoder(cells); + decoded.push(decoded_cell); + } + 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()); + + for (i, x) in decoded.into_iter().enumerate() { + sudoku.insert(i, char::from_digit(x.1 as u32, 10).unwrap()); } sudokus.push(sudoku); } @@ -210,9 +193,9 @@ impl Solver for Sudoku { let cols = possibility * possibility * 4; let mut matrix = Matrix::new(rows, cols); - for x in sparse.iter() { + for x in sparse.into_iter() { // println!("this is row#{}: {:?}",i, x); - matrix.add_row(&x); + matrix.add_row(x); } if let Some(val) = answers_wanted { self.wanted_ans_num = WantedSolutions::MaxWanted(val); diff --git a/src/sudoku_tester.rs b/src/sudoku_tester.rs index f8ddbd1..ef17451 100644 --- a/src/sudoku_tester.rs +++ b/src/sudoku_tester.rs @@ -1,10 +1,9 @@ use std::fs::File; -use std::io::{BufReader,Read}; +use std::io::Read; use std::path::Path; use std::thread::{JoinHandle, self}; use crate::solver::Solver; -use crate::sudoku::{Sudoku,WantedSolutions}; -use std::sync::{Arc,Mutex}; +use crate::sudoku::Sudoku; pub(crate) struct SudokuTester{ pub response: Vec } @@ -27,8 +26,8 @@ impl SudokuTester { let path = Path::new("data.txt"); let mut file = File::open(path).unwrap(); let mut bufreader = String::new(); - let contents = file.read_to_string(&mut bufreader); - if let Ok(contents) = contents{ + let ok = file.read_to_string(&mut bufreader); + if let Ok(_ok) = ok{ return bufreader;} "None".to_owned() } @@ -37,7 +36,6 @@ impl SudokuTester { 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 handles: Vec> = Vec::with_capacity(1000); for (i ,sud) in unsolved.into_iter().enumerate(){ let mut sudoku = Sudoku::new(sud,3usize);