【问题标题】:Solving Eight-queens in scheme解决方案中的八皇后
【发布时间】:2021-08-23 01:44:43
【问题描述】:

我开始编写一个函数来查看皇后是否相对于棋盘上的其他位置是“安全的”,棋盘的形式为(row col) 和 1-indexed。到目前为止,这是我所拥有的:

(define (get-row p) (car p))
(define (get-col p) (cadr p))
(define (is-equal p1 p2)
  (and (= (car p1) (car p2)) (= (cadr p1) (cadr p2))))

(define (safe? k positions)
  (filter
     (lambda (p) (not (and (is-equal p
                               (list (get-row p) k))
                     (is-equal p
                               (list (+ (get-row p) (- k (get-col p)))
                                     k
                                     ))
                     (is-equal p
                               (list (- (get-row p) (- k (get-col p)))
                                     k
                                     )))))
   positions))

我想这样称呼它:

(safe? 4 '((3 1) (1 2) (4 3) (2 4)))

查看棋盘上位置(2 4) 的第四个皇后(第四列)是否安全。

但是,我目前拥有的内容超出了标记范围,并且基本上返回了所有“其他”列,而不是我想要的列。有什么更好的方法来做到这一点?

【问题讨论】:

    标签: scheme lisp sicp n-queens


    【解决方案1】:

    有很多方法可以解决这个问题。对于初学者,我建议使用更简单的电路板表示,我选择使用数字列表。列表中的索引从 1 开始,表示女王所在的列及其所在行的值(坐标原点在左上角,新位置在列表末尾相邻);所有其他位置都假定为空。比如下面这个板子:

    (. Q)
    (Q .)
    

    将由列表'(2 1) 表示。根据我的表述,safe? 过程看起来像这样 - 请注意,diagonals? 检查实现起来有点棘手:

    ; a new queen is safe iff there are no other queens in the same
    ; row nor in any of the diagonals preceding its current position
    ; we don't need to check the column, this is the only queen on it
    
    (define (safe? col board)
      (let ((row (list-ref board (- col 1))))
        (and (<= (number-occurrences row board) 1)
             (diagonals? row board))))
    
    ; counts how many times an element appears on a list
    
    (define (number-occurrences e lst)
      (count (curry equal? e) lst))
    
    ; traverses the board looking for other queens
    ; located in one of the diagonals, going backwards
    ; starting from the location of the newest queen
    
    (define (diagonals? row board)
      (let loop ((lst   (cdr (reverse board)))
                 (upper (sub1 row))
                 (lower (add1 row)))
        (or (null? lst)
            (and (not (= (car lst) upper))
                 (not (= (car lst) lower))
                 (loop (cdr lst) (sub1 upper) (add1 lower))))))
    

    结果如预期:

    (safe? 4 '(2 4 1 3))
    => #t
    

    如果您愿意,可以调整上述代码以使用不同的坐标原点,或者使用成对的坐标来表示皇后。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多