Repository navigation
Expand file tree
/
Copy pathnqueens.lisp
More file actions
115 lines (95 loc) · 2.69 KB
/
Copy pathnqueens.lisp
File metadata and controls
115 lines (95 loc) · 2.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
;; nqueens solver for arbitrary sized boards
;;
;; This solves the 8x8 board by default, but you
;; may specify a larger sized board via the CLI
;; arguments.
;;
;; In the past this would exhaust our heap memory
;; on sizes of >= 12, however now we've added an
;; explicit GC call after printing each solution and
;; so it can handle a lot larger sizes.
;;
;; That said I got bored waiting for the solutions
;; to be generated for 20x20 - it was enough to show
;; that it did find a bunch of valid solutions so
;; I terminated my search after printing out a few
;; hundred of them!
;;
;; And still generating solutions for 22x22 will exhaust
;; the heap before generating even the first solution.
;; 21 seems to be about the most I can manage at the moment
;; but that seems like a reasonable size.
;;
;; Usage
;;
;; ./nqueens [size]
;;
(defvar SIZE 8)
(defvar solution-count 0)
(defun safe-helper (placed col distance)
(if (nil? placed)
t
(if (or (= (car placed) col)
(= (abs (- (car placed) col)) distance))
nil
(safe-helper (cdr placed)
col
(+ distance 1)))))
(defun safe? (placed col)
(safe-helper placed col 1))
;; printing routines
(defun print-cell (queen-col col)
(if (= queen-col col)
(print "Q ")
(print ". ")))
(defun print-row-helper (queen-col col)
(if (<= col SIZE)
(do
(print-cell queen-col col)
(print-row-helper queen-col (+ col 1)))))
(defun print-row (queen-col)
(do
(print "\t")
(print-row-helper queen-col 1)
(newline)))
(defun print-board (board)
(if board
(do
(print-row (car board))
(print-board (cdr board)))))
(defun print-solution (board)
(set! solution-count (+ solution-count 1))
(println "Solution " solution-count " " board ":\n")
(print-board board)
(newline)
(newline))
;;
;; ------------------------------------------------------------
;; Solver
;;
(defun solve-row (row placed)
(if (> row SIZE)
;; complete solution
(print-solution (reverse placed))
;; otherwise try every column
(try-column row placed 1)))
(defun try-column (row placed col)
(if (<= col SIZE)
(do
(if (safe? placed col)
(solve-row (+ row 1)
(cons col placed)))
(try-column row
placed
(+ col 1)))))
;;
;; ------------------------------------------------------------
;;
(defun main (args)
(if (= (length args) 2)
(set! SIZE (atoi (car (cdr args)))))
(println "\n8 Queens Solver for board size " SIZE "x" SIZE "\n")
(set! solution-count 0)
(solve-row 1 nil)
(println "Found " solution-count " solutions.")
)