Created
September 6, 2017 14:19
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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