SICP問題2.42 Nクイーン問題

;; 2.42
(define (queens board-size)
  (letrec ((queen-cols
	    (lambda (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 (adjoin-position new-row k rest-of-queens)
  (cons (list new-row k) rest-of-queens))

(define empty-board '())

(define (safe? k positions)
  (letrec ((not-found-row (lambda (row positions)
			    (cond [(null? positions) #t]
				  [(= row (caar positions)) #f]
				  [else (not-found-row row (cdr positions))])))
	   (not-found-diag (lambda (row col positions)
			     (cond [(null? positions) #t]
				   [(or (= row (+ (caar positions)
						  (- col (cadar positions))))
					(= row (- (caar positions)
						  (- col (cadar positions)))))
				    #f]
				   [else (not-found-diag row col (cdr positions))]))))
	
    (if (= k 1)
          #t
          (let ((row (caar positions))
		(col k))
	    (and (not-found-row row (cdr positions))
                 (not-found-diag row col (cdr positions)))))))
  
(define (enumerate-interval i j)
  (letrec ((iter (lambda (x result)
		   (if (< x i)
		       result
		       (iter (- x 1) (cons x result))))))
    (iter j '())))

(define (flatmap proc seq)
  (fold-right append '() (map proc seq)))

(define (fold-right op initial sequence)
  (if (null? sequence)
      initial
      (op (car sequence) (fold-right op initial (cdr sequence)))))