merged update
This commit is contained in:
parent
9a0a9afe37
commit
e06c9db089
172
src/main.rs
172
src/main.rs
|
@ -1,5 +1,5 @@
|
|||
use std::fmt;
|
||||
use std::collections::HashSet;
|
||||
//use std::collections::HashSet;
|
||||
use rand::seq::SliceRandom;
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -21,7 +21,7 @@ impl Cell {
|
|||
self.possibilities = (1..=9).collect();
|
||||
}
|
||||
|
||||
fn remove_possibilities(&mut self, possibilities: &HashSet<u8>) {
|
||||
fn remove_possibilities(&mut self, possibilities: &Vec<u8>) {
|
||||
self.possibilities.retain(|&x| !possibilities.contains(&x))
|
||||
}
|
||||
}
|
||||
|
@ -87,63 +87,28 @@ impl Sudoku {
|
|||
}
|
||||
|
||||
fn update_possibilities(&mut self) {
|
||||
self.update_rows();
|
||||
self.update_columns();
|
||||
self.update_squares();
|
||||
}
|
||||
|
||||
fn update_rows(&mut self) {
|
||||
for row_index in 0..9 {
|
||||
let mut used_values: HashSet<u8> = HashSet::new();
|
||||
|
||||
for column_index in 0..9 {
|
||||
if let Some(value) = self.grid[row_index][column_index].value {
|
||||
used_values.insert(value);
|
||||
}
|
||||
}
|
||||
|
||||
for column_index in 0..9 {
|
||||
self.grid[row_index][column_index].remove_possibilities(&used_values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn update_columns(&mut self) {
|
||||
for column_index in 0..9 {
|
||||
let mut used_values: HashSet<u8> = HashSet::new();
|
||||
|
||||
for row_index in 0..9 {
|
||||
if let Some(value) = self.grid[row_index][column_index].value {
|
||||
used_values.insert(value);
|
||||
}
|
||||
}
|
||||
|
||||
for row_index in 0..9 {
|
||||
self.grid[row_index][column_index].remove_possibilities(&used_values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn update_squares(&mut self) {
|
||||
for square_row_index in 0..3 {
|
||||
for square_column_index in 0..3 {
|
||||
let mut used_values: HashSet<u8> = HashSet::new();
|
||||
|
||||
for row_offset_index in 0..3 {
|
||||
for column_offset_index in 0..3 {
|
||||
if let Some(value) = self.grid[square_row_index * 3 + row_offset_index][square_column_index * 3 + column_offset_index].value {
|
||||
used_values.insert(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for row_offset_index in 0..3 {
|
||||
for column_offset_index in 0..3 {
|
||||
self.grid[square_row_index * 3 + row_offset_index][square_column_index * 3 + column_offset_index].remove_possibilities(&used_values.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut row_used_values: [Vec<u8>;9] = [vec![],vec![],vec![],vec![],vec![],vec![],vec![],vec![],vec![]];
|
||||
let mut column_used_values: [Vec<u8>;9] = [vec![],vec![],vec![],vec![],vec![],vec![],vec![],vec![],vec![]];
|
||||
let mut square_used_values: [[Vec<u8>;3];3] = [[vec![],vec![],vec![]],[vec![],vec![],vec![]],[vec![],vec![],vec![]]];
|
||||
|
||||
for row_index in 0..9 {
|
||||
for column_index in 0..9 {
|
||||
let Some(value) = self.grid[row_index][column_index].value else {
|
||||
continue
|
||||
};
|
||||
row_used_values[row_index].push(value);
|
||||
column_used_values[column_index].push(value);
|
||||
square_used_values[row_index/3][column_index/3].push(value);
|
||||
}
|
||||
}
|
||||
|
||||
for row_index in 0..9 {
|
||||
for column_index in 0..9 {
|
||||
self.grid[row_index][column_index].remove_possibilities(&row_used_values[row_index]);
|
||||
self.grid[row_index][column_index].remove_possibilities(&column_used_values[column_index]);
|
||||
self.grid[row_index][column_index].remove_possibilities(&square_used_values[row_index/3][column_index/3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn collapse(&mut self) -> bool {
|
||||
|
@ -188,16 +153,14 @@ impl Sudoku {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(choice) = fork {
|
||||
self.reset_possibilities();
|
||||
let mut choice_value = HashSet::new();
|
||||
choice_value.insert(choice.selected_value);
|
||||
self.grid[choice.cell_selected[0]][choice.cell_selected[1]].remove_possibilities(&choice_value);
|
||||
return self.collapse_cell(choice.cell_selected[0], choice.cell_selected[1])
|
||||
} else {
|
||||
let Some(choice) = fork else {
|
||||
println!("x backtracked to start");
|
||||
return false
|
||||
}
|
||||
};
|
||||
|
||||
self.reset_possibilities();
|
||||
self.grid[choice.cell_selected[0]][choice.cell_selected[1]].remove_possibilities(&vec![choice.selected_value]);
|
||||
return self.collapse_cell(choice.cell_selected[0], choice.cell_selected[1])
|
||||
}
|
||||
|
||||
fn reset_possibilities(&mut self) {
|
||||
|
@ -211,26 +174,61 @@ impl Sudoku {
|
|||
}
|
||||
|
||||
fn collapse_cell(&mut self, row_index: usize, column_index: usize) -> bool {
|
||||
if let Some(&selected_value) = self.grid[row_index][column_index].possibilities.choose(&mut self.rng) {
|
||||
self.history.push(Choice {
|
||||
cell_selected: [row_index, column_index],
|
||||
possibilities: self.grid[row_index][column_index].possibilities.clone(),
|
||||
selected_value,
|
||||
});
|
||||
|
||||
self.grid[row_index][column_index].set(selected_value);
|
||||
println!("# collapsing [{}][{}] ({:?}) to {}", row_index, column_index, self.grid[row_index][column_index].possibilities, selected_value);
|
||||
return true
|
||||
} else {
|
||||
let Some(&selected_value) = self.grid[row_index][column_index].possibilities.choose(&mut self.rng) else {
|
||||
println!("x no possibilities for [{}][{}]", row_index, column_index);
|
||||
return false
|
||||
};
|
||||
|
||||
self.history.push(Choice {
|
||||
cell_selected: [row_index, column_index],
|
||||
possibilities: self.grid[row_index][column_index].possibilities.clone(),
|
||||
selected_value,
|
||||
});
|
||||
|
||||
self.grid[row_index][column_index].set(selected_value);
|
||||
println!("# collapsing [{}][{}] ({:?}) to {}", row_index, column_index, self.grid[row_index][column_index].possibilities, selected_value);
|
||||
return true
|
||||
}
|
||||
|
||||
fn solve(&mut self, display: bool) {
|
||||
if display {
|
||||
self.display();
|
||||
println!("--------");
|
||||
}
|
||||
}
|
||||
|
||||
self.update_possibilities();
|
||||
|
||||
let mut counter: usize = 0;
|
||||
|
||||
while self.collapse() {
|
||||
self.update_possibilities();
|
||||
counter +=1;
|
||||
}
|
||||
|
||||
if display {
|
||||
println!("--------");
|
||||
|
||||
println!("finished with {} steps", counter);
|
||||
|
||||
self.display();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// [6,0,0,0,0,2,1,0,0], // has to backtrack
|
||||
// [0,3,2,9,0,0,0,7,0],
|
||||
// [0,0,0,0,0,8,0,0,0],
|
||||
// [2,0,0,0,0,0,4,0,0],
|
||||
// [7,0,3,0,0,0,9,1,0],
|
||||
// [0,8,0,0,9,4,0,0,0],
|
||||
// [0,0,4,0,0,0,6,0,0],
|
||||
// [1,2,0,7,0,0,0,0,5],
|
||||
// [0,0,0,0,0,0,0,9,4],
|
||||
|
||||
|
||||
fn main() {
|
||||
let sudoku_set: [[u8; 9]; 9] = [
|
||||
[6,0,0,0,0,2,1,0,0],
|
||||
[0,0,0,0,0,0,0,0,0],
|
||||
[0,3,2,9,0,0,0,7,0],
|
||||
[0,0,0,0,0,8,0,0,0],
|
||||
[2,0,0,0,0,0,4,0,0],
|
||||
|
@ -243,17 +241,5 @@ fn main() {
|
|||
|
||||
let mut sudoku = Sudoku::new(sudoku_set);
|
||||
|
||||
sudoku.display();
|
||||
|
||||
println!("--------");
|
||||
|
||||
sudoku.update_possibilities();
|
||||
|
||||
while sudoku.collapse() {
|
||||
sudoku.update_possibilities();
|
||||
}
|
||||
|
||||
println!("--------");
|
||||
|
||||
sudoku.display();
|
||||
sudoku.solve(true);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue