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
| | | | | | | | | | | | | | | | |