Gallery Ceiling Sensors

HardbacktrackingAlso known as N-Queens II

An art gallery is fitting motion sensors to a square ceiling made of n × n panels. Each sensor sends beams along its row of panels, its column, and both diagonals, all the way to the walls. If a beam reaches another sensor, the two set each other off, so no two sensors may share a row, a column or a diagonal.

Some panels are glass skylights. Nothing can be mounted on glass, but beams pass straight through it. The gallery needs exactly n sensors and wants to know how many different layouts are possible before choosing one.

Your task

Write countLayouts(ceiling). ceiling is a list of n strings of length n; ceiling[r][c] is '.' for a normal panel and '#' for a skylight. Return the number of ways to place n sensors on normal panels so that no two share a row, a column or a diagonal.

Two layouts are different if some panel has a sensor in one and not in the other. Skylights do not block beams. If no layout exists, return 0.

countLayouts(ceiling: string[]) → int

Examples

Example 1
Input
ceiling = ["....", "....", "....", "...."]
Output
2
Why

There are exactly two layouts on an open 4 × 4 ceiling. Writing the sensor's column for each row, they are 1, 3, 0, 2 and its mirror image 2, 0, 3, 1. Every other try puts two sensors on a shared column or diagonal.

Example 2
Input
ceiling = [".#..", "....", "....", "...."]
Output
1
Why

The skylight is at row 0, column 1. The layout 1, 3, 0, 2 needs a sensor exactly there, so it is gone. The mirror layout 2, 0, 3, 1 does not touch the skylight, so 1 layout is left.

Example 3
Input
ceiling = ["#"]
Output
0
Why

A 1 × 1 ceiling needs one sensor, and its only panel is glass. No layout.

Constraints

  • 1 ≤ n ≤ 10
  • Every row of ceiling has length n.
  • Each character is '.' or '#'.
Start with brute force

Choose any n of the n² panels and check whether the sensors clash. On a 10 × 10 ceiling that is about 17 trillion ways to choose 10 panels out of 100, far too many.

Even the smarter brute force, one sensor per row and per column (every ordering of the columns), is 10! = 3,628,800 full layouts, each checked at the end. Most of them clash in the first two or three rows, so building the rest of the layout is wasted work.

Hints

0 of 4 shown

Walkthrough and solution

Unlocks when you pass every test. Stuck for a while? Looking is fine too, as long as you then close it and write the code yourself.

Ctrl+Enter runs

Run your code to see results here. Run checks the examples. Submit checks every test, including hidden edge cases.

Write code