diff --git a/Cargo.lock b/Cargo.lock index 97865da..e2f817e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,74 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "dlx" version = "0.1.0" +dependencies = [ + "rand", +] + +[[package]] +name = "getrandom" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "libc" +version = "0.2.141" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/Cargo.toml b/Cargo.toml index 6b07b19..1cec675 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,3 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +rand = "0.8.4" diff --git a/src/LinkedList.rs b/src/LinkedList.rs deleted file mode 100644 index 5733d08..0000000 --- a/src/LinkedList.rs +++ /dev/null @@ -1,70 +0,0 @@ -use std::ops; - - - -#[derive(Debug,PartialEq)] -struct LinkedList{ - links: Vec -} - - -struct Link{ - prev: Cell, - next: Cell} - -impl ops::Index for LinkedList{ - - type Output = Link; - fn index(&self, a: Cell) -> &Link{ - &self.links[a.0]} - - - }impl ops::IndexMut for LinkedList{ - fn index_mut(&self, a:Cell) -> &mut Link{ - &mut self.links[a.0]}} - - -impl LinkedList { - - fn new_with_cap(cap: uzise) -> LinkedList{ - LinkedList{links: Vec::with_capacity(cap), covered:false,num:Num::None} - } - - fn new_cell(&mut self) -> Cell{ - let cell = Cell(self.links.len()); - self.links.push(Link{prev:cell, next:cell}); - cell} - - fn insert(&mut self, a:Cell,b:Cell){ - - let c = self[a].next; - - self[a].next = b; - self[b].next = c; - self[c].prev = b; - self[b].prev = a; } - - - fn remove(&mut self, a:Cell){ - - let a = self[b].prev; - let c = self[b].next; - - self[c].prev = self[b].prev; - self[a].next = self[b].next;} - - fn add_back(&mut self, b:Cell){ - - let a = self[b].prev; - let c = self[b].next; - - self[c].prev = b; - self[a].next = b;} - - fn cursor(&self, c: Cell) -> Cursor{ - Cursor {c, c}} -} - -fn main() { - -} diff --git a/src/cells.rs b/src/cells.rs index e69de29..6daeec8 100644 --- a/src/cells.rs +++ b/src/cells.rs @@ -0,0 +1,31 @@ +use std::ops; + +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct Cell(pub usize); + +pub const CERO: Cell = Cell(0); + +impl ops::Index for Vec { + type Output = Cell; + + fn index(&self, cell: Cell) -> &Cell { + &self[cell.0] + } +} +impl ops::IndexMut for Vec { + fn index_mut(&mut self, cell: Cell) -> &mut Cell { + &mut self[cell.0] + } +} +impl ops::Index for Vec { + type Output = usize; + fn index(&self, index: Cell) -> &usize { + &self[index.0] + } +} + +impl ops::IndexMut for Vec { + fn index_mut(&mut self, index: Cell) -> &mut usize { + &mut self[index.0] + } +} diff --git a/src/cursor.rs b/src/cursor.rs index b869cf0..5b21195 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -1,27 +1,27 @@ -mod LinkedList; -mod cells; +use crate::linked::Linked; +use crate::cells::Cell; -struct Cursor{ - head: Cell, - current: Cell} +pub(crate) struct Cursor{ + pub(crate) head: Cell, + pub(crate) current: Cell} impl Cursor { //Takes in a reference to a list and uses the cursor's internals to //navigate said list. If the cursor's new curr node is the same as //the node it started with, None is returned. - fn next(&self, &list: LinkedList) -> Option{ + pub(crate) fn next(&mut self, list: &Linked) -> Option{ self.current = list[self.current].next; - if assert_eq!(self.current,self.head ){ + if self.current == self.head{ return None;} - Some(self.current); + Some(self.current) } - fn prev(&self, &list:LinkedList) -> Option{ + pub(crate)fn prev(&mut self, list:&Linked) -> Option{ self.current = list[self.current].prev; - if assert_eq!(self.current, self.head){ + if self.current == self.head{ return None;} - Some(self.current);} + Some(self.current)} } diff --git a/src/linked.rs b/src/linked.rs new file mode 100644 index 0000000..44d821c --- /dev/null +++ b/src/linked.rs @@ -0,0 +1,68 @@ +use std::ops; +use crate::cells::Cell; +use crate::cursor::Cursor; + + +pub(crate) struct Linked{ + pub(crate) links: Vec +} + + +pub struct Link{ + pub(crate) prev: Cell, + pub(crate) next: Cell} + +impl ops::Index for Linked{ + + type Output = Link; + fn index(&self, a: Cell) -> &Link{ + &self.links[a.0]} + + + }impl ops::IndexMut for Linked{ + fn index_mut(&mut self, a:Cell) -> &mut Link{ + &mut self.links[a.0]}} + + +impl Linked { + + pub(crate) fn new_with_cap(cap: usize) -> Linked{ + Linked{links: Vec::with_capacity(cap)} + } + + pub(crate) fn new_cell(&mut self) -> Cell{ + let cell = Cell(self.links.len()); + self.links.push(Link{prev:cell, next:cell}); + cell} + + pub(crate) fn insert(&mut self, a:Cell,b:Cell){ + + let c = self[a].next; + + self[a].next = b; + self[b].next = c; + self[c].prev = b; + self[b].prev = a; } + + + pub(crate) fn remove(&mut self, b:Cell){ + + let a = self[b].prev; + let c = self[b].next; + + self[c].prev = self[b].prev; + self[a].next = self[b].next;} + + pub(crate) fn add_back(&mut self, b:Cell){ + + let a = self[b].prev; + let c = self[b].next; + + self[c].prev = b; + self[a].next = b;} + + pub(crate) fn cursor(&self, c: Cell) -> Cursor{ + Cursor {head: c, current:c}} +} + + diff --git a/src/main.exe b/src/main.exe new file mode 100644 index 0000000..86e05f1 Binary files /dev/null and b/src/main.exe differ diff --git a/src/main.pdb b/src/main.pdb new file mode 100644 index 0000000..f27662a Binary files /dev/null and b/src/main.pdb differ diff --git a/src/main.rs b/src/main.rs index b2d6687..0e3282e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1 +1,30 @@ -unimplemented!(); + +#![recursion_limit = "1000000"] +#![feature(int_roundings)] +use rand::{thread_rng,Rng}; +use std::{io, collections}; +mod cursor; +mod linked; +mod cells; +mod matrix; +mod sudoku; +use crate::sudoku::Sudoku; +use std::env; + +fn main(){ +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],split[1].parse::().unwrap(),split[2].parse::().unwrap()); +let res = sudoku_problem.time_to_solve(Sudoku::solver); +if let Some(res) = res{ + println!("found {} solutions to the problem",sudoku_problem.solutions); + let index = thread_rng().gen_range(1..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 00d6b6e..59b8ab9 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -1,116 +1,164 @@ -mod cells; -mod cursor; -mod LinkedList; - - -struct Matrix{ - horizontal: LinkedList, - vertical: LinkedList, - - access: Vec, - - sizes: Vec, - } - -impl Matrix{ +use rand::{thread_rng,Rng}; +use crate::cells::Cell; +use crate::cells::CERO; +use crate::cursor; +use crate::cursor::Cursor; +use crate::linked::Linked; + +pub struct Matrix { + pub(crate) horizontal: Linked, + pub(crate) vertical: Linked, + + pub(crate) access: Vec, + + pub(crate) sizes: Vec, + pub(crate) covered: Vec, + pub(crate) total_covered: usize, + pub(crate) total_uncovered: usize, +} - pub fn new(n: usize, rows:usize,cols:usize) -> Matrix{ - - let mut matrix = Matrix{ - horizontal : Vec::with_capacity(cols+1), - vertical : Vec::with_capacity(rows+1), - size: Vec::new(), - access: Vec::with_capacity(cols+1), - } - for _ in 0..cols{ +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), + }, + sizes: Vec::new(), + access: Vec::with_capacity(cols + 1), + covered: Vec::new(), + total_covered: 0usize, + total_uncovered: 0usize, + }; + assert_eq!(matrix.allocate_column(), CERO); + for _ in 0..cols { matrix.add_column(); } matrix - } - - fn allocate_cell(&mut self, cell: Cell) -> Cell{ + } + fn allocate_cell(&mut self, cell: Cell) -> Cell { self.access.push(cell); let x_cell = self.horizontal.new_cell(); let y_cell = self.vertical.new_cell(); - assert_eq!(x_cell,y_cell ); - x_cell + assert_eq!(x_cell, y_cell); + x_cell } - fn allocate_column(&mut self) -> Cell{ - + fn allocate_column(&mut self) -> Cell { let cell = self.allocate_cell(CERO); self.access[cell] = cell; - self.size.push(0); - cell + self.sizes.push(0); + self.covered.push(0); + cell } fn add_column(&mut self) -> Cell { - let cell = self.allocate_column(); // add column in last position - self.horizontal.insert(self.horizontal[CERO].prev,cell); + self.horizontal.insert(self.horizontal[CERO].prev, cell); cell } - pub fn add_row(&mut self, row: Vec) { - - + pub fn add_row(&mut self, row: &Vec) { let mut col = CERO; - + let mut prev = None; - for val in row{ - col = self.horizontal[col].next; - match val{ - Some(0) => _, - Some(1) =>{ - self.size[col] += 1; - let new_cell = self.allocate_cell(); + for val in row { + col = self.horizontal[col].next; + if *val == 1usize { + self.sizes[col] += 1; + let new_cell = self.allocate_cell(col); //fetch column and add new cell as cols new previous cell - self.vertical.insert(self.vertical[col].prev,new_cell); - if let Some(prev) =prev{ - self.horizontal.insert(prev,new_cell); - } - prev = Some(new_cell);} + self.vertical.insert(self.vertical[col].prev, new_cell); + if let Some(prev) = prev { + self.horizontal.insert(prev, new_cell); + } + prev = Some(new_cell); } } } - fn cover(&mut self, cell:Cell){ - //remove acces cell front x axis list + pub(crate) fn cover(&mut self, cell: Cell) { + //remove acces cell front x axis list + // println!("covering column: {:?}",cell); + //self.total_covered+=1; self.horizontal.remove(cell); + self.covered[cell] = 1; //get y axis cursor to iterate on rows to cover - let mut cur = self.y.cursor(cell); + let mut cur = self.vertical.cursor(cell); //here we only cover the rows but we leave the covered columns nodes //for us to cover later outside of this function - while let Some(c_axis_cell) = cur.next(&self.vertical){ + while let Some(c_axis_cell) = cur.next(&self.vertical) { let mut curr = self.horizontal.cursor(c_axis_cell); - while let Some(r_axis_cell) = curr.next(&self.horizontal){ - + while let Some(r_axis_cell) = curr.next(&self.horizontal) { self.vertical.remove(r_axis_cell); - self.size[self.acces[r_axis_cell]] -= 1; - + self.sizes[self.access[r_axis_cell]] -= 1; + //self.total_covered+=1; + // println!("size for column {:?} reduced to : {}",self.access[r_axis_cell],self.sizes[self.access[r_axis_cell]]); } - + } + } + pub(crate) fn cover_all_row(&mut self, col: Cell) { + let mut cursor = self.vertical.cursor(col); + while let Some(cell) = cursor.next(&self.horizontal) { + let header = self.access[cell]; + self.cover(header); } } - - fn uncover(&mut self, cell:Cell){ - + pub(crate) fn uncover(&mut self, cell: Cell) { let mut cur = self.vertical.cursor(cell); - while let Some(c_axis_cell) = cur.prev(&self.vertical){ - + while let Some(c_axis_cell) = cur.prev(&self.vertical) { let mut r_axis_cell = self.horizontal.cursor(c_axis_cell); - while let Some(current_cell) = r_axis_cell.prev(&self.horizontal){ - - self.size[self.access[current_cell]] += 1; + while let Some(current_cell) = r_axis_cell.prev(&self.horizontal) { + //self.total_uncovered +=1; + self.sizes[self.access[current_cell]] += 1; self.vertical.add_back(current_cell); - } - - } + } //self.total_uncovered+=1; + self.covered[cell] = 0; self.horizontal.add_back(cell); + } + pub(crate) fn uncover_all_row(&mut self, cell: Cell) { + let mut cursor = self.vertical.cursor(cell); + while let Some(cell) = cursor.prev(&self.horizontal) { + let header = self.access[cell]; + self.uncover(header) + } + } + pub(crate) fn get_row(&self, cell: Cell) -> Vec { + let mut cols_ind = Vec::new(); + + let mut curr = self.horizontal.cursor(cell); + cols_ind.push(self.access[cell].0); + while let Some(current) = curr.next(&self.horizontal) { + cols_ind.push(self.access[current].0); + } + cols_ind.sort(); + cols_ind } + pub(crate) fn get_smallest(&self) -> Cell { + let mut cursor = self.horizontal.cursor(CERO); + let mut smallest_column = CERO; + let mut changed:bool = false; + let mut current_smallest_size = self.sizes.clone().into_iter().max().unwrap()+1; + while let Some(node) = cursor.next(&self.horizontal) { + if self.sizes[self.access[node]] < current_smallest_size { + current_smallest_size = self.sizes[self.access[node]]; + smallest_column = node; + if current_smallest_size == 1 { + return smallest_column; + } + changed = true; + }if changed == false { + let index: usize = rand::thread_rng().gen_range(1..self.sizes.len()); + return self.access[index] + } + } + smallest_column + } } diff --git a/src/sudoku.rs b/src/sudoku.rs index b1b54fa..aa16217 100644 --- a/src/sudoku.rs +++ b/src/sudoku.rs @@ -1,95 +1,251 @@ -#![allow(unused)] -#![feature(int_roundings)] +use std::{any::type_name, time::SystemTime}; -use std::itertools::*; +use crate::{cells::Cell, cells::CERO, matrix::Matrix}; -struct Sudoku{ - sudoku:Vector, - dimension:usize,} - -impl Sudoku{ +pub struct Sudoku { + sudoku: String, + dimension: usize, + pub(crate) solutions: usize, + pub(crate) recursion_depth: usize, + pub(crate) wanted_ans_num:usize +} - fn sudoku_to_sparse() -> Vec>{ - let mut sparse = Vec::new(); - - for (ind, val) in enumerate(self.sudoku){ - - if val == 0{ - - let mut temp = self.build_nine_rows(ind); - temp.iter.map(|item|sparse.push(item)); - - }else{ - - let temp = self.build_one_row(ind,val); - sparse.push(temp); - +impl Sudoku { + 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, + } + } + fn small_sudoku(&self, sparse: &mut Vec>) { + let n = self.dimension * self.dimension; + for (ind, val) in self.sudoku.char_indices() { + let val_copy = val.clone(); + let val_dig = val_copy.to_digit(10u32).unwrap(); + if (val.to_digit(10u32).unwrap() as usize) == 0usize { + let mut temp = self.build_n_rows(n, ind); + while let Some(individual) = temp.pop() { + sparse.push(individual); + } + } else { + let temp = self.build_one_row(ind, (val_dig as usize)); + + let tempp: Vec = temp.into_iter().flatten().collect(); + sparse.push(tempp); } - } - sparse} - - fn get_index(dim:usize, val:usize, constraint_ind:usize) -> usize{ - - dim*(constraint_ind-1)+val + } + 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(); + 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 mut temp = self.build_one_row(ind, *val); + let tempp: Vec = temp.into_iter().flatten().collect(); + sparse.push(tempp) + } + } + } + fn sudoku_to_sparse(&self) -> Vec> { + let mut sparse: Vec> = Vec::new(); + if self.dimension < 4 { + self.small_sudoku(&mut sparse); + } else { + self.big_sudoku(&mut sparse); + } + println!("sparse: {:?}", sparse.len()); + sparse + } - } + fn push_to_constraint_vec(&self, vect: &mut Vec, comparor: &usize, compare_to: &usize) { + if comparor == compare_to { + vect.push(1usize); + } else { + vect.push(0usize) + } + } - fn build_one_row(ind:usize,val: usize) -> Vecusize{ + fn get_index(&self, dim: usize, val: usize, constraint_ind: usize) -> usize { + dim * (constraint_ind) + val + } - let dimension = - self.dimension*self.dimension*self.dimension*self.dimension; - let n = self.dimension*self.dimension; + fn build_one_row(&self, ind: usize, val: usize) -> Vec> { + //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 + //constraint, index 56 would mean that our possibility is located + //in the 7th row) + let mut col = ind % (n); + let row = ind.div_floor(n); + let box_con = (row - (row % self.dimension)) + (col.div_floor(self.dimension)); + //----------------------------------------------------------------------------- + + //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 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)); + } - let mut col = ind%(self.dimension*self.dimension); - if col == 0{ - col = 9;} - - let row = ind.div_ceil(self.dimension*self.dimension); - let box = (row-(row%self.dimension))+row.div_ceil(self.dimension); - - let row_index = self.get_index(n,val,row) ; - let col_index = self.get_index(n,val,col); - let box_index = self.get_index(n,val,box); - let digit_index = get_index(n,val,ind); - - let mut row_vec = Vec::new(); - let mut col_vec = Vec::new(); - let mut box_vec = Vec::new(); - let mut digit_vec = Vec::new(); - - for i in 0..dimension{ - - if i == col_index{ - col_vec.push(1usize); - }else{col_vec.push(0usize);} - if i == row_index{ - row_vec.push(1usize);} - else{row_vec.push(0usize);} - if i == box_index{box_vec.push(1usize);} - else{box_vec.push(0usize);} - if i == digit_index{digit_vec.push(1usize);} - else{digit_vec.push(0usize);} - - } completed_row.push(digit_vec); completed_row.push(row_vec); completed_row.push(col_vec); completed_row.push(box_vec); completed_row - } - - fn build_nine_rows(dim: usize){ + } + fn build_n_rows(&self, dim: usize, cell_num: usize) -> Vec> { let mut result = Vec::new(); - for i in 1..=dim*dim{ - let temp = build_one_row(dim,i); + for i in 1..=dim { + let mut temp: Vec = self + .build_one_row(cell_num, i) + .into_iter() + .flatten() + .collect(); result.push(temp); - } result } + pub fn solver(&mut self) -> Option>> { + let length = self.sudoku.len() as f64; + + let sparse = self.sudoku_to_sparse(); + + let possibility = self.dimension * self.dimension; + let rows = possibility * possibility * possibility; + let cols = possibility * possibility * 4; + let mut matrix = Matrix::new(rows, cols); + + for (i, x) in sparse.iter().enumerate() { + // println!("this is row#{}: {:?}",i, x); + matrix.add_row(&x); + } + let mut partial_ans = Vec::new(); + let mut answers = Vec::new(); + self.solve(&mut matrix, &mut partial_ans, &mut answers); + if answers.len() == 0 { + println!("no answers"); + return None; + } + let result: Vec> = self.ans_to_sudoku_ans(&answers, (length as usize)); + return Some(result); + } + fn solve( + &mut self, + matrix: &mut Matrix, + partials: &mut Vec, + ans: &mut Vec>>, + ) { + //println!("recursion depth: {}", self.recursion_depth); + self.recursion_depth +=1; + //check if matrix is empty + let mut curr = matrix.horizontal.cursor(CERO); + if curr.next(&matrix.horizontal) == None { + let answer = partials + .iter() + .map(|cell| matrix.get_row(*cell)) + .collect::>>(); + ans.push(answer); + self.solutions += 1; + 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(); + // println!("cell: {:?} covered",col); + matrix.cover(col); + let mut curr = matrix.vertical.cursor(col); + while let Some(curr) = curr.next(&matrix.vertical) { + partials.push(curr); + // println!("first cell of row to cover: {:?} cell in col:{:?} ",curr,matrix.access[curr]); + matrix.cover_all_row(curr); + // println!("total nodes covered {}",matrix.total_covered); + self.solve(matrix, partials, ans); + matrix.uncover_all_row(curr); + partials.pop(); + } + matrix.uncover(col); + //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 + } } diff --git a/src/sudoku_tester.rs b/src/sudoku_tester.rs new file mode 100644 index 0000000..e69de29