LinkedIn-Queens is a small, local Python solver for the LinkedIn-Queens, style puzzle. It reads a sample board from config.py, runs a backtracking solver (solver.py) with a handful of search heuristics, and visualizes the result with pygame (visualizer.py).
Note: This project does not interact with LinkedIn or any website. It solves only the puzzle data supplied locally in
config.py.
- Quick start
- Project structure
- Important Files
- Algorithm & heuristics ← detailed
- Example
- Future improvements
Requirements:
- Python 3.8+
pygame
Install pygame:
pip install -r requirements.txt
Run the solver:
git clone cd LinkedIn-Queens python main.py
main.py loads the sample board (from config.py), runs the solver, prints the solve time and, if a solution is found, launches the pygame visualizer.
LinkedIn-Queens/ ├── Queens-SampleCase/ # example boards (if present) ├── config.py # sample BOARD string, color mapping and RGB palette ├── parser.py # parseRegions(), buildGrid() ├── solver.py # solve(): backtracking + heuristics ├── visualizer.py # pygame visualizer ├── main.py # entrypoint: parse -> solve -> visualize └── requirements.txt # pygame
config.py: contains a multilineBOARDstring andCOLOR_MAP. TheBOARDuses single characters per cell;COLOR_MAPmaps those characters to human-readable region names (colors).parser.pyparseRegions(board, color_map)→ returns(regions, n)whereregionsis a dict mapping region_name → list of(r,c)cells andnis board size.buildGrid(board, color_map)→ converts the board into a grid of color-names for visualization.
solver.pysolve(n, regions)→ attempts to find a solution and returns an x nboolean grid with queens (orNone).
visualizer.py- Draws the colored board using
pygameand overlays"Q"for queen positions.
- Draws the colored board using
main.py- Calls
parseRegions, runssolve, prints the elapsed time, and callsvisualizeif a solution is found.
- Calls
This project solves the puzzle using recursive backtracking with several practical heuristics and lightweight forward-checking. Below is a precise, implementation-accurate description of what the solver enforces and how it guides search.
From the code in solver.py:
- The solver attempts to place exactly one queen per row (the
queensarray has lengthn, and the algorithm fills rows). - The following constraints are enforced when placing a queen at cell
(r, c):- Column uniqueness: no two queens share the same column. (tracked by
col_usedset) - Region requirement: each color/region must contain exactly one queen. The solver initializes
reqd[region] = 1for every region name and decrements it when a queen is placed in that region. A placement is invalid ifreqd[region] == 0. - Blocked cells (local neighborhood): when a queen is placed at
(r,c), the solver marks the 8 surrounding neighbours (one-cell king moves) as blocked (setblocked) and disallows future placements on those blocked cells. The solver does not implement full chess-style diagonal/ray attacks beyond column uniqueness and the immediate 8-cell neighborhood block.
- Column uniqueness: no two queens share the same column. (tracked by
- If all rows get filled respecting those constraints, the solver reports success and returns the boolean solution grid.
Important: The code's notion of attack/conflict is a combination of "no same column" plus "no cell in the one-cell surrounding neighborhood". This is the exact behavior implemented (see
col_usedandblocked).
The solver is a depth-first backtracker with the following heuristics to reduce search:
- Most Constrained Row (MRV over rows):
- At each recursion the solver picks the row
rthat currently has the fewest valid column choices . This is implemented ingetMostConstrainedRow()which callscountOptions(r)(counts valid columns for rowr) and chooses the row with the minimum options that is still empty. - If a row has
0options,getMostConstrainedRow()returns that row immediately so the backtracking layer sees the dead-end quickly. This gives early pruning.
- At each recursion the solver picks the row
- Move ordering using
countConstraints(r, c):- For the chosen row
r, the solver collects all valid columns(c)and computescountConstraints(r, c)for each candidate. countConstraintsestimates how many future cells (in rowsr+1..n-1) would remain available (and therefore how many potential placements remain) if you were to place a queen at(r, c). It iterates future rows and checks each candidate cell againstcol_used,reqdandblockedand increments a counter.- The solver then sorts candidate columns by that
countConstraintsvalue ascending and tries them in that order. This is an implementation detail that affects search; the sort key islambda x: x[1].
- For the chosen row
- Forward Checks and Local Pruning:
isValid(r,c)already performs the quick forward checks: column used? region already satisfied? cell blocked?- When placing a queen the solver updates:
col_used(fast column conflict tracking)reqd[region]decrement (ensures exactly one queen per region)blockedset for the immediate 8-neighbourhood cells (prevents placements adjacent to queens)
- On backtracking those changes are reverted.
- MRV (fewest options row) focuses search on the row most likely to fail, which often reduces the depth of unsuccessful exploration.
- Counting future options gives a (cheap) lookahead to prefer placements with predictable impacts on the remainder of the board; trying the more constraining placements first can either find a solution quickly if that placement is correct, or prune the search early if it causes a contradiction.
- Column set & blocked set are constant-time checks (set membership) and make validity checking cheap.
parse board -> regions (region_name -> list of cells) init reqd[region] = 1 init col_used = {}, blocked = set(), queens = [-1]*n backtrack(placed): pick row r with smallest number of valid columns (MRV) if all rows filled -> return True for each valid column c for r: try place queen at (r,c): mark queen, update col_used, reqd, blocked if backtrack(placed+1): return True undo changes return False
config.py contains a sample 16×16 test board under the variable BOARD and a COLOR_MAP. Running python main.py will print something like:
Solving 16x16 board with16 regions... Solution found in0.12345 seconds
…and then open the pygame window that draws each region in its color and overlays a Q where queens were placed.
- Add a CLI to load different boards (JSON/CSV) and batch-run test cases.
- Add unit tests and a CI workflow.
- Make it into a chrome extension to solve the board directly in your browser