20-CS-4003-001 |
Organization of Programming Languages |
Fall 2017 |
---|---|---|

Search and Abstract Thinking |

**The N Queens Problem**

;; r - hypothesized row for queen in next ;; unassigned column ;; l - current queen assignments in leftmost ;; consecutive columns ;; returns #t iff a queen can be placed in ;; row r of the next unassigned column ;; without attacking any queen that was ;; assigned in l. Assumes there are no ;; two attacking queens in l. (define check? (lambda (r l) (if (null? l) #t (let ((qp (car l)) (d (length l))) (if (or (= r qp) ;; row (= (+ r d) qp) ;; diag↑ (= (- r d) qp)) ;; diag↓ #f (check? r (cdr l))))))) ;; extend queen assignment l by adding r in the ;; first unassigned column then return that list ;; if it is of size m or return all solutions ;; that can be made by extending that list (define extend (lambda (r l m) (let ((el (append l (list r)))) (if (= m (length el)) (list el) (queen 1 el m '()))))) ;; returns all assignments of queens to squares ;; such that no two queens are attacking that ;; include the assignments of list l and ;; assignments to rows r, r+1,... in the column ;; right after the last column of l. Param m ;; is the board size (m x m). (define queen (lambda (r l m acc) (if (> r m) acc (if (check? r l) (let ((s (append acc (extend r l m)))) (queen (+ r 1) l m s)) (queen (+ r 1) l m acc))))) (define nqueen (lambda (m) (queen 1 '() m '()))) | - |
The N-Queens problem:Given a N x N chessboard and N queens, place
the queens on the board so that no two are attacking. Two queens are
attacking if they are on the same diagonal, on the same row, or on the
same column. Examples:
+---+---+---+---+ +---+---+---+---+ | | . | Q | | | Q | * | Q | | |---+---+---+---+ +---+---+---+---+ | Q | | . | | | | * | | | |---+---+---+---+ +---+---+---+---+ |...|...|...| Q | | | Q | * | | |---+---+---+---+ +---+---+---+---+ | | Q | . | | | | | | Q | +---+---+---+---+ +---+---+---+---+ no attacking pair two attacking pairs Setup:representation:
add x=1 to list:() success! add x=1 to list:(1) fail :-( add x=2 to list:(1) fail :-( add x=3 to list:(1) success! add x=1 to list:(1 3) fail :-( add x=2 to list:(1 3) fail :-( add x=3 to list:(1 3) fail :-( add x=4 to list:(1 3) fail :-( tried all possibilities: backtrack add x=4 to list:(1) success! add x=1 to list:(1 4) fail :-( add x=2 to list:(1 4) success! add x=1 to list:(1 4 2) fail :-( add x=2 to list:(1 4 2) fail :-( add x=3 to list:(1 4 2) fail :-( add x=4 to list:(1 4 2) fail :-( tried all possibilities: backtrack ... add x=3 to list:(2 4 1) --> (2 4 1 3) ... add x=2 to list:(3 1 4) --> (3 1 4 2) ... ;Value 11: ((2 4 1 3) (3 1 4 2))
1 2 3 4 (2 4 1) <- cur-queen-assgn +---+---+---+---+ (3 2 1 0) <- dec-numbs 1 | | . | Q | | 3 <- next-col-queen-pos |---+---+---+---+ --------- 2 | Q | | . | | (or (= 3 2) (= 6 2) (= 0 2)) -> #f |---+---+---+---+ (or (= 3 4) (= 5 4) (= 1 4)) -> #f 3 |...|...|...| X | r=3 (or (= 3 1) (= 4 1) (= 2 1)) -> #f |---+---+---+---+ ===================== 4 | | Q | . | | (2 4 1) <- cur-queen-assgn +---+---+---+---+ (3 2 1 0) <- dec-numbs o col 4 1 <- next-col-queen-pos --------- \---------/ (or (= 1 2) (= 4 2) (= -2 2)) -> #f (2 4 1) <- assgn (or (= 1 4) (= 3 4) (= -1 4)) -> #f (or (= 1 1) (= 2 1) (= 0 1)) -> #t =====================The list of decreasing numbers can be obtained by invoking dec-seq.
The (check? 1 '(2 4 1)) -> #f (check? 2 '(2 4 1)) -> #f (check? 3 '(2 4 1)) -> #t (check? 4 '(2 4 1)) -> #fBack to the search for a solution. Function queen
takes as input number r - a queen placement in a row of the next
unassigned column, a list l - a current assignment of queens to
rows, a number m - the size of the board, and
acc - to accumulate a list of queen assignments that are
solutions. The action of queen is to append to the accumulator
list all extensions of l that are solutions. Examples:
(queen 1 '(2) 8 '()) ((2 4 6 8 3 1 7 5) (2 5 7 1 3 8 6 4) (2 5 7 4 1 8 6 3) (2 6 1 7 4 8 3 5) (2 6 8 3 1 4 7 5) (2 7 3 6 8 5 1 4) (2 7 5 8 1 4 6 3) (2 8 6 1 3 5 7 4)) (queen 1 '(2) 4 '()) ((2 4 1 3))If it is OK to add r to l (check? returns
#t) then use a call to queen with l appended
with the OK row position (nl below) for the next unassigned column.
But if the newly filled column completes an assignment for a solution,
then output that list (as (list nl)).
(let ((nl (append l (list x)))) (if (= m (length nl)) (list nl) (queen 1 nl m '())))))add all solutions that include current queen assignments with the new column assignment added
(define nqueens (lambda (n) (queen 1 '() m '()))) (nqueens 8) |