6
$\begingroup$

The board

Place three Knights, three Bishops and three Rooks on this board snippet.

The only rule: each piece has to be attacked exactly once.

Notes:

Ignore color, so every piece attacks every other piece whose square it can move to.

I don't know how many solutions there are, but there is at least one (and its symmetric twins).

$\endgroup$
7
$\begingroup$

This seems to work:

The knight on "c5" could also be moved to d2, and b4 could be on d5. Combined with symmetry (across both diagonals), that gives a total of 16 variations of this solution.

$\endgroup$
  • $\begingroup$ Good job! This was my solution: i.imgur.com/NJfg9Aw.png I cant move any piece and still solve the puzzle, so your solution is even better than mine :) Now I wonder how many solutions there are... $\endgroup$ – Tweakimp Dec 23 '17 at 6:52
6
$\begingroup$

Here’s a solution using only the top three rows of the board

enter image description here

$\endgroup$
  • $\begingroup$ It's interesting to see that we all use two rooks two attack each other. Do you think it can be done without a rook hitting another rook? Or even more insane: without a piece hitting another piece of the same kind? :O $\endgroup$ – Tweakimp Dec 23 '17 at 8:36
  • $\begingroup$ No idea. The board is definitely small enough to brute force, though. But as you can probably guess, my suggestion for improving this puzzle is just scrapping the unnecessary rows. $\endgroup$ – Bass Dec 23 '17 at 8:46
  • $\begingroup$ Thanks, but I needed them to create the puzzle, you just beat it too well :) $\endgroup$ – Tweakimp Dec 23 '17 at 8:53
2
$\begingroup$

This is similar to the question Two Knights, two Bishops, two Rooks and two Kings on a 4x4 chessboard and I could heavily reuse the code I wrote for that one to answer the question how many solutions there are.

There are

1344 solutions, including reflections and rotations. There is one diagonal reflection and one diagonal rotation, so unless a unique solution exhibits some kind of symmetry, it contributes to 4 solutions. It turns out there are no such symmetries, so there are 336 unique solutions.

I considered a 5x5 board with the squares named like this

 0  1  2  3  4
 5  6  7  8  9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24

and just excluded 0, 1, 5, 19, 23 and 24.

Each solution consists of 9 numbers, e.g., (2, 3, 4, 6, 18, 20, 14, 16, 17). The first three numbers correspond to the placement of the knights, the next three of the rooks and the last three of the bishops. There are too many unique solutions to provide a visual representation, so I'll just list the piece coordinates for each

