diff --git a/Cargo.toml b/Cargo.toml index 9578e68..4d58beb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,11 @@ version = "0.1.0" authors = ["ddidderr "] edition = "2021" +[lints.clippy] +pedantic = { level = "warn", priority = -1 } +todo = "warn" +unwrap_used = "warn" + [dependencies] [profile.release] diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..e270811 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,3 @@ +group_imports = "StdExternalCrate" +imports_granularity = "Crate" +imports_layout = "HorizontalVertical" diff --git a/src/main.rs b/src/main.rs index 8562b1b..7084c77 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,10 +4,26 @@ const BLOCK_SIZE: usize = 3; const SIZE: usize = BLOCK_SIZE * BLOCK_SIZE; const NUM_FIELDS: usize = SIZE * SIZE; +fn print_gray() { + print!("\x1b\x5b\x31\x3b\x33\x30\x6d"); +} + +fn print_green() { + print!("\x1b\x5b\x31\x3b\x33\x32\x6d"); +} + +fn print_neutral() { + print!("\x1b\x5b\x31\x3b\x30\x6d"); +} + +fn print_clear() { + print!("\x1b\x5b\x48\x1b\x5b\x32\x4a"); +} + struct SField { field: Vec, - skipf: Vec, - skipb: Vec, + skip_forward: Vec, + skip_backward: Vec, pos: usize, possible_values: Vec>, } @@ -27,6 +43,22 @@ impl SField { 0,0,8,2,0,0,0,6,0, ]; + let mut sudoku = SField { + field, + skip_forward: vec![0; NUM_FIELDS + 1], + skip_backward: vec![0; NUM_FIELDS + 1], + pos: 0, + possible_values: vec![vec![]; NUM_FIELDS], + }; + + sudoku.build_possible_values_db(); + + sudoku.build_skip_dbs(); + + sudoku + } + + fn build_skip_dbs(&mut self) { fn find_fixed_streak_forward(mut idx: usize, field: &[u8]) -> u8 { let mut fixed_count = 1; idx += 1; @@ -51,29 +83,21 @@ impl SField { fixed_count } - let mut skipf = vec![0; NUM_FIELDS + 1]; - for (idx, nr) in field.iter().enumerate() { + let fwd = &mut self.skip_forward; + for (idx, nr) in self.field.iter().enumerate() { match nr { - 0 => skipf[idx] = *nr, - _ => skipf[idx] = find_fixed_streak_forward(idx, &field), + 0 => fwd[idx] = *nr, + _ => fwd[idx] = find_fixed_streak_forward(idx, &self.field), } } - let mut skipb = vec![0; NUM_FIELDS + 1]; - for (idx, nr) in field.iter().enumerate().rev() { + let bwd = &mut self.skip_backward; + for (idx, nr) in self.field.iter().enumerate().rev() { match nr { - 0 => skipb[idx + 1] = *nr, - _ => skipb[idx + 1] = find_fixed_streak_backward(idx, &field), + 0 => bwd[idx + 1] = *nr, + _ => bwd[idx + 1] = find_fixed_streak_backward(idx, &self.field), } } - - SField { - field, - skipf, - skipb, - pos: 0, - possible_values: vec![vec![]; SIZE * SIZE], - } } fn build_possible_values_db(&mut self) { @@ -84,7 +108,7 @@ impl SField { self.pos = idx; // try all values between 1 and =self.size and remember the good ones let mut good_ones = Vec::with_capacity(SIZE); - for nr in 1..=(SIZE as u8) { + for nr in 1..=(u8::try_from(SIZE).expect("SIZE is too big")) { if self.ok(nr) { good_ones.push(nr); } @@ -101,9 +125,9 @@ impl SField { if !self.put_valid_nr() { self.clear_current_field(); if !self.prev() { - self.print_clear(); + print_clear(); self.print(); - println!("Number of solutions: {}", num_solutions); + println!("Number of solutions: {num_solutions}"); break; } continue; @@ -112,9 +136,9 @@ impl SField { if !self.next() { num_solutions += 1; if num_solutions % 10_000 == 0 { - self.print_clear(); + print_clear(); self.print(); - println!("Number of solutions: {}", num_solutions); + println!("Number of solutions: {num_solutions}"); } self.clear_current_field(); @@ -125,22 +149,6 @@ impl SField { num_solutions > 0 } - fn print_gray(&self) { - print!("\x1b\x5b\x31\x3b\x33\x30\x6d"); - } - - fn print_green(&self) { - print!("\x1b\x5b\x31\x3b\x33\x32\x6d"); - } - - fn print_neutral(&self) { - print!("\x1b\x5b\x31\x3b\x30\x6d"); - } - - fn print_clear(&self) { - print!("\x1b\x5b\x48\x1b\x5b\x32\x4a"); - } - fn print(&self) { for i in 0..NUM_FIELDS { if i != 0 && i % SIZE == 0 { @@ -148,15 +156,15 @@ impl SField { } if i == self.pos { - self.print_green(); + print_green(); } else if self.get_field_at_pos(i) == 0 { - self.print_gray(); + print_gray(); } print!("{:2} ", self.get_field_at_pos(i)); if i == self.pos || self.get_field_at_pos(i) == 0 { - self.print_neutral(); + print_neutral(); } } println!(); @@ -174,7 +182,7 @@ impl SField { // so self.pos can safely be used to index here let possible_vals = &self.possible_values[self.pos]; - for nr in possible_vals.iter() { + for nr in possible_vals { if *nr <= current_nr { continue; } @@ -246,7 +254,7 @@ impl SField { } fn next(&mut self) -> bool { - let new_pos = self.pos + 1 + self.skipf[self.pos + 1] as usize; + let new_pos = self.pos + 1 + self.skip_forward[self.pos + 1] as usize; if new_pos >= NUM_FIELDS { return false; @@ -257,7 +265,7 @@ impl SField { } fn prev(&mut self) -> bool { - let new_pos = self.pos - 1 - self.skipb[self.pos] as usize; + let new_pos = self.pos - 1 - self.skip_backward[self.pos] as usize; if new_pos >= NUM_FIELDS { return false; @@ -276,17 +284,7 @@ impl SField { } } -fn run() -> Result<(), String> { - let mut field = SField::new(); - - field.build_possible_values_db(); - - field.solve(); - Ok(()) -} - fn main() { - if let Err(e) = run() { - println!("{}", e) - } + let mut field = SField::new(); + field.solve(); }