Skip to main content

Generator and human-style solver for LinkedIn-Queens / Star Battle puzzles.

Project description

queens-generator

Generator and human-style solver for LinkedIn-Queens / Star Battle puzzles.

The package is named speed_stars (the original internal name) for backward compatibility with existing consumers; the project distribution is named queens-generator to match the player-facing brand.

This logic creates puzzles for Pemdas and validates community-submitted puzzles on Queens Puzzle Maker.

The generator refuses to ship any puzzle it can't solve without backtracking, using a hand-coded set of human deduction rules. When deduction stalls, instead of regenerating, it mutates the zone boundaries of the existing puzzle until deduction succeeds.

For the long-form write-up — why uniqueness isn't enough, how the deduction rules are ordered, why the generator refines instead of regenerates — see DESIGN.md.

Install

pip install queens-generator
# or, from a checkout:
pip install -e .

Usage

from speed_stars import generate_speed_stars_puzzle

puzzle = generate_speed_stars_puzzle(grid_size=6)

puzzle.zone_grid is a list-of-lists where each integer is a region ID:

[[1, 5, 5, 5, 5, 5],
 [1, 1, 5, 5, 5, 5],
 [4, 4, 4, 5, 2, 5],
 [5, 5, 5, 5, 2, 3],
 [5, 5, 0, 5, 2, 3],
 [5, 0, 0, 3, 3, 3]]

puzzle.star_positions is the unique solution — one star per row, column, and region:

[Position(x=0, y=0), Position(x=1, y=3), Position(x=2, y=1),
 Position(x=3, y=4), Position(x=4, y=2), Position(x=5, y=5)]

puzzle.deductions is the ordered sequence of human-style steps that solve the puzzle, each with a natural-language reason. The first few for the puzzle above:

Deduction(cells=[Position(2,3), Position(2,4), Position(2,5)],
          state='crossedOut',
          reason='row 3 can only have a star in {zone_4}')
Deduction(cells=[Position(0,4), Position(1,4), Position(5,4)],
          state='crossedOut',
          reason='column 5 can only have a star in {zone_2}')
Deduction(cells=[...8 cells...],
          state='crossedOut',
          reason='{zone_1}, {zone_5} must have stars in rows 1, 2')

The deduction list is also what powers in-app hints: each Deduction is explainable to a player without revealing the solution.

Difficulty

The generator discards puzzles that are too trivial. The thresholds are profiled per grid size in speed_stars/generate.py:

grid size min solve rounds min cell deductions
5 3 12
6 3 14
7 3 17
8 3 18
9 3 12
10–12 4 15

The thresholds count work done by the propagation solver (solve_speed_stars), which is what the generator uses to decide whether a puzzle is uniquely solvable without backtracking. The explainable Deduction list returned to the player is built by a separate pass (generate_deductions) that shares the same rules but reorders them by how easy they are for a human to spot.

  • Rounds is how many passes the propagation solver makes through the grid before it stops finding new deductions. Each pass applies subset elimination then per-cell checks; below the threshold the puzzle falls open in a sweep or two and isn't interesting.
  • Cell deductions counts the per-cell branches specifically — subset-elimination steps (N rows spanning N zones) are tracked separately and don't count, since they're easier for humans to spot. The threshold forces each puzzle to also demand the harder per-cell reasoning.
  • Zone size: independent of grid size, every zone must have at least 3 cells (MIN_ZONE_SIZE). Smaller zones produce one-step "only cell left" deductions that aren't interesting.

A puzzle that solves but fails any threshold is discarded; generation retries from scratch with a fresh zone layout. Zone-boundary refinement only runs to make unsolvable puzzles solvable, never to make easy puzzles harder.

The thresholds are exposed and overridable:

from speed_stars import generate_speed_stars_puzzle, RECOMMENDED_THRESHOLDS

# Use the profiled defaults
puzzle = generate_speed_stars_puzzle(grid_size=8)

# Override for a specific run (e.g., easier 8x8 for a tutorial pack)
puzzle = generate_speed_stars_puzzle(grid_size=8, min_rounds=2, min_deductions=10)

Grid sizes outside the profiled range fall back to the nearest known size via get_default_thresholds.

Tests

pip install -e .[dev]
python -m pytest tests/

License

MIT.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

queens_generator-0.1.0.tar.gz (22.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

queens_generator-0.1.0-py3-none-any.whl (20.2 kB view details)

Uploaded Python 3

File details

Details for the file queens_generator-0.1.0.tar.gz.

File metadata

  • Download URL: queens_generator-0.1.0.tar.gz
  • Upload date:
  • Size: 22.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.2

File hashes

Hashes for queens_generator-0.1.0.tar.gz
Algorithm Hash digest
SHA256 56bd415b0824afa6f8b7697c2b2a1c7d010891ebd61670fc646473435e060d3a
MD5 feb1466044dd1c7ead536e0015d754d3
BLAKE2b-256 2428b0da9be6e94a417a352bd818851cddc0aafd3ad9bcf8c00b4b1d577b3291

See more details on using hashes here.

File details

Details for the file queens_generator-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for queens_generator-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d87540e60a154e6bf23103f08dd4f02ee67fada65e1b96ad7d4de057c1c6a8fd
MD5 b5d93e2d7d5620c953c1a8b88bb4f678
BLAKE2b-256 520e0483c0e8379cec78d57e2ed2c17095e2dd2a21898adf61169a530487a6e5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page