【问题标题】:SICP 2.42 eight queens. Help check what's wrong with my code?SICP 2.42 八皇后。帮助检查我的代码有什么问题?
【发布时间】:2012-09-11 06:14:47
【问题描述】:

程序是生成八个皇后的所有可能结果。 我使用包含行号的列表作为数据结构。 但是当我运行它时,我得到了错误的结果。 这是我的代码:

(define (queens board-size)
  (define (safe? k position)
    (define (iter last-element front-lst col-num k)
      (define (ok? l-e car-lst)
    (and (not (= l-e car-lst))
         (not (= (abs (- l-e car-lst)) (abs (- k col-num))))))
      (if (null? front-lst)
      true
      (and (ok? last-element (car front-lst))
           (iter last-element (cdr front-lst) (++ col-num) k))))
    (let ((l-e (car (my-reverse position)))
      (f-l (my-remove (car (my-reverse position)) position)))
      (iter l-e f-l 1 k)))

  (define empty-board nil)

  (define (adjoin-position new-row k rest-of-queens)
    (append rest-of-queens (list new-row)))

  (define (queen-cols k)
    (if (= k 0)
    (list empty-board)
    (filter
     (lambda (positions) (safe? k positions))
     (my-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))))))
  (queen-cols board-size))

【问题讨论】:

  • 尝试先评论您的代码。我怀疑很多人有时间尝试了解您想要做什么。既然有错误,你甚至可能会发现它!
  • 你得到了什么,你期望得到什么?
  • 堆栈溢出通常不赞成人们简单地上传代码并说它会产生“错误的结果”。什么样的错误结果?代码的哪一部分被破坏了?等等。考虑编辑您的问题,并在发布问题之前阅读 stackoverflow 为您提供的页面。

标签: lisp scheme sicp mit-scheme


【解决方案1】:

我怀疑你的方法太复杂了。 你需要做的是:

为下一个皇后找到一个符合两个条件的新行号:1)它尚未包含 2)新行号与任何已使用的行号之间的距离不等于两行的距离.

以递归方式执行此操作。

我的 CL 解决方案供参考:

(defun fits (p list)
  (and (not (member p list))
       (loop for i in list as j from 1
            never (eql (abs (- p i)) j))))

(defun backtrack (list)
  (if (eql (length list) 8)
      (print list)
      (loop for i from 1 to 8
         when (fits i list)
           do (backtrack (cons i list)))))

运行

(backtrack nil)

【讨论】:

    【解决方案2】:

    我今天刚在SICP中完成了这个问题,所以我会在这里尝试帮助:

    我用这个 my-remove 测试了你的代码:

    (define (my-remove num num-list)
        (cond   ((null? num-list) nil)
                ((= num (car num-list)) (cdr num-list))
                (else (cons (car num-list) (my-remove num (cdr num-list))))))
    

    测试:

    (let ((result (queens 8)))
    (display (length result))(newline)
    (map (lambda (possible-solution) (display possible-solution)(newline)) result)
    )
    

    返回 92 . . (3 7 2 8 5 1 4 6) (3 7 2 8 6 4 1 5) . .

    92个结果,其中一个是书中的解

    这是您代码的一部分(略微)重构,我摆脱了 my-remove,并使用了 let*。 我不打算重构整个事情,但我至少尝试在变量名中添加含义。 通过这些更改,它更快了一些: (还添加了一些cmets)

    ;no major refactoring, essentially removed my-remove and some refactors
    (define (queens board-size)
      (define (safe? k position)
        (define (iter last-element front-lst col-num k)
            ;what's ok?
          (define (ok? l-e car-lst)
                (and (not (= l-e car-lst))
                    (not (= (abs (- l-e car-lst)) (abs (- k col-num))))))
          (if (null? front-lst)
          true
          (and (ok? last-element (car front-lst))
               (iter last-element (cdr front-lst) (++ col-num) k))))
        ;queens means a list of rows, each representing a queen position
        ;that is, when queens[col] = row  that means there's a queen in row 'row and 
        ;column 'col
    
        ;reimplementing removing the queen, and the let turned to let*
        (let* ((reverse-column-queens (my-reverse position))
               (last-queen (car reverse-column-queens))
            ;remove that queen from the list
            ;btw 'position is actually 'positions
            (all-other-queens (my-reverse (cdr reverse-column-queens))))
          (iter last-queen all-other-queens 1 k)))
    .
    .
    .
    

    所以,我猜你使用的 my-remove 可能是错误的。

    现在,您的变量名称不是很具有描述性,因此它会添加到已经令人困惑的代码中(无意冒犯本练习的作者或您)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-17
      • 1970-01-01
      • 1970-01-01
      • 2020-07-19
      相关资源
      最近更新 更多