Skip to content

Commit

Permalink
better peformance using multi-threading (140s, 16s using release flag)
Browse files Browse the repository at this point in the history
  • Loading branch information
BAXYCode committed Apr 25, 2023
1 parent b50b278 commit 70cbf43
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 46 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
4 changes: 2 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());


}
Expand All @@ -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::<usize>().unwrap());
let mut res: Option<Vec<Vec<usize>>> =None ;
let mut res: Option<Vec<String>> =None ;
if split.len()>2{
res = sudoku_problem.time_to_solve(Sudoku::solver,Some(split[2].parse::<usize>().unwrap()));}
else{
Expand Down
2 changes: 1 addition & 1 deletion src/solver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::matrix::Matrix;
use crate::cells::Cell;

pub trait Solver {
fn solver(&mut self, wanted_ans: Option<usize>) -> Option<Vec<Vec<usize>>>;
fn solver(&mut self, wanted_ans: Option<usize>) -> Option<Vec<String>>;
fn solve(
&mut self,
matrix: &mut Matrix,
Expand Down
53 changes: 27 additions & 26 deletions src/sudoku.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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<Vec<usize>>) {
let n = self.dimension * self.dimension;
for (ind, mut val) in self.sudoku.char_indices() {
Expand All @@ -49,24 +52,22 @@ impl Sudoku {
fn big_sudoku(&self, sparse: &mut Vec<Vec<usize>>) {
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::<usize>().unwrap()))
.count();
let mut sudoku_vec = Vec::with_capacity(n*n);
for x in sudoku_split{
sudoku_vec.push(x.parse::<usize>().unwrap());
}
for (ind, val) in sudoku_vec.iter().enumerate() {
if *val == 0usize {
let mut temp = self.build_n_rows(n, ind);
while let Some(row) = temp.pop() {
sparse.push(row);
}
} else {
let row = self.build_one_row(ind, *val);
let mut temp: Vec<usize> = Vec::with_capacity(row[0].len()*4);
let row = self.build_one_row(ind, *val);
let mut temp: Vec<usize> = Vec::with_capacity(row[0].len() * 4);
let flat_row = row.into_iter().flatten();
temp.extend(flat_row);
sparse.push(temp)

}
}
}
Expand Down Expand Up @@ -142,7 +143,7 @@ impl Sudoku {

for i in 1..=dim {
let row = self.build_one_row(cell_num, i);
let mut temp: Vec<usize> = Vec::with_capacity(row[0].len()*4);
let mut temp: Vec<usize> = Vec::with_capacity(row[0].len() * 4);
let flat_row = row.into_iter().flatten();
temp.extend(flat_row);
result.push(temp);
Expand All @@ -163,28 +164,28 @@ impl Sudoku {
};
(cell, value)
}
fn ans_to_sudoku_ans(&self, answers: &Vec<Vec<Vec<usize>>>, length: usize) -> Vec<Vec<usize>> {
let mut sudokus: Vec<Vec<usize>> = Vec::new();
fn ans_to_sudoku_ans(&self, answers: &Vec<Vec<Vec<usize>>>, length: usize) -> Vec<String> {
let mut sudokus: Vec<String> = 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::<Vec<(usize, usize)>>();

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<usize>) -> Option<Vec<Vec<usize>>>,
f: fn(&mut Sudoku, Option<usize>) -> Option<Vec<String>>,
ans_wanted: Option<usize>,
) -> Option<Vec<Vec<usize>>> {
) -> Option<Vec<String>> {
let start = SystemTime::now();
let res = f(self, ans_wanted);

Expand All @@ -199,7 +200,7 @@ impl Sudoku {
}
}
impl Solver for Sudoku {
fn solver(&mut self, answers_wanted: Option<usize>) -> Option<Vec<Vec<usize>>> {
fn solver(&mut self, answers_wanted: Option<usize>) -> Option<Vec<String>> {
let length = self.sudoku.len() as f64;

let sparse = self.sudoku_to_sparse();
Expand All @@ -224,7 +225,7 @@ impl Solver for Sudoku {
println!("no answers");
return None;
}
let result: Vec<Vec<usize>> = self.ans_to_sudoku_ans(&answers, length as usize);
let result: Vec<String> = self.ans_to_sudoku_ans(&answers, length as usize);
return Some(result);
}
fn solve(
Expand Down
2 changes: 1 addition & 1 deletion src/sudoku_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ impl SudokuGenerator {
dimension: size,
}
}
pub fn generate(&mut self) -> Option<Vec<Vec<usize>>> {
pub fn generate(&mut self) -> Option<Vec<String>> {
let sudokus = self.blank.solver(None);
if let Some(sudokus) = sudokus {
return Some(sudokus);
Expand Down
46 changes: 30 additions & 16 deletions src/sudoku_tester.rs
Original file line number Diff line number Diff line change
@@ -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<String>
}
Expand Down Expand Up @@ -33,23 +34,36 @@ impl SudokuTester {
}

pub(crate)fn test_performance(&mut self){
let mut result: Vec<String> = Vec::new();
let mut treated = self.treat_file();
let mut unsolved = self.get_sudoku(&treated);
let mut results: Vec<String> = 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<JoinHandle<_>> = 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;
}


Expand Down

0 comments on commit 70cbf43

Please sign in to comment.