Skip to content

Commit

Permalink
Document more modules
Browse files Browse the repository at this point in the history
  • Loading branch information
dharkness committed May 29, 2023
1 parent 9d112f5 commit 1a406fc
Show file tree
Hide file tree
Showing 9 changed files with 47 additions and 28 deletions.
4 changes: 3 additions & 1 deletion src/layout.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
//! Combines the various pieces that make up a Sudoku puzzle.

mod cells;
mod houses;
mod knowns;

pub use cells::{Bit, Bits, Cell, Rectangle, Set as CellSet};
pub use cells::{Bits, Cell, Rectangle, Set as CellSet};
pub use houses::{Coord, House, Shape};
pub use knowns::{Known, Set as KnownSet};
3 changes: 2 additions & 1 deletion src/layout/cells.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
///! Provides Cell and Set to track collections of cells and methods to manipulate them.
//! Provides [`Cell`] and [`Set`] to track collections of cells and methods to manipulate them.

mod bit;
mod cell;
mod label;
Expand Down
6 changes: 6 additions & 0 deletions src/layout/houses.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
//! [`House`]s are the nine rows, columns and boxes (also called blocks)
//! that make up the [`Board`][crate::puzzle::Board].
//!
//! Each [`House`] has a [`Shape`] and a unique [`Coord`].
//! In a valid puzzle, each `House` must contain exactly one of each [`Known`][crate::layout::Known].

mod coord;
mod house;
mod shape;
Expand Down
2 changes: 2 additions & 0 deletions src/layout/knowns.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Provides [`Known`] and [`Set`] to track collections of knowns and methods to manipulate them.

mod known;
mod set;

Expand Down
2 changes: 2 additions & 0 deletions src/play.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Provides a text-based interface for creating and playing Sudoku puzzles.

use std::io::{stdout, Write};

use crate::layout::{Cell, Known};
Expand Down
2 changes: 2 additions & 0 deletions src/printers.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Provides functions for printing the state of a puzzle to the console.

use crate::layout::{House, Known};
use crate::puzzle::Board;

Expand Down
4 changes: 4 additions & 0 deletions src/puzzle.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
//! Provides the [`Board`] for tracking the state of a puzzle,
//! the [`Action`]s that can be taken to solve it,
//! and any [`Error`]s that arise due to those actions.

mod action;
mod board;
mod effects;
Expand Down
50 changes: 24 additions & 26 deletions src/puzzle/board.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@ use super::{Effects, Error, Strategy};
/// Tracks the full state of a puzzle in play.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Board {
// Cells that were solved at the start.
givens: CellSet,
// Solved cells.
knowns: CellSet,
// Values for all cells.
values: [u8; 81],
known_candidates: [KnownSet; 81],
cell_candidates: [CellSet; 9],
cell_knowns: [CellSet; 9],
valid: bool,
// Knowns that are still possible for each cell.
candidate_knowns: [KnownSet; 81],
// Cells that are still possible for each known.
candidate_cells: [CellSet; 9],
// Cells that have been solved for each known.
known_cells: [CellSet; 9],
}

impl Board {
Expand All @@ -23,10 +28,9 @@ impl Board {
givens: CellSet::empty(),
knowns: CellSet::empty(),
values: [Known::UNKNOWN; 81],
known_candidates: [KnownSet::full(); 81],
cell_candidates: [CellSet::full(); 9],
cell_knowns: [CellSet::empty(); 9],
valid: true,
candidate_knowns: [KnownSet::full(); 81],
candidate_cells: [CellSet::full(); 9],
known_cells: [CellSet::empty(); 9],
}
}

Expand Down Expand Up @@ -54,37 +58,32 @@ impl Board {
self.knowns.is_full()
}

pub fn is_valid(&self) -> bool {
self.valid
}

pub fn all_candidates(&self, cells: CellSet) -> KnownSet {
cells
.iter()
.fold(KnownSet::empty(), |acc, cell| acc | self.candidates(cell))
}

pub fn candidates(&self, cell: Cell) -> KnownSet {
self.known_candidates[cell.usize()]
self.candidate_knowns[cell.usize()]
}

pub fn is_candidate(&self, cell: Cell, known: Known) -> bool {
self.known_candidates[cell.usize()][known]
self.candidate_knowns[cell.usize()][known]
}

pub fn remove_candidate(&mut self, cell: Cell, known: Known, effects: &mut Effects) -> bool {
let knowns = &mut self.known_candidates[cell.usize()];
let knowns = &mut self.candidate_knowns[cell.usize()];
if knowns[known] {
// println!("remove candidate {} from {}", known, cell);
*knowns -= known;
if knowns.is_empty() {
self.valid = false;
effects.add_error(Error::UnsolvableCell(cell));
} else if knowns.size() == 1 {
effects.add_set(Strategy::NakedSingle, cell, knowns.iter().next().unwrap());
}

let cells = &mut self.cell_candidates[known.usize()];
let cells = &mut self.candidate_cells[known.usize()];
debug_assert!(cells[cell]);
*cells -= cell;
self.remove_candidate_cell_from_houses(cell, known, effects);
Expand All @@ -100,13 +99,12 @@ impl Board {
known: Known,
effects: &mut Effects,
) {
let all_candidates = self.cell_candidates[known.usize()];
let all_candidates = self.candidate_cells[known.usize()];
for house in cell.houses() {
let house_cells = house.cells();
if (self.cell_knowns[known.usize()] & house_cells).is_empty() {
if (self.known_cells[known.usize()] & house_cells).is_empty() {
let candidates = all_candidates & house_cells;
if candidates.is_empty() {
self.valid = false;
effects.add_error(Error::UnsolvableHouse(house, known));
} else if candidates.size() == 1 {
effects.add_set(
Expand Down Expand Up @@ -145,17 +143,17 @@ impl Board {

self.values[cell.usize()] = known.value();
self.knowns += cell;
self.cell_knowns[known.usize()] += cell;
self.cell_candidates[known.usize()] -= cell;
self.known_cells[known.usize()] += cell;
self.candidate_cells[known.usize()] -= cell;

let candidates = self.known_candidates[cell.usize()] - known;
self.known_candidates[cell.usize()] = KnownSet::empty();
let candidates = self.candidate_knowns[cell.usize()] - known;
self.candidate_knowns[cell.usize()] = KnownSet::empty();
for known in candidates.iter() {
self.cell_candidates[known.usize()] -= cell;
self.candidate_cells[known.usize()] -= cell;
self.remove_candidate_cell_from_houses(cell, known, effects);
}

for neighbor in (self.cell_candidates[known.usize()] & cell.neighbors()).iter() {
for neighbor in (self.candidate_cells[known.usize()] & cell.neighbors()).iter() {
effects.add_erase(Strategy::Neighbor, neighbor, known);
}

Expand Down
2 changes: 2 additions & 0 deletions src/solvers.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
//! Provides various strategies for solving Sudoku puzzles.

pub mod deadly_rectangles;
pub mod intersection_removals;

0 comments on commit 1a406fc

Please sign in to comment.