This is not the fastest implementation of the circuit, but it is pretty brief. I came up with this on my own, but I doubt it is unique. This is in the PLT Scheme, so some function names need to be changed to run it in R6RS. The list of solutions and each solution are built with minuses, so they are reversed. The turns and maps at the end reorder everything and add lines to the solutions for pretty output. Most languages ββhave a function like fold, see:
http://en.wikipedia.org/wiki/Fold_%28higher-order_function%29
#lang scheme/base (define (N-Queens N) (define (attacks? delta-row column solution) (and (not (null? solution)) (or (= delta-row (abs (- column (car solution)))) (attacks? (add1 delta-row) column (cdr solution))))) (define (next-queen safe-columns solution solutions) (if (null? safe-columns) (cons solution solutions) (let move-queen ((columns safe-columns) (new-solutions solutions)) (if (null? columns) new-solutions (move-queen (cdr columns) (if (attacks? 1 (car columns) solution) new-solutions (next-queen (remq (car columns) safe-columns) (cons (car columns) solution) new-solutions))))))) (unless (exact-positive-integer? N) (raise-type-error 'N-Queens "exact-positive-integer" N)) (let ((rows (build-list N (Ξ» (row) (add1 row))))) (reverse (map (Ξ» (columns) (map cons rows (reverse columns))) (next-queen (build-list N (Ξ» (i) (add1 i))) null null)))))
If you are thinking about a problem, the list is indeed the natural data structure for this problem. Since only one queen can be placed on each row, all you need to do is pass the list of inert or unused columns to the iterator for the next row. This is done by calling remq in the cond clause, which makes a callback to the next queen.
The foldl function can be rewritten as named let:
(define (next-queen safe-columns solution solutions) (if (null? safe-columns) (cons solution solutions) (let move-queen ((columns safe-columns) (new-solutions solutions)) (if (null? columns) new-solutions (move-queen
This is significantly faster since it avoids checking the add-in built into foldl. I came up with the idea of ββusing implicit strings when viewing the PLT Scheme N-Queens test. Starting with the delta line of one and increasing it as the solution is tested, it is pretty smooth. For some reason, abs is expensive in PLT Scheme, so is there a faster form for attacks?
In a PLT scheme, you need to use a mutable list type for the fastest implementation. A test that takes decisions into account without returning them can be written without creating any cons elements other than the original list of columns. This avoids garbage collection up to N = 17, when 618 milliseconds were spent in gc, while the program spent 1 hour, 51 minutes searching 95,815 104 solutions.
source share