sicp 2.42

Exercise 2.42.  

 

Figure 2.8:  A solution to the eight-queens puzzle.
 

The ``eight-queens puzzle'' asks how to place eight queens on a chessboard so that no queen is in check from any other (i.e., no two queens are in the same row, column, or diagonal). One possible solution is shown in figure 2.8. One way to solve the puzzle is to work across the board, placing a queen in each column. Once we have placed k - 1 queens, we must place the kth queen in a position where it does not check any of the queens already on the board. We can formulate this approach recursively: Assume that we have already generated the sequence of all possible ways to place k - 1 queens in the first k - 1 columns of the board. For each of these ways, generate an extended set of positions by placing a queen in each row of the kth column. Now filter these, keeping only the positions for which the queen in the kth column is safe with respect to the other queens. This produces the sequence of all ways to place k queens in the first k columns. By continuing this process, we will produce not only one solution, but all solutions to the puzzle.

We implement this solution as a procedure queens, which returns a sequence of all solutions to the problem of placing n queens on ann× n chessboard. Queens has an internal procedure queen-cols that returns the sequence of all ways to place queens in the first kcolumns of the board.

 

(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))

 

In this procedure rest-of-queens is a way to place k - 1 queens in the first k - 1 columns, and new-row is a proposed row in which to place the queen for the kth column. Complete the program by implementing the representation for sets of board positions, including the procedure adjoin-position, which adjoins a new row-column position to a set of positions, and empty-board, which represents an empty set of positions. You must also write the procedure safe?, which determines for a set of positions, whether the queen in thekth column is safe with respect to the others. (Note that we need only check whether the new queen is safe -- the other queens are already guaranteed safe with respect to each other.)

 

 

八皇后问题,结果只保存了行,列即是list的下标

 

(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 (adjoin-position new-row k rest-of-queens)
  (append rest-of-queens (list new-row)))

(define (safe? k positions)
  (if (< (length positions) 2)
      #t
      (let ((new (list-ref positions (- k 1)))
            (first (car positions)))
        (cond ((= new first) #f)
              ((= new (+ first (- (length positions) 1))) #f)
              ((= new (- first (- (length positions) 1))) #f)
              (else (safe? (- k 1) (cdr positions)))))))

(define (filter predicate sequence)  
  (cond ((null? sequence) '())  
        ((predicate (car sequence))  
         (cons (car sequence)  
               (filter predicate (cdr sequence))))  
        (else (filter predicate (cdr sequence)))))

(define (flatmap proc seq)
  (accumulate append '() (map proc seq)))

(define (accumulate op initial sequence)  
  (if (null? sequence)  
      initial  
      (op (car sequence)  
          (accumulate op initial (cdr sequence)))))

(define (enumerate-interval n m)
  (if (> n m)
      '()
      (cons n (enumerate-interval (+ n 1) m))))

(queens 8)

 

((1 5 8 6 3 7 2 4)

 (1 6 8 3 7 4 2 5)

 (1 7 4 6 8 2 5 3)

 (1 7 5 8 2 4 6 3)

 (2 4 6 8 3 1 7 5)

 (2 5 7 1 3 8 6 4)

 (2 5 7 4 1 8 6 3)

 (2 6 1 7 4 8 3 5)

 (2 6 8 3 1 4 7 5)

 (2 7 3 6 8 5 1 4)

 (2 7 5 8 1 4 6 3)

 (2 8 6 1 3 5 7 4)

 (3 1 7 5 8 2 4 6)

 (3 5 2 8 1 7 4 6)

 (3 5 2 8 6 4 7 1)

 (3 5 7 1 4 2 8 6)

 (3 5 8 4 1 7 2 6)

 (3 6 2 5 8 1 7 4)

 (3 6 2 7 1 4 8 5)

 (3 6 2 7 5 1 8 4)

 (3 6 4 1 8 5 7 2)

 (3 6 4 2 8 5 7 1)

 (3 6 8 1 4 7 5 2)

 (3 6 8 1 5 7 2 4)

 (3 6 8 2 4 1 7 5)

 (3 7 2 8 5 1 4 6)

 (3 7 2 8 6 4 1 5)

 (3 8 4 7 1 6 2 5)

 (4 1 5 8 2 7 3 6)

 (4 1 5 8 6 3 7 2)

 (4 2 5 8 6 1 3 7)

 (4 2 7 3 6 8 1 5)

 (4 2 7 3 6 8 5 1)

 (4 2 7 5 1 8 6 3)

 (4 2 8 5 7 1 3 6)

 (4 2 8 6 1 3 5 7)

 (4 6 1 5 2 8 3 7)

 (4 6 8 2 7 1 3 5)

 (4 6 8 3 1 7 5 2)

 (4 7 1 8 5 2 6 3)

 (4 7 3 8 2 5 1 6)

 (4 7 5 2 6 1 3 8)

 (4 7 5 3 1 6 8 2)

 (4 8 1 3 6 2 7 5)

 (4 8 1 5 7 2 6 3)

 (4 8 5 3 1 7 2 6)

 (5 1 4 6 8 2 7 3)

 (5 1 8 4 2 7 3 6)

 (5 1 8 6 3 7 2 4)

 (5 2 4 6 8 3 1 7)

 (5 2 4 7 3 8 6 1)

 (5 2 6 1 7 4 8 3)

 (5 2 8 1 4 7 3 6)

 (5 3 1 6 8 2 4 7)

 (5 3 1 7 2 8 6 4)

 (5 3 8 4 7 1 6 2)

 (5 7 1 3 8 6 4 2)

 (5 7 1 4 2 8 6 3)

 (5 7 2 4 8 1 3 6)

 (5 7 2 6 3 1 4 8)

 (5 7 2 6 3 1 8 4)

 (5 7 4 1 3 8 6 2)

 (5 8 4 1 3 6 2 7)

 (5 8 4 1 7 2 6 3)

 (6 1 5 2 8 3 7 4)

 (6 2 7 1 3 5 8 4)

 (6 2 7 1 4 8 5 3)

 (6 3 1 7 5 8 2 4)

 (6 3 1 8 4 2 7 5)

 (6 3 1 8 5 2 4 7)

 (6 3 5 7 1 4 2 8)

 (6 3 5 8 1 4 2 7)

 (6 3 7 2 4 8 1 5)

 (6 3 7 2 8 5 1 4)

 (6 3 7 4 1 8 2 5)

 (6 4 1 5 8 2 7 3)

 (6 4 2 8 5 7 1 3)

 (6 4 7 1 3 5 2 8)

 (6 4 7 1 8 2 5 3)

 (6 8 2 4 1 7 5 3)

 (7 1 3 8 6 4 2 5)

 (7 2 4 1 8 5 3 6)

 (7 2 6 3 1 4 8 5)

 (7 3 1 6 8 5 2 4)

 (7 3 8 2 5 1 6 4)

 (7 4 2 5 8 1 3 6)

 (7 4 2 8 6 1 3 5)

 (7 5 3 1 6 8 2 4)

 (8 2 4 1 7 5 3 6)

 (8 2 5 3 1 7 4 6)

 (8 3 1 6 2 5 7 4)

 (8 4 1 3 6 2 7 5))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值