Scheme 为什么我的n-queens代码返回空列表?
我现在正在处理。我知道我的Scheme 为什么我的n-queens代码返回空列表?,scheme,lisp,sicp,Scheme,Lisp,Sicp,我现在正在处理。我知道我的邻接位置函数有问题,因为当我用 (define (adjoin-position-WORKING new-row k rest-of-queens) (cons (list new-row k) rest-of-queens)) 我从queens获得了合理的输出 在此替换之前,我使用练习模板的代码如下: #lang sicp ;;Boilerplate functions that the exercise calls: (define (filter pre
邻接位置
函数有问题,因为当我用
(define (adjoin-position-WORKING new-row k rest-of-queens)
(cons (list new-row k) rest-of-queens))
我从queens
获得了合理的输出
在此替换之前,我使用练习模板的代码如下:
#lang sicp
;;Boilerplate functions that the exercise calls:
(define (filter predicate sequence)
(cond ((null? sequence) nil)
((predicate (car sequence))
(cons (car sequence)
(filter predicate (cdr sequence))))
(else (filter predicate (cdr sequence)))))
(define (enumerate-interval low high)
(cond ((> low high) nil)
((= low high) (list high))
(else (cons low (enumerate-interval (+ 1 low) high)))))
(define (flatmap proc seq)
(accumulate append nil (map proc seq)))
(define (accumulate op initial sequence)
(if (null? sequence)
initial
(op (car sequence)
(accumulate op initial (cdr sequence)))))
;;;Start of solution:
(define empty-board nil)
;Placeholder, stops the filter from actually filtering anything:
(define (safe? new-queen-col-numb old-solutions) #t)
;;THE RELEVANT BIT
(define (adjoin-position ultimate-row-index new-queen-col-pos old-solutions)
(define (iter to-append-left to-append-right depth)
(cond ((null? to-append-right) to-append-left)
((= depth 1)
(append to-append-left (cons new-queen-col-pos to-append-right)))
(else (iter (append to-append-left (list (car to-append-right)))
(cdr old-solutions)
(- depth 1)))))
(iter nil old-solutions ultimate-row-index))
;;The template provided by the exercise, untouched by me:
(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))
;;Example of adjoin-position working as expected:
(adjoin-position 2 5 (list 10 11 12 13 14 15 16))
;Output: (10 5 11 12 13 14 15 16)
;i.e. it placed 5 at position 2, as I wanted it to.
;;Code to show that my adjoin-position is bugged.
(map queens (enumerate-interval 1 3))
最后一个函数(map queens(枚举间隔13))
的输出令人恐惧:
((())
(() () () ())
(()
()
()
()
()
()
()
()
()
()
()
()
()
()
()
()
()
()
()
()
()
()
()
()
()
()
()))
用邻接位置工作
替换邻接位置
后,我的输出更容易接受:
((((1 1)))
(((1 2) (1 1)) ((2 2) (1 1)) ((1 2) (2 1)) ((2 2) (2 1)))
(((1 3) (1 2) (1 1))
((2 3) (1 2) (1 1))
((3 3) (1 2) (1 1))
((1 3) (2 2) (1 1))
((2 3) (2 2) (1 1))
((3 3) (2 2) (1 1))
((1 3) (3 2) (1 1))
((2 3) (3 2) (1 1))
((3 3) (3 2) (1 1))
((1 3) (1 2) (2 1))
((2 3) (1 2) (2 1))
((3 3) (1 2) (2 1))
((1 3) (2 2) (2 1))
((2 3) (2 2) (2 1))
((3 3) (2 2) (2 1))
((1 3) (3 2) (2 1))
((2 3) (3 2) (2 1))
((3 3) (3 2) (2 1))
((1 3) (1 2) (3 1))
((2 3) (1 2) (3 1))
((3 3) (1 2) (3 1))
((1 3) (2 2) (3 1))
((2 3) (2 2) (3 1))
((3 3) (2 2) (3 1))
((1 3) (3 2) (3 1))
((2 3) (3 2) (3 1))
((3 3) (3 2) (3 1))))
因此,既然我们已经确定原来的邻接位置
被窃听了,并且返回了一个空列表列表,而不是包括数字在内的任何内容,我就剩下真正的问题了——原来的邻接位置
哪里出错了?对我来说,最大的惊喜不仅是(邻接位置25(列表1011213141516))
工作得很好,而且皇后
应该调用我理解的(邻接位置11(列表nil))
,这也给出了一个可用的结果:(1())
。我是否误解了皇后
传递到邻接位置的参数
我还没有学会如何调试方案代码,但将调用(map(lambda(新行)…
替换为调用map debug
:
(define (map-debug proc seq)
(display "Input list: ")
(display seq)
(newline)
(display "Output list:")
(display (map proc seq))
(newline)
(map proc seq))
为(映射皇后(枚举间隔12))生成以下输出
这意味着bug在下面的代码块中,但我没有看到它
(lambda (rest-of-queens)
(map (lambda (new-row)
(adjoin-position new-row k rest-of-queens))
(enumerate-interval 1 board-size)))
(lambda (rest-of-queens)
(map (lambda (new-row)
(adjoin-position new-row k rest-of-queens))
(enumerate-interval 1 board-size)))
我所能理解的最远的是(=depth 1)相邻位置的分支cond
语句似乎从未运行过。我不知道为什么,我只知道在其中粘贴显示
行表示该分支从未使用过。它的旧解决方案
参数似乎正在传递nil
?首先让我描述一下我对它的理解他的计划是为了工作。因为如果我们对它应该如何工作有不同的想法,那么理解它的实施是很困难的
假设我们已经有了单列和双列问题的第一个解决方案:
First of 8 Solutions To the 1-Column Problem:
=============================================
_
|_|
|_|
|_|
|_|
|_|
|_|
|_|
|Q|
position: ((1 1))
First of 42 Solutions To the 2-Column Problem:
==============================================
_ _
|_|_|
|_|_|
|_|_|
|_|_|
|_|_|
|_|Q|
|_|_|
|Q|_|
position: ((2 3) (1 1))
对于3列问题,我们从2列问题的第一个解决方案开始,然后为8个可能的行生成8个可能的板位置。皇后可以放置在第3列中:
First 8 Positions to Test as Possible Solutions To the 3-Column Problem:
========================================================================
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|_|_|_ |_|_|_ |_|_|_ |_|_|_ |_|_|_ |_|_|_ |_|_|_ |_|_|?
|_|_|_ |_|_|_ |_|_|_ |_|_|_ |_|_|_ |_|_|_ |_|_|? |_|_|_
|_|_|_ |_|_|_ |_|_|_ |_|_|_ |_|_|_ |_|_|? |_|_|_ |_|_|_
|_|_|_ |_|_|_ |_|_|_ |_|_|_ |_|_|? |_|_|_ |_|_|_ |_|_|_
|_|_|_ |_|_|_ |_|_|_ |_|_|? |_|_|_ |_|_|_ |_|_|_ |_|_|_
|_|Q|_ |_|Q|_ |_|Q|? |_|Q|_ |_|Q|_ |_|Q|_ |_|Q|_ |_|Q|_
|_|_|_ |_|_|? |_|_|_ |_|_|_ |_|_|_ |_|_|_ |_|_|_ |_|_|_
|Q|_|? |Q|_|_ |Q|_|_ |Q|_|_ |Q|_|_ |Q|_|_ |Q|_|_ |Q|_|_
First 8 positions to test:
((3 1) (2 3) (1 1))
((3 2) (2 3) (1 1))
((3 3) (2 3) (1 1))
((3 4) (2 3) (1 1))
((3 5) (2 3) (1 1))
((3 6) (2 3) (1 1))
((3 7) (2 3) (1 1))
((3 8) (2 3) (1 1))
调用Adjoin position 8次,通过扩展2列解决方案来创建要测试的位置(造成混淆的一个可能原因是,Adjoin position的前两个参数是row然后col,但传统上位置是col然后row)
然后对其进行过滤,给出三列问题的四个解决方案,这四个解决方案扩展了第一个两列解决方案
First 4 (of 140) Solutions to the 3-Column problem:
===================================================
positions:
((3 5) (2 3) (1 1))
((3 6) (2 3) (1 1))
((3 7) (2 3) (1 1))
((3 8) (2 3) (1 1))
_ _ _ _ _ _ _ _ _ _ _ _
|_|_|_ |_|_|_ |_|_|_ |_|_|Q
|_|_|_ |_|_|_ |_|_|Q |_|_|_
|_|_|_ |_|_|Q |_|_|_ |_|_|_
|_|_|Q |_|_|_ |_|_|_ |_|_|_
|_|_|_ |_|_|_ |_|_|_ |_|_|_
|_|Q|_ |_|Q|_ |_|Q|_ |_|Q|_
|_|_|_ |_|_|_ |_|_|_ |_|_|_
|Q|_|_ |Q|_|_ |Q|_|_ |Q|_|_
正如您所看到的,我的邻接位置与您的非常不同,它接受列表列表并返回更长的列表列表(板上皇后的坐标)
我发现理解我自己的解决方案已经够难了,目前我正在努力理解你的解决方案是如何工作的。如果我描述的图像/算法部分与你的解决方案相匹配,并且只是不同位置的表示/实现,那么如果你能描述你如何表示ose位置。例如,您希望看到什么,而不是:
(adjoin-position 1 3 ((2 3) (1 1))) => ((3 1) (2 3) (1 1))
(adjoin-position 2 3 ((2 3) (1 1))) => ((3 2) (2 3) (1 1))
(adjoin-position 3 3 ((2 3) (1 1))) => ((3 3) (2 3) (1 1))
...
首先让我描述一下我是如何理解这个计划的,因为如果我们对它应该如何工作有不同的想法,那么理解它的实现是很困难的
假设我们已经有了单列和双列问题的第一个解决方案:
First of 8 Solutions To the 1-Column Problem:
=============================================
_
|_|
|_|
|_|
|_|
|_|
|_|
|_|
|Q|
position: ((1 1))
First of 42 Solutions To the 2-Column Problem:
==============================================
_ _
|_|_|
|_|_|
|_|_|
|_|_|
|_|_|
|_|Q|
|_|_|
|Q|_|
position: ((2 3) (1 1))
对于3列问题,我们从2列问题的第一个解决方案开始,然后为8个可能的行生成8个可能的板位置。皇后可以放置在第3列中:
First 8 Positions to Test as Possible Solutions To the 3-Column Problem:
========================================================================
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|_|_|_ |_|_|_ |_|_|_ |_|_|_ |_|_|_ |_|_|_ |_|_|_ |_|_|?
|_|_|_ |_|_|_ |_|_|_ |_|_|_ |_|_|_ |_|_|_ |_|_|? |_|_|_
|_|_|_ |_|_|_ |_|_|_ |_|_|_ |_|_|_ |_|_|? |_|_|_ |_|_|_
|_|_|_ |_|_|_ |_|_|_ |_|_|_ |_|_|? |_|_|_ |_|_|_ |_|_|_
|_|_|_ |_|_|_ |_|_|_ |_|_|? |_|_|_ |_|_|_ |_|_|_ |_|_|_
|_|Q|_ |_|Q|_ |_|Q|? |_|Q|_ |_|Q|_ |_|Q|_ |_|Q|_ |_|Q|_
|_|_|_ |_|_|? |_|_|_ |_|_|_ |_|_|_ |_|_|_ |_|_|_ |_|_|_
|Q|_|? |Q|_|_ |Q|_|_ |Q|_|_ |Q|_|_ |Q|_|_ |Q|_|_ |Q|_|_
First 8 positions to test:
((3 1) (2 3) (1 1))
((3 2) (2 3) (1 1))
((3 3) (2 3) (1 1))
((3 4) (2 3) (1 1))
((3 5) (2 3) (1 1))
((3 6) (2 3) (1 1))
((3 7) (2 3) (1 1))
((3 8) (2 3) (1 1))
调用Adjoin position 8次,通过扩展2列解决方案来创建要测试的位置(造成混淆的一个可能原因是,Adjoin position的前两个参数是row然后col,但传统上位置是col然后row)
然后对其进行过滤,给出三列问题的四个解决方案,这四个解决方案扩展了第一个两列解决方案
First 4 (of 140) Solutions to the 3-Column problem:
===================================================
positions:
((3 5) (2 3) (1 1))
((3 6) (2 3) (1 1))
((3 7) (2 3) (1 1))
((3 8) (2 3) (1 1))
_ _ _ _ _ _ _ _ _ _ _ _
|_|_|_ |_|_|_ |_|_|_ |_|_|Q
|_|_|_ |_|_|_ |_|_|Q |_|_|_
|_|_|_ |_|_|Q |_|_|_ |_|_|_
|_|_|Q |_|_|_ |_|_|_ |_|_|_
|_|_|_ |_|_|_ |_|_|_ |_|_|_
|_|Q|_ |_|Q|_ |_|Q|_ |_|Q|_
|_|_|_ |_|_|_ |_|_|_ |_|_|_
|Q|_|_ |Q|_|_ |Q|_|_ |Q|_|_
正如您所看到的,我的邻接位置与您的非常不同,它接受列表列表并返回更长的列表列表(板上皇后的坐标)
我发现理解我自己的解决方案已经够难了,目前我正在努力理解你的解决方案是如何工作的。如果我描述的图像/算法部分与你的解决方案相匹配,并且只是不同位置的表示/实现,那么如果你能描述你如何表示ose位置。例如,您希望看到什么,而不是:
(adjoin-position 1 3 ((2 3) (1 1))) => ((3 1) (2 3) (1 1))
(adjoin-position 2 3 ((2 3) (1 1))) => ((3 2) (2 3) (1 1))
(adjoin-position 3 3 ((2 3) (1 1))) => ((3 3) (2 3) (1 1))
...
问题是找到bug,问题几乎成功了。在问题中,我们得到了:
似乎它的旧解决方案
参数被传递为nil
解释这一点,以及由此产生的问题并不困难。确定的问题是:
这意味着bug在下面的代码块中,但我没有看到它
(lambda (rest-of-queens)
(map (lambda (new-row)
(adjoin-position new-row k rest-of-queens))
(enumerate-interval 1 board-size)))
(lambda (rest-of-queens)
(map (lambda (new-row)
(adjoin-position new-row k rest-of-queens))
(enumerate-interval 1 board-size)))
要理解哪里出了问题,我们需要查看rest of queens
参数。相关部分是rest of queens
将成为我们怀疑的旧解决方案
参数。从引用的这段代码中查找一个级别,我们发现传递给rest of queens
是列表中的条目(queen cols(-k 1))
(它通过调用flatmap
,这是一个map
)。这就是我们的错误所在。问题怀疑对邻接位置的调用是(邻接位置1(列表nil))
,其中(列表nil)
可能来自对(quee)的调用