(2, 3, 4, 6, 18, 20, 14, 16, 17)
(2, 3, 4, 8, 14, 22, 10, 17, 20)
(2, 3, 4, 8, 14, 22, 16, 20, 21)
(2, 3, 4, 9, 16, 22, 15, 18, 20)
(2, 3, 4, 10, 18, 21, 8, 9, 22)
(2, 3, 4, 11, 18, 20, 8, 9, 22)
(2, 3, 4, 14, 20, 22, 6, 7, 17)
(2, 3, 4, 14, 20, 22, 6, 15, 17)
(2, 3, 7, 4, 15, 20, 6, 13, 22)
(2, 3, 7, 4, 20, 22, 6, 15, 17)
(2, 3, 7, 8, 15, 20, 4, 6, 17)
(2, 3, 7, 8, 15, 20, 4, 6, 22)
(2, 3, 7, 8, 20, 22, 4, 6, 17)
(2, 3, 7, 13, 15, 17, 4, 6, 22)
(2, 3, 7, 13, 15, 17, 6, 20, 22)
(2, 3, 7, 13, 17, 20, 4, 6, 21)
(2, 3, 8, 9, 16, 22, 15, 18, 20)
(2, 3, 8, 14, 15, 22, 6, 7, 16)
(2, 3, 8, 14, 17, 20, 6, 7, 16)
(2, 3, 8, 14, 20, 22, 4, 6, 7)
(2, 3, 8, 17, 20, 21, 7, 10, 14)
(2, 3, 10, 4, 7, 15, 18, 20, 21)
(2, 3, 10, 9, 15, 21, 7, 8, 18)
(2, 3, 10, 9, 15, 22, 4, 11, 18)
(2, 3, 10, 9, 17, 20, 15, 16, 18)
(2, 3, 15, 4, 10, 18, 8, 17, 22)
(2, 3, 15, 4, 17, 20, 13, 16, 18)
(2, 3, 15, 8, 14, 16, 4, 10, 17)
(2, 3, 15, 9, 13, 20, 4, 10, 18)
(2, 3, 16, 14, 20, 22, 10, 15, 17)
(2, 3, 18, 4, 6, 20, 8, 13, 22)
(2, 3, 18, 4, 7, 10, 16, 17, 22)
(2, 3, 18, 4, 7, 10, 20, 21, 22)
(2, 3, 18, 6, 20, 22, 14, 15, 17)
(2, 3, 18, 8, 14, 16, 4, 10, 17)
(2, 3, 18, 8, 14, 22, 4, 10, 17)
(2, 3, 18, 8, 14, 22, 10, 17, 20)
(2, 3, 18, 10, 16, 20, 4, 7, 8)
(2, 3, 18, 14, 20, 22, 6, 7, 17)
(2, 3, 18, 14, 20, 22, 6, 15, 17)
(2, 3, 20, 7, 14, 18, 4, 15, 22)
(2, 3, 20, 8, 14, 21, 4, 10, 17)
(2, 3, 20, 9, 10, 17, 15, 16, 18)
(2, 3, 20, 9, 16, 22, 4, 15, 18)
(2, 3, 20, 9, 16, 22, 7, 8, 18)
(2, 3, 21, 9, 10, 22, 7, 8, 18)
(2, 3, 21, 9, 17, 20, 4, 11, 22)
(2, 3, 21, 10, 17, 22, 4, 7, 8)
(2, 3, 21, 14, 15, 22, 6, 7, 16)
(2, 3, 21, 14, 17, 22, 4, 6, 7)
(2, 3, 22, 9, 17, 20, 7, 8, 21)
(2, 3, 22, 10, 16, 20, 4, 8, 9)
(2, 3, 22, 14, 15, 18, 6, 16, 17)
(2, 3, 22, 14, 18, 20, 4, 6, 17)
(2, 3, 22, 14, 18, 20, 6, 16, 21)
(2, 4, 6, 10, 18, 21, 8, 9, 22)
(2, 4, 6, 11, 18, 20, 8, 9, 22)
(2, 4, 8, 3, 10, 21, 7, 17, 22)
(2, 4, 8, 6, 12, 14, 3, 10, 15)
(2, 4, 8, 9, 10, 16, 6, 7, 20)
(2, 4, 8, 9, 16, 22, 15, 18, 20)
(2, 4, 8, 9, 20, 21, 6, 7, 22)
(2, 4, 8, 14, 15, 22, 18, 20, 21)
(2, 4, 8, 14, 17, 20, 15, 16, 18)
(2, 4, 8, 14, 17, 21, 15, 18, 20)
(2, 4, 10, 8, 14, 22, 3, 18, 20)
(2, 4, 10, 14, 16, 22, 15, 18, 20)
(2, 4, 12, 3, 6, 15, 10, 17, 18)
(2, 4, 12, 3, 6, 15, 10, 17, 20)
(2, 4, 15, 6, 10, 18, 14, 16, 17)
(2, 4, 15, 10, 18, 21, 14, 16, 17)
(2, 4, 16, 3, 8, 15, 17, 18, 21)
(2, 4, 16, 3, 8, 22, 17, 18, 20)
(2, 4, 21, 8, 14, 20, 6, 16, 22)
(2, 4, 22, 3, 10, 20, 7, 18, 21)
(2, 4, 22, 6, 12, 14, 10, 15, 17)
(2, 6, 7, 3, 14, 20, 11, 12, 21)
(2, 6, 7, 4, 8, 21, 17, 20, 22)
(2, 6, 8, 4, 14, 22, 7, 10, 20)
(2, 6, 8, 10, 12, 16, 3, 14, 20)
(2, 6, 8, 10, 12, 16, 9, 14, 20)
(2, 6, 8, 10, 12, 16, 14, 20, 21)
(2, 6, 10, 4, 18, 21, 7, 20, 22)
(2, 6, 12, 4, 14, 18, 10, 11, 22)
(2, 6, 12, 4, 14, 18, 10, 21, 22)
(2, 6, 16, 3, 10, 20, 4, 17, 18)
(2, 6, 16, 3, 10, 20, 4, 18, 21)
(2, 6, 16, 4, 10, 20, 7, 12, 17)
(2, 6, 16, 4, 10, 20, 7, 12, 21)
(2, 6, 18, 4, 8, 14, 15, 16, 20)
(2, 6, 18, 4, 8, 14, 16, 17, 20)
(2, 6, 18, 4, 8, 14, 16, 20, 21)
(2, 6, 18, 10, 16, 20, 3, 4, 8)
(2, 6, 18, 10, 16, 20, 4, 7, 8)
(2, 6, 20, 10, 12, 16, 3, 21, 22)
(2, 6, 20, 12, 16, 21, 4, 7, 8)
(2, 6, 21, 4, 8, 14, 15, 16, 20)
(2, 6, 21, 4, 8, 14, 16, 17, 20)
(2, 6, 21, 4, 10, 22, 7, 18, 20)
(2, 6, 21, 7, 14, 20, 3, 4, 22)
(2, 6, 21, 9, 10, 22, 7, 8, 18)
(2, 6, 22, 4, 8, 14, 16, 17, 20)
(2, 6, 22, 10, 12, 16, 3, 20, 21)
(2, 6, 22, 10, 16, 20, 3, 4, 8)
(2, 6, 22, 10, 16, 20, 4, 8, 9)
(2, 6, 22, 12, 16, 18, 7, 8, 9)
(2, 6, 22, 12, 16, 18, 7, 8, 21)
(2, 7, 8, 4, 6, 10, 17, 18, 20)
(2, 7, 8, 4, 6, 10, 18, 20, 21)
(2, 7, 8, 4, 10, 21, 15, 18, 20)
(2, 7, 8, 4, 10, 22, 18, 20, 21)
(2, 7, 8, 16, 20, 22, 4, 6, 9)
(2, 7, 12, 3, 6, 22, 10, 17, 20)
(2, 7, 12, 4, 6, 22, 10, 17, 20)
(2, 7, 12, 8, 15, 21, 4, 6, 22)
(2, 7, 15, 4, 20, 21, 3, 10, 18)
(2, 7, 21, 11, 15, 17, 4, 6, 22)
(2, 7, 21, 11, 15, 17, 6, 20, 22)
(2, 7, 22, 4, 15, 21, 3, 6, 17)
(2, 7, 22, 8, 15, 21, 4, 6, 17)
(2, 8, 10, 6, 12, 16, 9, 15, 18)
(2, 8, 10, 14, 16, 22, 4, 18, 20)
(2, 8, 14, 6, 15, 22, 3, 13, 18)
(2, 8, 15, 3, 6, 14, 7, 17, 22)
(2, 8, 15, 4, 6, 14, 7, 16, 17)
(2, 8, 16, 3, 10, 14, 7, 17, 20)
(2, 8, 16, 3, 10, 20, 7, 17, 22)
(2, 8, 16, 9, 10, 21, 6, 15, 18)
(2, 8, 16, 9, 20, 21, 6, 7, 18)
(2, 8, 16, 12, 14, 21, 3, 4, 15)
(2, 8, 16, 14, 15, 20, 4, 6, 18)
(2, 8, 16, 14, 20, 21, 4, 6, 18)
(2, 8, 18, 4, 14, 20, 3, 10, 12)
(2, 8, 18, 4, 14, 20, 7, 12, 17)
(2, 8, 18, 4, 14, 20, 12, 15, 17)
(2, 8, 18, 4, 14, 21, 3, 6, 20)
(2, 8, 18, 4, 14, 21, 7, 20, 22)
(2, 8, 20, 3, 6, 10, 7, 18, 22)
(2, 8, 20, 3, 14, 21, 7, 15, 22)
(2, 8, 20, 4, 6, 14, 7, 12, 21)
(2, 8, 20, 12, 14, 21, 3, 4, 15)
(2, 8, 20, 12, 16, 21, 6, 7, 14)
(2, 8, 20, 14, 15, 22, 4, 18, 21)
(2, 8, 21, 4, 14, 22, 3, 16, 20)
(2, 8, 21, 4, 14, 22, 7, 16, 20)
(2, 8, 22, 4, 6, 14, 10, 15, 17)
(2, 8, 22, 12, 14, 16, 4, 7, 10)
(2, 8, 22, 12, 16, 18, 6, 7, 9)
(2, 8, 22, 12, 16, 18, 6, 7, 21)
(2, 8, 22, 18, 20, 21, 3, 6, 7)
(2, 10, 14, 6, 15, 22, 3, 13, 18)
(2, 10, 14, 12, 16, 22, 9, 15, 20)
(2, 12, 18, 3, 6, 15, 4, 10, 17)
(2, 12, 18, 3, 6, 15, 10, 17, 20)
(2, 12, 18, 4, 6, 14, 10, 15, 22)
(2, 12, 18, 16, 20, 22, 3, 10, 13)
(2, 14, 20, 6, 8, 12, 15, 16, 21)
(2, 15, 16, 3, 8, 14, 17, 21, 22)
(2, 15, 16, 4, 14, 18, 7, 17, 22)
(2, 15, 16, 4, 14, 22, 3, 10, 17)
(2, 15, 16, 4, 14, 22, 7, 17, 20)
(2, 15, 16, 8, 12, 21, 3, 14, 17)
(2, 15, 18, 4, 8, 14, 16, 20, 21)
(2, 15, 18, 4, 14, 22, 3, 6, 17)
(2, 15, 20, 4, 14, 21, 3, 10, 17)
(2, 15, 21, 4, 6, 18, 7, 16, 17)
(2, 15, 21, 7, 11, 18, 3, 4, 20)
(2, 15, 21, 7, 13, 20, 3, 4, 16)
(2, 16, 17, 3, 10, 22, 4, 7, 18)
(2, 16, 17, 3, 10, 22, 4, 15, 18)
(2, 16, 17, 3, 14, 20, 7, 12, 21)
(2, 16, 17, 9, 12, 20, 4, 15, 22)
(2, 16, 17, 14, 18, 20, 3, 4, 6)
(2, 16, 17, 14, 18, 20, 4, 6, 7)
(2, 16, 17, 14, 18, 20, 4, 6, 15)
(2, 16, 18, 3, 20, 22, 4, 15, 17)
(2, 16, 20, 3, 14, 15, 7, 17, 18)
(2, 16, 20, 3, 14, 21, 7, 17, 18)
(2, 16, 20, 8, 10, 21, 6, 14, 15)
(2, 16, 21, 4, 10, 18, 3, 8, 17)
(2, 16, 21, 8, 10, 22, 3, 14, 20)
(2, 16, 21, 8, 12, 15, 3, 14, 17)
(2, 17, 18, 4, 15, 21, 3, 8, 22)
(2, 17, 18, 4, 15, 22, 3, 6, 16)
(2, 17, 18, 14, 15, 22, 6, 7, 16)
(2, 17, 21, 4, 7, 11, 3, 18, 20)
(2, 17, 21, 4, 15, 22, 3, 6, 16)
(2, 17, 21, 9, 15, 22, 6, 7, 16)
(2, 17, 21, 13, 15, 22, 3, 6, 16)
(2, 18, 20, 6, 8, 12, 3, 16, 21)
(2, 20, 21, 9, 13, 17, 4, 15, 22)
(3, 4, 8, 9, 10, 21, 7, 17, 22)
(3, 4, 8, 9, 15, 22, 10, 11, 13)
(3, 4, 8, 9, 15, 22, 11, 13, 18)
(3, 4, 8, 9, 20, 22, 6, 11, 13)
(3, 4, 8, 9, 20, 22, 6, 13, 15)
(3, 4, 8, 14, 17, 20, 6, 15, 16)
(3, 4, 8, 14, 17, 21, 10, 15, 20)
(3, 4, 9, 2, 10, 11, 18, 20, 21)
(3, 4, 9, 2, 10, 21, 16, 17, 18)
(3, 4, 9, 2, 11, 20, 16, 17, 18)
(3, 4, 9, 6, 17, 20, 11, 14, 16)
(3, 4, 11, 2, 9, 20, 13, 15, 18)
(3, 4, 11, 2, 10, 21, 13, 16, 18)
(3, 4, 11, 7, 10, 21, 9, 14, 16)
(3, 4, 11, 7, 10, 21, 9, 16, 18)
(3, 4, 15, 7, 10, 21, 2, 9, 20)
(3, 4, 16, 14, 20, 22, 10, 15, 17)
(3, 4, 18, 2, 6, 20, 8, 17, 22)
(3, 4, 18, 2, 6, 20, 13, 14, 16)
(3, 4, 18, 2, 6, 20, 14, 16, 17)
(3, 4, 18, 8, 14, 22, 10, 17, 20)
(3, 4, 18, 14, 20, 22, 6, 15, 17)
(3, 4, 20, 2, 11, 18, 8, 21, 22)
(3, 4, 21, 6, 15, 22, 11, 14, 20)
(3, 4, 21, 6, 17, 20, 8, 11, 22)
(3, 4, 21, 6, 17, 20, 11, 14, 16)
(3, 4, 21, 13, 17, 20, 6, 8, 11)
(3, 4, 21, 13, 17, 20, 8, 11, 22)
(3, 4, 21, 14, 17, 20, 6, 9, 16)
(3, 7, 8, 2, 9, 21, 10, 17, 18)
(3, 7, 8, 2, 15, 20, 4, 6, 22)
(3, 7, 8, 4, 10, 21, 15, 18, 20)
(3, 7, 8, 4, 10, 22, 18, 20, 21)
(3, 7, 8, 4, 18, 21, 10, 13, 20)
(3, 7, 9, 4, 20, 21, 2, 11, 22)
(3, 7, 9, 4, 20, 21, 6, 11, 22)
(3, 7, 9, 8, 15, 20, 4, 6, 22)
(3, 7, 11, 13, 15, 22, 2, 4, 21)
(3, 7, 11, 13, 15, 22, 4, 6, 21)
(3, 7, 17, 4, 11, 20, 13, 15, 18)
(3, 7, 17, 4, 11, 20, 13, 15, 22)
(3, 7, 20, 2, 9, 11, 8, 18, 21)
(3, 8, 9, 2, 10, 21, 13, 16, 18)
(3, 8, 9, 2, 11, 15, 20, 21, 22)
(3, 8, 9, 2, 11, 20, 13, 16, 18)
(3, 8, 9, 2, 11, 20, 16, 18, 21)
(3, 8, 13, 17, 20, 21, 2, 7, 18)
(3, 8, 13, 17, 20, 21, 4, 7, 10)
(3, 8, 13, 17, 20, 21, 4, 7, 18)
(3, 8, 13, 17, 20, 21, 7, 10, 14)
(3, 8, 15, 2, 14, 20, 10, 13, 16)
(3, 8, 15, 14, 16, 22, 2, 9, 20)
(3, 8, 16, 2, 15, 20, 6, 13, 14)
(3, 8, 16, 9, 10, 20, 7, 17, 22)
(3, 8, 16, 9, 10, 21, 6, 7, 17)
(3, 8, 16, 9, 20, 22, 10, 11, 13)
(3, 8, 16, 14, 20, 21, 4, 6, 7)
(3, 8, 16, 14, 20, 22, 4, 10, 15)
(3, 8, 18, 2, 14, 15, 6, 16, 21)
(3, 8, 18, 14, 20, 22, 4, 6, 15)
(3, 8, 20, 2, 9, 15, 6, 13, 21)
(3, 8, 20, 2, 9, 15, 10, 13, 21)
(3, 8, 20, 7, 15, 16, 9, 13, 18)
(3, 8, 21, 14, 15, 22, 6, 7, 16)
(3, 8, 21, 14, 17, 20, 6, 7, 16)
(3, 9, 15, 2, 10, 11, 4, 13, 20)
(3, 9, 15, 2, 10, 21, 13, 16, 18)
(3, 9, 15, 2, 10, 21, 16, 17, 18)
(3, 9, 15, 2, 11, 20, 16, 17, 18)
(3, 9, 15, 4, 10, 11, 8, 18, 20)
(3, 9, 15, 10, 18, 21, 2, 17, 20)
(3, 9, 15, 11, 18, 20, 2, 16, 17)
(3, 9, 16, 6, 20, 22, 8, 11, 13)
(3, 9, 20, 4, 7, 10, 8, 15, 22)
(3, 11, 16, 2, 9, 20, 4, 13, 15)
(3, 11, 16, 2, 9, 20, 4, 17, 18)
(3, 11, 16, 4, 10, 22, 6, 8, 13)
(3, 11, 16, 4, 10, 22, 6, 8, 21)
(3, 11, 16, 9, 18, 20, 2, 4, 17)
(3, 11, 21, 4, 7, 17, 10, 15, 20)
(3, 13, 18, 9, 15, 21, 7, 8, 10)
(3, 13, 18, 15, 17, 21, 4, 9, 10)
(3, 15, 18, 2, 11, 20, 13, 14, 16)
(3, 15, 18, 4, 11, 17, 8, 13, 20)
(3, 15, 18, 8, 14, 16, 4, 10, 17)
(3, 16, 17, 4, 9, 20, 18, 21, 22)
(3, 16, 18, 6, 20, 22, 13, 14, 15)
(3, 16, 18, 6, 20, 22, 14, 15, 17)
(3, 16, 18, 9, 20, 22, 6, 8, 11)
(3, 16, 18, 9, 20, 22, 6, 8, 15)
(3, 16, 18, 14, 20, 22, 4, 6, 15)
(3, 16, 20, 8, 15, 22, 2, 18, 21)
(3, 17, 18, 9, 12, 20, 2, 15, 22)
(3, 18, 20, 4, 10, 16, 2, 8, 13)
(4, 6, 12, 9, 10, 18, 11, 14, 16)
(4, 6, 12, 9, 10, 21, 11, 14, 16)
(4, 6, 12, 9, 16, 22, 11, 14, 20)
(4, 6, 12, 9, 18, 21, 11, 14, 20)
(4, 6, 12, 9, 18, 21, 11, 20, 22)
(4, 6, 16, 2, 10, 11, 9, 14, 21)
(4, 6, 16, 3, 10, 20, 2, 17, 22)
(4, 8, 16, 2, 9, 15, 3, 6, 18)
(4, 8, 16, 2, 12, 15, 9, 14, 21)
(4, 8, 16, 3, 10, 12, 9, 20, 21)
(4, 8, 16, 3, 10, 12, 9, 21, 22)
(4, 8, 16, 3, 10, 21, 6, 15, 18)
(4, 8, 16, 3, 15, 22, 6, 11, 18)
(4, 8, 16, 3, 20, 21, 6, 11, 18)
(4, 8, 16, 3, 20, 22, 6, 10, 15)
(4, 8, 20, 2, 9, 10, 3, 6, 18)
(4, 8, 20, 2, 9, 15, 3, 10, 18)
(4, 8, 20, 2, 10, 21, 6, 14, 15)
(4, 8, 20, 2, 12, 15, 9, 14, 21)
(4, 8, 20, 3, 10, 22, 6, 15, 18)
(4, 8, 20, 3, 12, 15, 9, 18, 21)
(4, 11, 16, 8, 14, 20, 6, 21, 22)
(4, 11, 16, 9, 12, 20, 10, 18, 21)
(4, 12, 16, 3, 6, 22, 2, 17, 18)
(4, 12, 16, 3, 15, 22, 2, 17, 18)
(6, 7, 8, 4, 10, 22, 18, 20, 21)
(6, 7, 8, 4, 12, 15, 2, 9, 20)
(6, 7, 8, 4, 12, 15, 2, 20, 22)
(6, 7, 8, 4, 12, 20, 2, 9, 16)
(6, 7, 8, 4, 12, 20, 2, 16, 21)
(6, 7, 12, 4, 8, 20, 2, 16, 17)
(6, 7, 12, 4, 10, 18, 2, 11, 20)
(6, 7, 12, 4, 13, 21, 2, 11, 22)
(6, 7, 12, 4, 18, 21, 2, 11, 20)
(6, 7, 12, 4, 18, 21, 10, 11, 20)
(6, 8, 12, 2, 4, 18, 10, 11, 22)
(6, 8, 12, 2, 4, 18, 10, 21, 22)
(6, 8, 12, 2, 4, 21, 7, 14, 20)
(6, 8, 12, 4, 14, 18, 10, 11, 22)
(6, 8, 12, 4, 14, 18, 10, 21, 22)
(6, 8, 16, 2, 4, 15, 9, 14, 18)
(6, 8, 16, 2, 4, 21, 9, 14, 18)
(6, 8, 18, 2, 4, 15, 10, 13, 20)
(6, 8, 18, 2, 16, 22, 4, 9, 20)
(6, 8, 18, 2, 16, 22, 4, 13, 20)
(7, 8, 13, 2, 11, 15, 12, 21, 22)
(7, 11, 12, 3, 6, 17, 10, 14, 21)
(7, 11, 12, 3, 17, 21, 10, 13, 14)
(7, 12, 13, 3, 6, 15, 8, 17, 22)
(7, 12, 13, 3, 17, 21, 10, 11, 14)
(7, 12, 13, 3, 18, 21, 8, 10, 11)

