Skip to content

Commit

Permalink
optimised the generation of sparse matrices, time down to around 6s t…
Browse files Browse the repository at this point in the history
…o solve 49k down from 16s, pretty good:)
  • Loading branch information
BAXYCode committed Apr 26, 2023
1 parent 70cbf43 commit cc28ade
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 67 deletions.
7 changes: 2 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,19 @@ 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::<usize>().unwrap());
let mut res: Option<Vec<String>> =None ;
let res: Option<Vec<String>> ;
if split.len()>2{
res = sudoku_problem.time_to_solve(Sudoku::solver,Some(split[2].parse::<usize>().unwrap()));}
else{
res = sudoku_problem.time_to_solve(Sudoku::solver, None);}
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]);
// }
}
}
21 changes: 16 additions & 5 deletions src/matrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -55,13 +56,23 @@ impl Matrix {

cell
}
pub fn add_row(&mut self, row: &Vec<usize>) {
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
Expand All @@ -70,7 +81,7 @@ impl Matrix {
self.horizontal.insert(prev, new_cell);
}
prev = Some(new_cell);
}

}
}
pub(crate) fn cover(&mut self, cell: Cell) {
Expand Down
85 changes: 34 additions & 51 deletions src/sudoku.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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,
Expand All @@ -28,7 +30,7 @@ impl Sudoku {
}
}

fn small_sudoku(&self, sparse: &mut Vec<Vec<usize>>) {
fn small_sudoku(&self, sparse: &mut Vec<RowConditions>) {
let n = self.dimension * self.dimension;
for (ind, mut val) in self.sudoku.char_indices() {
if val == '.' {
Expand All @@ -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<usize> = temp.into_iter().flatten().collect();
sparse.push(tempp);
sparse.push(row);
}
}
}
fn big_sudoku(&self, sparse: &mut Vec<Vec<usize>>) {
fn big_sudoku(&self, sparse: &mut Vec<RowConditions>) {
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::<usize>().unwrap());
}
for (ind, val) in sudoku_vec.iter().enumerate() {
Expand All @@ -64,19 +66,16 @@ impl Sudoku {
}
} else {
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)
sparse.push(row)
}
}
}
pub fn set_new_sudoku(&mut self, sudoku: &str) {
self.solutions = 0usize;
self.sudoku = sudoku.to_owned();
}
fn sudoku_to_sparse(&self) -> Vec<Vec<usize>> {
let mut sparse: Vec<Vec<usize>> = Vec::new();
fn sudoku_to_sparse(&self) -> Vec<RowConditions> {
let mut sparse: Vec<RowConditions> = Vec::new();
if self.dimension < 4 {
self.small_sudoku(&mut sparse);
} else {
Expand All @@ -97,11 +96,10 @@ impl Sudoku {
dim * (constraint_ind) + val
}

fn build_one_row(&self, ind: usize, val: usize) -> Vec<Vec<usize>> {
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
Expand All @@ -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<Vec<usize>> {
fn build_n_rows(&self, dim: usize, cell_num: usize) -> Vec<RowConditions> {
let mut result = Vec::new();

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 flat_row = row.into_iter().flatten();
temp.extend(flat_row);
result.push(temp);
result.push(row);
}
result
}
Expand All @@ -168,14 +148,17 @@ impl Sudoku {
let mut sudokus: Vec<String> = 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::<Vec<(usize, usize)>>();
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);
}
Expand Down Expand Up @@ -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);
Expand Down
10 changes: 4 additions & 6 deletions src/sudoku_tester.rs
Original file line number Diff line number Diff line change
@@ -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<String>
}
Expand All @@ -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()
}
Expand All @@ -37,7 +36,6 @@ impl SudokuTester {
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 handles: Vec<JoinHandle<_>> = Vec::with_capacity(1000);
for (i ,sud) in unsolved.into_iter().enumerate(){
let mut sudoku = Sudoku::new(sud,3usize);
Expand Down

0 comments on commit cc28ade

Please sign in to comment.