;;;Programmed by Ron Danielson, 1/31/00 

;;;

;;;This set of functions finds one solution for the N queens problem.

;;;Rows are tested sequentially, with a recursive function to trial

;;;place a queen in various columns on that row.

 

(DEFINE (SAFE board row col)

  ;;There is no diagonal attack if none of the queens already on the board

  ;;are in the same column, or have a slope of 1 or -1 from the tested

  ;;position (checked by subtracting corresponding row and column

  ;;coordinates, comparing absolute values of result).

  (DO ((test board (CDR test))

       (result #t)

      )

      ((null? test) result)

      (COND  ((OR (EQUAL? (ABS (- row (CAAR test)))

                          (ABS (- col (CADAR test)))

                  )

                  (EQUAL? col (CADAR test))

              )

            (SET! result #f))

      )

  )

)

(DEFINE (PRINTSOLN board)

  ;;Recursively traverse board, printing out each queen as it's encountered.

  (COND ((NULL? board) #t)

         (ELSE (DISPLAY (CAAR board))

               (DISPLAY ", ")

               (DISPLAY (CADAR board))

               (DISPLAY "; ")

               (PRINTSOLN (CDR board))

         )

  )

)

(DEFINE (TRYROW currow n board)

  (DO ((col 1 (+ col 1))      ;for col := 1 to n

       (soln #f)              ;set T when solution found

      )

      ((OR (> col n) soln) soln)  ;stop loop if > n or solution found

      (COND ((safe board currow col)        ;check current position

               (SET! board (CONS (LIST currow col) board))  ;add if OK

               (COND  ((< currow n) (SET! soln (tryrow (+ currow 1) n board)))

                              ;;if row < n, try next row

                      (ELSE (SET! soln (printsoln board)))   ;solution found

               )

               (SET! board (CDR board))     ;backtrack - remove previous queen

            )

      )

  )

)

(DEFINE (QUEENS n)

  (tryrow 1 n ())

)