Optimized backtracking solver for the 42 Paris Rush01 puzzle.
v1.2.0 introduces early pruning based on partial visibility counts, achieving sub-millisecond solves up to 9Γ9.
This project is part of the 42 Piscine / Rush series. It solves the classic Skyscrapers puzzle (a.k.a. Rush01): fill an nΓn grid with values 1..n so that each row/column contains all numbers once, and each side clue indicates how many βbuildingsβ are visible from that side.
- Parse command-line input of
4*nedge clues (top, bottom, left, right). - Pre-fill obvious values before backtracking:
- If clue =
nβ the entire row/column is{1..n}in the correct direction. - If clue =
1β the first cell on the clue side is set ton.
- If clue =
- Early pruning based on partial visibility counts:
- Dynamically check partial rows/columns against their visibility clues.
- Stop recursion early when the current state can no longer match the clue.
- Print the resulting grid to
stdout, orError\nwhen no solution exists or input is invalid. - Keep the code Norm-friendly and simple for learning/debugging.
.
βββ CHANGELOG.md
βββ ex00
βΒ Β βββ includes
βΒ Β βΒ Β βββ args.h
βΒ Β βΒ Β βββ check.h
βΒ Β βΒ Β βββ fix_max.h
βΒ Β βΒ Β βββ fix_min.h
βΒ Β βΒ Β βββ map.h
βΒ Β βΒ Β βββ print.h
βΒ Β βΒ Β βββ run.h
βΒ Β βΒ Β βββ rush01.h
βΒ Β βΒ Β βββ solve.h
βΒ Β βΒ Β βββ types.h
βΒ Β βββ Makefile
βΒ Β βββ srcs
βΒ Β βββ args.c
βΒ Β βββ check.c
βΒ Β βββ main.c
βΒ Β βββ map.c
βΒ Β βββ print.c
βΒ Β βββ run.c
βΒ Β βββ solver
βΒ Β βββ fix_max.c
βΒ Β βββ fix_min.c
βΒ Β βββ solve.c
βββ README.md
βββ rush01.en.subject.pdf
βββ tests.txt
Subject included: rush01.en.subject.pdf
From ex00/:
make
# produces ./rush-01Clean targets:
make clean # remove objects
make fclean # remove objects + binary
make re # full rebuildThe program expects 4*n clues (top, bottom, left, right order) as a single argument list.
Example for 6Γ6:
./rush01 "6 5 4 3 2 1 1 2 2 2 2 2 6 5 4 3 2 1 1 2 2 2 2 2"Successful output prints the solved grid:
1 2 3 4 5 6
2 3 4 5 6 1
3 4 5 6 1 2
4 5 6 1 2 3
5 6 1 2 3 4
6 1 2 3 4 5
On invalid/unsatisfiable inputs, prints Error\n.
Tip: See
tests.txtfor ready-to-run samples.
Results measured on the authorβs machine (macOS / Apple M4 / Xcode Time Profiler / main() execution time):
| Size | v1.0.0 (baseline) | v1.1.0 (obvious values) | v1.2.0 (early pruning) |
|---|---|---|---|
| 3Γ3 | < 1 ms | < 1 ms | < 1 ms |
| 4Γ4 | < 1 ms | < 1 ms | < 1 ms |
| 5Γ5 | < 1 ms | < 1 ms | < 1 ms |
| 6Γ6 | 66 ms | 4 ms | < 1 ms |
| 7Γ7 | ~600 000 ms | ~5 000 ms | < 1 ms |
| 8Γ8 | > 30 min | > 30 min | < 1 ms |
| 9Γ9 | > 30 min | > 30 min | < 1 ms |
v1.1.0 added a pre-filling of obvious values (for clue = 1 and clue = n). v1.2.0 introduces real-time pruning of impossible branches using partial visibility checks.
With this, the solver reaches sub-millisecond performance up to 9Γ9 grids. β‘οΈ
βFrom brute force to elegance β one segfault at a time.β π§