I used various shortcuts to cut down the time, but it's a big board, with quite a few pieces and not that restricting conditions, so the code still takes 5 minutes to run.

from collections import defaultdict
import itertools as it

SIZE = 5
SQUARES = [s for s in range(SIZE**2) if s not in (0, 1, 5, 19, 23, 24)]

def flatten(rank, file):
    return rank * SIZE + file

def is_in_bounds(square):
    return 0 <= square < SIZE

def square_exists(rank, file):
    return (is_in_bounds(rank) and
            is_in_bounds(file) and
            flatten(rank, file) in SQUARES)

def rook_moves(rank, file):
    moves = [[flatten(r, file) for r in range(rank-1, -1, -1) if square_exists(r, file)]]
    moves += [[flatten(r, file) for r in range(rank+1, SIZE) if square_exists(r, file)]]
    moves += [[flatten(rank, f) for f in range(file-1, -1, -1) if square_exists(rank, f)]]
    moves += [[flatten(rank, f) for f in range(file+1, SIZE) if square_exists(rank, f)]]
    return moves

def bishop_moves(rank, file):
    down = range(-1, -rank-1, -1)
    up = range(1, SIZE-rank)
    moves = [[flatten(rank+i, file-i) for i in down if square_exists(rank+i, file-i)]]
    moves += [[flatten(rank+i, file+i) for i in down if square_exists(rank+i, file+i)]]
    moves += [[flatten(rank+i, file-i) for i in up if square_exists(rank+i, file-i)]]
    moves += [[flatten(rank+i, file+i) for i in up if square_exists(rank+i, file+i)]]
    return moves

