Permalink
Browse files

*real* initial commit.

  • Loading branch information...
uberj
uberj committed Nov 13, 2011
1 parent b1ba277 commit 4ecf82815143b64e84594f52e517ad897e014fa1
Showing with 200 additions and 0 deletions.
  1. +14 −0 README
  2. +99 −0 nqueens.py
  3. +87 −0 test_nqueens.py
View
14 README
@@ -0,0 +1,14 @@
+N Queens
+========
+
+Right now it just prints the solutions out. Eventually it will save board states and account for rotations and reflections.
+
+usage:
+
+ python nqueens.py <number of queens>
+
+Example:
+
+ python nqueens.py 4
+
+_Note: I was completely sober (seriously, @mythmon can confirm) while writing this code._
View
@@ -0,0 +1,99 @@
+import sys
+import pdb
+import unittest
+
+"""
+Solve nqueens for a generic NxN board
+"""
+def solve_nqueens( n ):
+ board = [ [0]*n for i in range(n) ]
+ do_nqueens( 0, n, board )
+
+"""
+Helper function.
+"""
+def do_nqueens( row, n, board ):
+ if row >= n:
+ pb( board, n )
+ return
+ for col in range(n):
+ if valid_move( row, col, board, n ):
+ mark( row, col, board )
+ do_nqueens( row+1, n, board )
+ unmark( row, col, board )
+
+def mark( row, col, board ):
+ board[row][col] = 1
+
+def unmark( row, col, board ):
+ board[row][col] = 0
+
+"""
+Check a generic (row,col) coordinate to see if it is a
+valid move.
+"""
+def valid_move( row, col, board, n ):
+ col_val = check_col( row, col, board, n )
+ row_val = check_row( row, col, board, n )
+ diags_val = check_diags( row, col, board, n )
+ return not (col_val or row_val or diags_val)
+
+
+"""
+Generic test for board state. Control via xd and yd (x-direction and y-direction).
+"""
+def check_dir( row, col, xd, yd, board, n ):
+ if row < 0 or col < 0 or row >= n or col >= n:
+ return False
+ else:
+ if board[row][col]:
+ return True
+ else:
+ return check_dir( row + xd, col + yd, xd, yd, board, n )
+"""
+Check a row for move.
+True if there is a move.
+False if the colomn is free.
+"""
+def check_diags( row, col, board, n ):
+ up_left = check_dir( row, col, 1, 1, board, n )
+ up_right = check_dir( row, col, 1, -1, board, n )
+ down_left = check_dir( row, col, -1, 1, board, n )
+ down_right = check_dir( row, col, -1, -1, board, n )
+ return up_left or up_right or down_left or down_right
+
+"""
+Check a column for move.
+True if there is a move.
+False if the colomn is free.
+"""
+def check_col( row, col, board, n):
+ left = check_dir( row, col, 1, 0, board, n )
+ right = check_dir( row, col, -1, 0, board, n )
+ return left if left else right
+
+"""
+Check a row for move.
+True if there is a move.
+False if the colomn is free.
+"""
+def check_row( row, col, board, n ):
+ up = check_dir( row, col, 0, 1, board, n )
+ down = check_dir( row, col, 0, -1, board, n )
+ return up if up else down
+
+# Print board
+def pb( board, n ):
+ print "======================="
+ for i in range(n):
+ for j in range(n):
+ print board[i][j],
+ print
+
+
+
+if __name__ == "__main__":
+ solve_nqueens(int(sys.argv[1]))
+
+
+
View
@@ -0,0 +1,87 @@
+from nqueens import *
+
+class TestnQueens(unittest.TestCase):
+ def setUp(self):
+ self.n = 11
+
+ def test_check_row1( self ):
+ n = self.n
+ board = [ [0]*n for i in range(n) ]
+ board[0][0] = 1
+ for i in range(n):
+ self.assertTrue(check_row( 0, i, board, n ))
+
+ def test_check_row2( self ):
+ n = self.n
+ board = [ [0]*n for i in range(n) ]
+ board[6][5] = 1
+ for i in range(n):
+ self.assertTrue(check_row( 6, i, board, n ))
+
+ def test_check_col1( self ):
+ n = self.n
+ board = [ [0]*n for i in range(n) ]
+ board[0][0] = 1
+ for i in range(n):
+ self.assertTrue(check_col( i, 0, board, n ))
+
+ def test_check_col2( self ):
+ n = self.n
+ board = [ [0]*n for i in range(n) ]
+ board[0][n-1] = 1
+ for i in range(n):
+ self.assertTrue(check_col( i, n-1, board, n ), "0,n")
+
+ def test_check_col3( self ):
+ n = self.n
+ board = [ [0]*n for i in range(n) ]
+ board[7][2] = 1
+ for i in range(n):
+ self.assertTrue(check_col( i, 2, board, n ))
+
+ def test_mark( self ):
+ n = self.n
+ board = [ [0]*n for i in range(n) ]
+ mark( 5, 4, board )
+ self.assertTrue( board[5][4] == 1 , "(5,4)")
+ mark( 7, 4, board )
+ self.assertTrue( board[7][4] == 1 , "(7,4)")
+ mark( 5, 7, board )
+ self.assertTrue( board[5][7] == 1 , "(5,7)")
+ mark( 1, 2 , board )
+ self.assertTrue( board[1][2] == 1 , "(1,2)")
+
+ def test_unmark( self ):
+ n = self.n
+ board = [ [0]*n for i in range(n) ]
+ mark( 5, 4, board )
+ mark( 7, 4, board )
+ mark( 5, 7, board )
+ mark( 1, 2 , board )
+ unmark( 5, 4, board )
+ unmark( 7, 4, board )
+ unmark( 5, 7, board )
+ unmark( 1, 2 , board )
+ self.assertTrue( board[5][4] == 0 , "(5,4)")
+ self.assertTrue( board[7][4] == 0 , "(7,4)")
+ self.assertTrue( board[5][7] == 0 , "(5,7)")
+ self.assertTrue( board[1][2] == 0 , "(1,2)")
+
+ def test_diag( self ):
+ n = self.n
+ board = [ [0]*n for i in range(n) ]
+ board[0][0] = 1
+ self.assertTrue(check_diags( n-1, n-1, board, n))
+ board[0][0] = 0
+
+ board[0][n-1] = 1
+ self.assertTrue(check_diags( n-1, 0, board, n ))
+ board[0][n-1] = 0
+
+ board[1][2] = 1
+ self.assertTrue(check_diags( 0, 3, board, n ))
+ board[1][2] = 0
+
+if __name__ == "__main__":
+ unittest.main()
+

0 comments on commit 4ecf828

Please sign in to comment.