Skip to content
Sup2point0Public

About

Pure logic algorithm for solving Skyscrapers puzzles

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

116 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ascendant

An automated solver for Skyscrapers↗ puzzles, relying only on pure logic.

For a rundown of the algorithm, jump to § Algorithm. For an explanation of how Skyscrapers puzzles work, I have a quickfire explanation on Skyscraping↗.

Example

show
pass #0:
   |    4    |    3    |    2    |    2    |    1    |
---------------------------------------------------------
 4 | [12345] | [12345] | [12345] | [12345] | [12345] | 1
 3 | [12345] | [12345] | [12345] | [12345] | [12345] | 2
 2 | [12345] | [12345] | [12345] | [12345] | [12345] | 3
 1 | [12345] | [12345] | [12345] | [12345] | [12345] | 2
 3 | [12345] | [12345] | [12345] | [12345] | [12345] | 2
---------------------------------------------------------
   |    2    |    2    |    2    |    1    |    3    |

pass #1:
   |    4    |    3    |    2    |    2    |    1    |
---------------------------------------------------------
 4 | [   12] | [  123] | [ 1234] |    4    |    5    | 1
 3 | [   23] |    4    |    5    | [   12] | [   23] | 2
 2 |    4    |    5    | [ 1234] | [  123] | [  123] | 3
 1 |    5    | [  123] | [  123] | [  123] |    4    | 2
 3 | [  123] | [ 1234] | [ 1234] |    5    | [  123] | 2
---------------------------------------------------------
   |    2    |    2    |    2    |    1    |    3    |

pass #2:
   |    4    |    3    |    2    |    2    |    1    |
---------------------------------------------------------
 4 |    1    |    3    | [  123] |    4    |    5    | 1
 3 | [   23] |    4    |    5    |    1    | [   23] | 2
 2 |    4    |    5    | [  123] | [  123] | [  123] | 3
 1 |    5    | [   12] | [  123] | [  123] |    4    | 2
 3 | [   23] |    2    |    4    |    5    |    1    | 2
---------------------------------------------------------
   |    2    |    2    |    2    |    1    |    3    |

pass #3:
   |    4    |    3    |    2    |    2    |    1    |
---------------------------------------------------------
 4 |    1    |    3    |    2    |    4    |    5    | 1
 3 |    2    |    4    |    5    |    1    |    3    | 2
 2 |    4    |    5    |    1    |    3    |    2    | 3
 1 |    5    |    1    |    3    |    2    |    4    | 2
 3 |    3    |    2    |    4    |    5    |    1    | 2
---------------------------------------------------------
   |    2    |    2    |    2    |    1    |    3    |

Run

Clone the repository:

> git clone https://github.com/Sup2point0/ascendant

[!Important] You will need Rust nightly↗ since the project uses generic_const_exprs.

See the algorithm in action:

ascendant> cargo run -- solve-one 7 --diff=2 --random-date

See what else you can do:

ascendant> cargo run -- --help

Features

Fetch puzzles:

# fetch 6x6 puzzles of all difficulties
ascendant> cargo run -- fetch --sizes 6 --diffs 1 2 3

Solve puzzles in bulk and view stats:

# solve all 4x4, 5x5, 6x6 puzzles of difficulty 3
ascendant> cargo run -- solve-all --sizes 4 5 6 --diffs 3

View the steps in solving one puzzle:

# solve the 7x7 full hard (difficulty 2) puzzle from April 1, showing all solution substeps
ascendant> cargo run -- solve-one 7 --diff=2 --date=0401 --debug

Progress

Full puzzles have clues along every lane in both directions. Sparse puzzles have much fewer clues, and are significantly more difficult. Bear in mind most human-oriented puzzles1 are sparse 5x5 or 6x6 ;)

size difficulty solved time as of
4x4 full 365/365 ~0.5 s 2026 January
sparse 256/365 ^ 2026 January
5x5 full easy 365/365 ~1.5 s 2026 January
full hard 365/365 ^ 2026 January
sparse 93/365 ^ 2026 January
6x6 full easy 359/365 ~4.5 s 2026 January
full hard 355/365 ^ 2026 January
sparse 23/365 ^ 2026 January
7x7 full easy 331/365 ~3.5 s 2026 January
full hard 335/365 ^ 2026 January
8x8 full easy 321/365 ~7.5 s 2026 January
full hard 310/365 ^ 2026 January

Note

