scheme解决八皇后问题

此前描述了一个枚举、过滤、重组的过程,通过这一过程也能解决嵌套循环的问题。
练习2.40 请定义过程unique-pairs,给它整数n,它能产生序对(i,j),其中1≤j≤i≤n

点击查看代码
(define nil '())
(define (enumerate-interval low high)
    (if (> low high)
        nil
        (cons low (enumerate-interval (+ low 1) high))))
(define (unique-pairs n)
    (map (lambda (i)
            (map (lambda (j) (list i j))
                    (enumerate-interval 1 (- i 1))))
                    (enumerate-interval 1 n)))
练习2.41 请写出一个过程,它能产生所有小于等于整数n的正的相异整数i,j和k的有序三元组,使得每个三元组的和为给定整数s
点击查看代码
(define (flatmap proc seqs)
    (accumulate append nil (map proc seqs)))
(define (accumulate op initial seq)
    (if (null? seq) 
        initial
        (op (car seq)
            (accumulate op initial (cdr seq)))))
(define (filter proc seqs)
    (cond ((null? seqs) nil)
          ((proc (car seqs)) (cons (car seqs) (filter proc (cdr seqs))))
          (else (filter proc (cdr seqs)))))
(define (third-pairs n)
    (flatmap
        (lambda (i)
            (flatmap
                (lambda (j)
                    (map (lambda (k) 
                            (list i j k))
                    (enumerate-interval 1 (- j 1))))
                (enumerate-interval 1 (- i 1))))
        (enumerate-interval 1 n)))
(define (ordered-triples-sum n s)
    (filter (lambda (x) (= (accumulate + 0 x) s))
        (third-pairs n)))

练习2.42 八皇后问题 将八个皇后摆在国际象棋棋盘上,使得任意一个皇后都不能攻击另一个皇后,有多少种方式? (将k个皇后摆在k行k列的棋盘上,使得任意一个皇后都不能攻击另一个皇后)
点击查看代码
;定义空棋盘
(define nil '())
(define empty-board nil)
;通过append进行累积
(define (flatmap proc seqs)
    (accumulate append nil (map proc seqs)))
(define (accumulate op initial seqs)
    (if (null? seqs)
        initial
        (op (car seqs)(accumulate op initial (cdr seqs)))))
;过滤
(define (filter predicate sequence)
      (cond ((null? sequence) nil)
            ((predicate (car sequence))
              (cons (car sequence)
                    (filter predicate (cdr sequence))))
            (else (filter predicate (cdr sequence)))))
;通过生成一个整数序列,由于每一列都需要填入一个棋子,在解答皇后问题时,可以只录入每列的位置。在序对中可以表示为,(position,1-k)
(define (enumerate-interval low high)
      (if ( > low high)
          nil
          (cons low (enumerate-interval (+ low 1) high))))
(define (queens board-size)
    (define (queens-cols k)
        (if (= k 0)
            (list empty-board)
            (filter
                (lambda (positions) (safe? k positions))
                (flatmap
                    (lambda (rest-of-queens)
                        (map
                            (lambda (new-row)
                                (adjoin-positions new-row k rest-of-queens))
                                (enumerate-interval 1 board-size)))
                (queens-cols (- k 1))))))
    (queens-cols board-size))
;录入新的棋子位置,录在前面比较容易提取
(define (adjoin-positions new-row k rest-of-queens)
    (cons new-row rest-of-queens))
;判断一个棋子是否安全:是否和其他棋子在同一行?是否和其他棋子在同一对角线?只需要判断最新的棋子位置,但也要遍历所有已确定的棋子
(define (safe? k positions)
    (define (same-row? v0 v1)
        (= (car v0)(car v1)))
    (define (same-diag? v0 v1)
        (= (abs (- (car v0) (car v1)))
           (abs (- (cdr v0) (cdr v1)))))
    (let ((pair-list (map cons positions (enumerate-interval 1 k))))
        (let ((val (car pair-list)))
            (= (length
                (filter
                    (lambda (x) (or (same-row? x val) (same-diag? x val)))
                    (cdr pair-list))) 0 ))))
posted @ 2025-12-25 10:44  檐上落白luckin  阅读(6)  评论(0)    收藏  举报