def knight_moves(rank, file):
    offsets = ((-2, -1), (-2, 1),
               (-1, -2), (-1, 2),
               (1, -2), (1, 2),
               (2, -1), (2, 1))
    moves = [flatten(rank+x, file+y) for x, y in offsets
             if square_exists(rank+x, file+y)]
    return moves

def filter_ray_moves(moves, occupied):
    filtered_moves = []
    for direction in moves:
        for square in direction:
            if square not in occupied:
                filtered_moves.append(square)
            else:
                filtered_moves.append(square)
                break
    return filtered_moves

def solve(piece_moves_from, rook_adjacent_to):
    solutions = []
    attack_rule = [1] * 9
    for n1, n2, n3 in it.combinations(SQUARES, 3):
        knight_attacks = (piece_moves_from['N'][n1] +
                          piece_moves_from['N'][n2] +
                          piece_moves_from['N'][n3])
        # if two knights gang up on the other, skip
        if any(knight_attacks.count(knight) for knight in (n1, n2, n3)):
            continue
        attack_counter = defaultdict(int)
        for coord in (n1, n2, n3):
            for square in piece_moves_from['N'][coord]:
                attack_counter[square] += 1
        rook_allowed = [s for s in SQUARES
                   if s not in (n1, n2, n3) and knight_attacks.count(s) < 2]
        for r1, r2, r3 in it.combinations(rook_allowed, 3):
            # We can't know all the squares a rook can attack until all
            # pieces are on the board. However, the four adjacent squares
            # are guaranteed to be attacked, so we can use those find
            # pieces under double attack and other double attacked squares
            # we can exclude when placing the bishops.
            rook_attacks = (rook_adjacent_to[r1] +
                            rook_adjacent_to[r2] +
                            rook_adjacent_to[r3])
            for piece in (n1, n2, n3, r1, r2, r3):
                if attack_counter[piece] + rook_attacks.count(piece) > 1:
                    continue
            forbidden = [s for s in rook_allowed
                         if attack_counter[s] + rook_attacks.count(s) > 1]
            forbidden += [r1, r2, r3]
            bishop_allowed = [s for s in rook_allowed if s not in forbidden]
            for b1, b2, b3 in it.combinations(bishop_allowed, 3):
                piece_coords = (n1, n2, n3, r1, r2, r3, b1, b2, b3)
                counter = attack_counter.copy()
                for coord in (r1, r2, r3):
                    for square in filter_ray_moves(
                        piece_moves_from['R'][coord], piece_coords):
                        counter[square] += 1
                for coord in (b1, b2, b3):
                    for square in filter_ray_moves(
                        piece_moves_from['B'][coord], piece_coords):
                        counter[square] += 1
                attacks = [counter[piece] for piece in piece_coords]
                if attacks == attack_rule:
                    solutions.append(piece_coords)
    return solutions

piece_moves = {'N': knight_moves,
               'R': rook_moves,
               'B': bishop_moves,
               }

piece_moves_from = {}
for piece, moves in piece_moves.items():
    piece_moves_from[piece] = {}
    for rank in range(SIZE):
        for file in range(SIZE):
            square = flatten(rank, file)
            if square in SQUARES:
                piece_moves_from[piece][square] = moves(rank, file)

rook_adjacent_to = {}
for square in SQUARES:
    rank = square // SIZE
    file = square % SIZE
    adjacent = []
    for f in (file-1, file+1):
        if square_exists(rank, f):
            adjacent.append(flatten(rank, f))
    for r in (rank-1, rank+1):
        if square_exists(r, file):
            adjacent.append(flatten(r, file))
    rook_adjacent_to[square] = adjacent

solutions = solve(piece_moves_from, rook_adjacent_to)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.