summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2022-04-03 17:09:09 +0200
committerThomas White <taw@physics.org>2022-04-03 17:09:09 +0200
commitd7f6da737335aaf87ac1d5c5ff283bb0d7a5507f (patch)
tree32c26fd8df10d923a30b3bcd8634693e16d44bf6
parent106e978231a2be2e160fc380ae2e75a4acd58b23 (diff)
Clean up (sort of)
-rw-r--r--sudoku.scm141
1 files changed, 95 insertions, 46 deletions
diff --git a/sudoku.scm b/sudoku.scm
index 965e8d2..5d9306b 100644
--- a/sudoku.scm
+++ b/sudoku.scm
@@ -1,19 +1,17 @@
(use-modules
(srfi srfi-1)
+ (srfi srfi-26)
+ (ice-9 match)
(sat solver)
(sat helpers))
-;; Board indices: column row value
-(define board-size 9)
-
-
(define (get-value board vals col row)
(1+
(find
(lambda (possible-value)
(array-ref vals
(array-ref board col row possible-value)))
- (iota board-size))))
+ (iota (biggest-value board)))))
(define (set-initial-value board col row val)
@@ -25,53 +23,106 @@
(1- val)))))
-(let ((board (make-array #f
- board-size
- board-size
- board-size)))
- (array-map! board make-sat-variable)
+(define (map-for-0-to n f)
+ (map f (iota n)))
- ;; No row contains duplicate values
- (do ((row 0 (1+ row))) ((= row board-size))
- (do ((value 0 (1+ value))) ((= value board-size))
- (exactly-one-true
- (map
- (lambda (col)
- (array-ref board col row value))
- (iota board-size)))))
- ;; No column contains duplicate values
- (do ((col 0 (1+ col))) ((= col board-size))
- (do ((value 0 (1+ value))) ((= value board-size))
+(define (make-row row board-size)
+ (map-for-0-to
+ board-size
+ (cut cons <> row)))
+
+
+(define (make-col col board-size)
+ (map-for-0-to
+ board-size
+ (cut cons col <>)))
+
+
+(define (rows board-size)
+ (map-for-0-to
+ board-size
+ (cut make-row <> board-size)))
+
+
+(define (cols board-size)
+ (map-for-0-to
+ board-size
+ (cut make-col <> board-size)))
+
+
+(define (make-box bcol brow box-size)
+ (let ((l '()))
+ (do ((icol 0 (1+ icol))) ((= icol box-size))
+ (do ((irow 0 (1+ irow))) ((= irow box-size))
+ (set! l (cons
+ (cons (+ (* box-size bcol) icol)
+ (+ (* box-size brow) irow))
+ l))))
+ l))
+
+
+(define (boxes board-size box-size)
+ (let ((l '()))
+ (do ((bcol 0 (1+ bcol))) ((= bcol 3))
+ (do ((brow 0 (1+ brow))) ((= brow 3))
+ (set! l (cons
+ (make-box bcol brow box-size)
+ l))
+ ))
+ l))
+
+
+(define (biggest-value board)
+ (1+ (match
+ (array-shape board)
+ (((_ _) (_ _) (_ max-value))
+ max-value))))
+
+
+(define (unique-values board coords-list)
+ (for-each
+ (lambda (n)
(exactly-one-true
(map
- (lambda (row)
- (array-ref board col row value))
- (iota board-size)))))
-
- ;; No 3x3 box contains duplicate values
- (do ((col 0 (+ 3 col))) ((= col board-size))
- (do ((row 0 (+ 3 row))) ((= row board-size))
- (do ((value 0 (1+ value))) ((= value board-size))
- (exactly-one-true
- (let ((l '()))
- (do ((col1 0 (1+ col1))) ((= col1 3))
- (do ((row1 0 (1+ row1))) ((= row1 3))
- (set! l (cons (array-ref board
- (+ col col1)
- (+ row row1)
- value)
- l))))
- l)))))
+ (lambda (coord)
+ (array-ref board (car coord) (cdr coord) n))
+ coords-list)))
+ (iota (biggest-value board))))
+
+
+(define (all-unique-values board coord-lists)
+ (for-each
+ (cut unique-values board <>)
+ coord-lists))
+
+
+(define (make-board size)
+ (let ((board (make-array #f size size size)))
+ (array-map! board make-sat-variable)
+ board))
+
+
+(define (all-one-number board col row)
+ (exactly-one-true
+ (map
+ (lambda (value)
+ (array-ref board col row value))
+ (iota (biggest-value board)))))
+
+
+(let* ((board-size 9)
+ (board (make-board board-size)))
+
+ ;; The standard Sudoku rules
+ (all-unique-values board (rows board-size))
+ (all-unique-values board (cols board-size))
+ (all-unique-values board (boxes board-size 3))
;; Each position contains exactly one number
(do ((col 0 (1+ col))) ((= col board-size))
(do ((row 0 (1+ row))) ((= row board-size))
- (exactly-one-true
- (map
- (lambda (value)
- (array-ref board col row value))
- (iota board-size)))))
+ (all-one-number board col row)))
;; Initially specified values
(set-initial-value board 0 0 4)
@@ -100,8 +151,6 @@
(set-initial-value board 8 0 5)
-
-
(let ((vals (solve-sat)))
(do ((row 0 (1+ row))) ((= row board-size))
(do ((col 0 (1+ col))) ((= col board-size))