7x7 and 8x8 are taking less time currently since I haven't tried the solver on Sparse puzzles for those sizes yet!

Notes

show
  • The algorithm is not strong at all on sparse puzzles, although it is fairly impressive how far it can get on sparse 5x5 puzzles.
    • Only 23/365 on the sparse 6x6 puzzles... 🤣
    • 4x4 sparse puzzles are quite specially intractable, simply down to how barren information is – some puzzles only have, like, 3 clues!
  • Despite the increase in information with larger puzzle sizes, the increase in complexity is much more significant.
    • That being said, the algorithm often reaches an almost-solved state.
    • I’m currently figuring out how to improve the algorithm to handle these final near-solved states. Many of them need only a single push before the rules of Sudoku can clear the rest of the puzzle!
  • I’m still torn over whether to implement a weak version of lane-isolated backtracking, because humans can do this mentally, so it's arguably not beyond the reach of “logic”. But it’s so ambiguous...

Algorithm

I affectionally call it peak descent!

Outline

The solving algorithm is iterative – it’ll keep passing over the grid, trying to make logical deductions, until it can no longer find any.

These are the steps in each pass-through:2

  • Ascent: Use the clues to establish a foundation of candidates for each cell.
    • e.g. A lane $\text{4 | \_ \_ \_ \_ \_ \_ |}$ in a 6x6 puzzle could start with any of $[123]$, but not $[456]$.
  • Peak Descent: Enforce ascending sequences by descending peaks.
    • If a peak has been found in a lane, step down from the peak towards the clue, calculating how many skyscrapers are currently guaranteed to be visible.
    • Subtract this from the clue to find how many more skyscrapers should be visible in front of the first peak.
    • Use this to restrict the candidates of the sequence.
      • e.g. In a lane $\text{4 | \_ \_ 4 \_ 6 5 |}$ this deduces $\text{4 | [12] [23] 4 \_ 6 5 |}$.
      • e.g. In a lane $\text{3 | \_ \_ \_ 5 \_ 6 |}$ this deduces $\text{3 | [4] [123] [123] 5 \_ 6 |}$.
  • Sudoku: Eliminate invalid candidates by the rules of Sudoku.
    • e.g. A lane $\text{| 3 [36] [123] \_ \_ \_ |}$ can be eliminated to $\text{| 3 [6] [12] \_ \_ \_ |}$.
  • Pinpoint: Mark cells which are the only place in their lane for a digit to go as solved.
    • e.g. A lane $\text{| [123] [23] [24] [34] 5 6 |}$ can be solved to $\text{| 1 [23] [24] [34] 5 6 |}$.
  • Isolate: Eliminate candidates outside of ‘isolated’ groups (couples, triplets, etc.)
    • Two $[12]$ cells between them are guaranteed to use both $1$ and $2$.
      • We might not know which way round, but we can still deduce that $1$ and $2$ cannot go in any other cells in the lane.
    • This can be thought of as a ‘pseudo-pinpoint’ followed by sudoku elimination.
    • e.g. A lane $\text{| [12] [12] [123] [26] \_ \_ |}$ can be eliminated to $\text{| [12] [12] [3] [6] \_ \_ |}$.
  • Solve: Mark cells with only 1 candidate left as solved.

Terminology

See the Glossary on Skyscraping↗.

Development

Future strategies to implement include:

  • Twin/triplet/... elimination: 2 $[xy]$ cells eliminate $x$ and $y$ as candidates from all other cells in the lane.
    • (more advanced) Closed set elimination: Any set of cells which between them consume $[xyz...]$ eliminate $[xyz]$ as candidates from all other cells in the lane.
  • Solve cells with 2 candidates where one would be visible and the other obscured.

Philosophy

  • The goal is to get as far as possible with purely logical deductions, i.e. no ‘guesswork’ or ‘backtracking’. Even though guesswork isn’t well-defined↗...
  • The strategies I plan on implementing are mostly those covered in Skyscraping↗.
  • If we stick firmly to this, then we may be able to also generate new skyscrapers puzzles!

Footnotes

  1. After many years solving Skyscrapers (on-off, granted), I can speedrun some sparse 5x5, am alright with sparse 6x6, and am starting to solve some sparse 7x7s. ↩

  2. The algorithm steps are executed in this order to optimise deduction rate, but you could theoretically use any order. ↩

About

Pure logic algorithm for solving Skyscrapers puzzles

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages