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)