ActiveState Code

Recipe 576647: Eight queens. Six lines.


What six lines of Python can do

Python
1
2
3
4
5
6
7
8
from itertools import permutations

n = 8
cols = range(n)
for vec in permutations(cols):
    if (n == len(set(vec[i]+i for i in cols))
          == len(set(vec[i]-i for i in cols))):
        print vec

Discussion

Solver for the eight queens puzzle:
http://en.wikipedia.org/wiki/Eight_queens_puzzle

Computes all 92 solutions for eight queens. By setting n to different values, other sized puzzles can be solved.

The output is presented in vector form (each number represents the column position of a queen on consecutive rows). The vector can be pretty printed with this function:

def board(vec):
    '''Translate column positions to an equivalent chess board.

    >>> board([0, 4, 7, 5, 2, 6, 1, 3])
    Q-------
    ----Q---
    -------Q
    -----Q--
    --Q-----
    ------Q-
    -Q------
    ---Q----

    '''

    for col in vec:
        s = ['-'] * len(vec)
        s[col] = 'Q'
        print ''.join(s)
    print

With the solution represented as a vector with one queen in each row, we don't have to check to see if two queens are on the same row. By using a permutation generator, we know that no value in the vector is repeated, so we don't have to check to see if two queens are on the same column. Since rook moves don't need to be checked, we only need to check bishop moves.

The technique for checking the diagonals is to add or subtract the column number from each entry, so any two entries on the same diagonal will have the same value (in other words, the sum or difference is unique for each diagnonal). Now all we have to do is make sure that the diagonals for each of the eight queens are distinct. So, we put them in a set (which eliminates duplicates) and check that the set length is eight (no duplicates were removed).

Any permutation with non-overlapping diagonals is a solution. So, we print it and continue checking other permutations.

Comments

  1. 1. At 1:52 a.m. on 28 mar 2009, Gabriel Genellina said:

    awesome!

  2. 2. At 12:06 p.m. on 24 apr 2009, charles.merriam tollak said:

    Very nice!

    For those that like more concise output in python 3.0, I use:

    print ("\n".join('.' * i + 'Q' + '.' * (n-i-1) for i in vec), end = "\n===\n")
    
  3. 3. At 2:26 a.m. on 13 sep 2009, Paddy McCarthy said:

    I have submitted the above on Rosetta Code, on this page where it will be compared to solutions in other programming languages.

    • Paddy.

Sign in to comment