WIP amb-8-queens

This commit is contained in:
Oliver Payne 2023-11-16 23:06:35 +00:00
parent 1c6d87d844
commit 30c84f7888
3 changed files with 101 additions and 1 deletions

92
mceval/amb-8-queens.rkt Normal file
View File

@ -0,0 +1,92 @@
;; EXERCISE 2.42
(define (queens board-size)
(define (queen-cols k)
(if (= k 0)
(list empty-board)
(filter
(lambda (positions) (safe? k positions))
(flatmap
(lambda (rest-of-queens)
(map (lambda (new-row)
(adjoin-position new-row k rest-of-queens))
(enumerate-interval 1 board-size)))
(queen-cols (- k 1))))))
(queen-cols board-size))
(define empty-board '())
(define (position row col) (cons row col))
(define (row position) (car position))
(define (col position) (cdr position))
(define (intercepts horiz pos neg) (list horiz pos neg))
(define (horiz intercepts) (car intercepts))
(define (pos intercepts) (cadr intercepts))
(define (neg intercepts) (caddr intercepts))
(define (col-k-pos k positions)
(car (filter (lambda (x) (= (col x) k)) positions)))
; Compute the y-intercepts of the horizontal line the line
; of gradient +1 and the line of gradient -1 through the
; given position. Any two positions that share one of these
; intercepts put are not safe wrt each other.
(define (compute-intercepts position)
(intercepts (row position)
(- (row position) (col position))
(+ (row position) (col position))))
(define (checks pos1 pos2)
(if (= (col pos1) (col pos2))
#f
(let ((int1 (compute-intercepts pos1))
(int2 (compute-intercepts pos2)))
(or (= (horiz int1) (horiz int2))
(= (pos int1) (pos int2))
(= (neg int1) (neg int2))))))
(define (adjoin-position row col rest-of-queens)
(append rest-of-queens (list (position row col))))
; Calculuate the intercepts of each of the position. If any
; match, then the k-th position is not safe.
(define (safe? k positions)
(if (= (col (car positions)) k) #t ; Need to only check with first k-1
(let* ((k-pos (col-k-pos k positions))
(k-int (compute-intercepts k-pos))
(int (compute-intercepts (car positions))))
(and (not (= (horiz int) (horiz k-int)))
(not (= (pos int) (pos k-int)))
(not (= (neg int) (neg k-int)))
(safe? k (cdr positions))))))
(define (eight-queens)
(define (position row col) (cons row col))
(define (row position) (car position))
(define (col position) (cdr position))
(define (safe? k positions)
(let ((kth-position (list-ref positions (- k 1)))
(pre-kth-positions (cdr (reverse positions))))
;; If the row, positive or negative intercept of the k-th position
;; is equal to any of the first k-1 positions, then the k-th
;; position is not safe.
;; Better would be: look at columns up to k and check that row
;; and intercepts are distinct.
(if (memv (row kth-position) (map row pre-kth-positions))
false
(if (memv (positive-intercept kth-position)
(map positive-intercept pre-kth-positions))
false
(if (memv (negative-intercept kth-position)
(map negative-intercept pre-kth-positions))
false
true)))))
(let ((queens
(map (lambda (col) (position (amb 1 2 3 4 5 6 7 8) col))
'(1 2 3 4 5 6 7 8))))
(and-map (lambda (k) (safe? k queens))
'(1 2 3 4 5 6 7 8))
queens))

View File

@ -25,5 +25,11 @@
(define (map f l)
(if (null? l) '()
(cons (f (car l))
(map f (cdr l)))))))
(map f (cdr l)))))
(define (and-map f l)
(if (null? l) true
(if (f (car l))
true
false)))))

View File

@ -163,7 +163,9 @@
(list 'cons cons)
(list 'null? null?)
(list 'list list)
(list 'reverse reverse)
(list 'memq memq)
(list 'memv memv)
(list 'member member)
(list 'not not)
(list '= =)