From 7d513dccf622193aaa0cfc291b7d2a42b602c45c Mon Sep 17 00:00:00 2001 From: Oliver Payne Date: Thu, 11 Nov 2021 22:29:11 +0000 Subject: [PATCH] Completed up to 2.42 --- 2_40.sch | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/2_40.sch b/2_40.sch index 22f8951..1898026 100644 --- a/2_40.sch +++ b/2_40.sch @@ -87,3 +87,68 @@ (define (triple-leq-n-sum-s n s) (filter (lambda (x) (= (sum x) s)) (ordered-triples n))) + +;; 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)))))) + +; Neater solution using map / accumulate with checks? +;(define (safe? k positions) +; (accumulate and #t (map