Skip to main content

The puzzle model

Houses, cages, rules and candidates: the puzzle the solver works on. Generated from the comments in the headers by Doxygen and tools/gen_cpp_reference.py; public members only.

model.hpp​

csrc/model.hpp

Constraint-agnostic puzzle model: cells, houses, relations, n-ary constraints (built from pencilmark/model.py).

Constraint kinds: AllDiff groups complete (houses: exactly D cells, every digit once) or partial (cages), optionally carrying a sum pair relations exclusion tables rel_ex[a][b][v] = digits excluded at b when a == v (non-consecutive, thermo, kropki, XV, whispers, ... all reduce to this) neq pairs anti-knight / anti-king style "different" links domains per-cell allowed-digit masks

Everything downstream works on these four primitives only; extensions (arrow sums, generic AIC link graphs, ...) add new primitives here plus strategies that consume them (see strategy.hpp).

struct Group​

source

Fields

  • cells std::vector< int >
  • complete bool
  • has_total bool
  • total int
  • shape double
  • name std::string
  • kind std::string — grader Group.kind ('row' 'col' 'box' 'region' 'diag' 'window' 'cage' ...)

struct RelSpec​

source

a == v excludes fwd[v] at b; b == v excludes bwd[v] at a.

Tables have D+1 entries (index 0 unused). neq relations carry no tables.

Fields

  • a int
  • b int
  • neq bool
  • fwd std::vector< uint32_t >
  • bwd std::vector< uint32_t >

struct InnieSet​

source

Fields

  • hi int
  • cells std::vector< int >
  • total int
  • cages std::vector< int >
  • outie bool
  • houses std::vector< int > — the house union defining the region

struct Puzzle​

source

NameWhat it does
finalizebuilds the derived tables (counts, peers, bitsets, innies, implied houses) once the groups are filled in
rectsunique-rectangle candidates: four cells in two lines and two boxes, from the structure alone
peers
neqb
relb
gbits
rel_exrel_ex[x][y] table (y must be a relation partner of x)

Fields

  • uid uint64_t
  • D int
  • coords std::vector< std::pair< int, int > >
  • groups std::vector< Group >
  • domains std::vector< uint32_t > — empty -> all full
  • relations std::vector< RelSpec >
  • nary_specs std::vector< NSpec > — n-ary constraints (grader Puzzle.constraints)
  • N int
  • G int
  • W int
  • full uint32_t
  • houses std::vector< int >
  • groups_of std::vector< std::vector< int > >
  • neq std::vector< std::vector< int > > — CPython set iteration order of p.neq[c].
  • rel std::vector< std::vector< int > > — CPython set iteration order of p.nonconsec[c].
  • rel_out std::vector< std::vector< uint32_t > > — rel_out[c][j*(D+1)+v] = rel_ex[c][rel[c][j]][v]; rel_in = rel_ex[rel[c][j]][c][v]
  • rel_in std::vector< std::vector< uint32_t > >
  • rel_sorted_j std::vector< std::vector< int > > — indices j of rel[c] sorted by partner
  • rel_dir std::vector< std::vector< int8_t > > — rel_dir[c][j]: +1 partner rel[c][j] is strictly greater than c, -1 strictly smaller, 0 other
  • peer_list std::vector< std::vector< int > > — sorted
  • peer_bits std::vector< uint64_t >
  • neq_bits std::vector< uint64_t >
  • rel_bits std::vector< uint64_t >
  • group_bits std::vector< uint64_t >
  • group_overlap std::vector< char > — G*G, cells shared.
  • group_line std::vector< int > — 0 row, 1 column (same coordinate), 2 other (box/region/diagonal...)
  • group_cat std::vector< int > — GroupCat.
  • has_cages bool
  • sum_cages std::vector< int >
  • innies std::vector< InnieSet >
  • house_unions std::vector< std::vector< int > > — for inspection / tests
  • nary std::vector< NConstraint > — from nary_specs (same order)
  • cage_nary std::vector< NConstraint > — sum-cage groups as sum constraints (combo-lock)
  • big_innies std::vector< InnieSet > — rule-of-45 regions of 5..BIG_INNIE_MAX cells
  • innie_nary std::vector< NConstraint > — ... as derived sum constraints
  • line_windows std::vector< NConstraint > — 3-cell windows of longer pairwise lines (LineScan)
  • implied std::shared_ptr< Puzzle > — Puzzle copy with implied complete houses (unions of parallel lines minus disjoint houses inside them, iterated twice: windoku hidden windows, jigsaw leftover regions) and law-of-leftovers same-multiset constraints appended; null when nothing is implied. Built by finalize().
  • canonical std::shared_ptr< Puzzle > — copy with exact (integer-moment) shapes for canonical solving; its own implied is built too. null on derived copies.
  • exact_shapes bool
  • base_G int — groups [base_G, G) are implied houses (in implied)
  • base_nary int — nary_specs [base_nary, ...) are derived leftovers
  • is_derived bool
  • BIG_INNIE_MAX const size_t

void finalize()​

source

builds the derived tables (counts, peers, bitsets, innies, implied houses) once the groups are filled in

const std::vector< Rect > & rects() const​

source

unique-rectangle candidates: four cells in two lines and two boxes, from the structure alone

const uint64_t * peers(int c) const​

source

No comment.

const uint64_t * neqb(int c) const​

source

No comment.

const uint64_t * relb(int c) const​

source

No comment.

const uint64_t * gbits(int g) const​

source

No comment.

const uint32_t * rel_ex(int x, int y) const​

source

rel_ex[x][y] table (y must be a relation partner of x)

struct Puzzle::Rect​

source

unique-rectangle candidates (structure only), computed once on demand

Fields

  • c int[4] — A B / C D: A-B and C-D share groups, A-C and B-D share groups.

struct Puzzle::RectCache​

source

Fields

  • once std::once_flag
  • rects std::vector< Rect >