Skip to content

Instantly share code, notes, and snippets.

@rosemichaele
Created September 6, 2017 14:19
Show Gist options
  • Save rosemichaele/98079356137be4cb78e831f6ccced5ba to your computer and use it in GitHub Desktop.
Save rosemichaele/98079356137be4cb78e831f6ccced5ba to your computer and use it in GitHub Desktop.
An adaptation of the eight queens puzzle for any positive integer n > 3.
from itertools import permutations, dropwhile
def n_queens(n: int) -> list:
"""An adaptation of the eight queens puzzle for any positive integer n > 3.
:param - n: a positive integer representing the number of rows, columns, and queens to solve for.
:return - queen_squares: a list of 2-tuples representing the (0-based) squares to place the queens on, such that no
queen is attacked / guarded by another."""
if n < 4:
return ["Do it yourself."]
squares = [(row, col) for row in range(n) for col in range(n)]
diagonals = {s: {ds for ds in squares if abs(ds[0] - s[0]) == abs(ds[1] - s[1]) and ds != s} for s in squares}
# Construct a generator for all possible queen placements such that there is only one queen in a given row
gen = permutations(squares, n)
no_shared_rows = filter(lambda t: len(set([x for x, _ in t])) == n, gen)
# Filter down to where there is only one queen per column as well
no_shared_rows_or_cols = filter(lambda t: len(set([y for _, y in t])) == n, no_shared_rows)
# Function to look for a placement where no queens share a diagonal
def shared_diagonals(t):
for square in t:
d = diagonals[square]
if d.intersection(set(t)) == set():
continue
else:
return True
return False
# Iterate until a placement is found where no queen shares a diagonal with another
sol = dropwhile(shared_diagonals, no_shared_rows_or_cols)
queen_squares = next(sol)
return queen_squares
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment