For loop LispWorks中的嵌套for循环(4x4皇后)

For loop LispWorks中的嵌套for循环(4x4皇后),for-loop,common-lisp,n-queens,For Loop,Common Lisp,N Queens,我刚刚开始使用LispWorks,正在解决4x4 Queen问题。我想做的是在4个for循环的帮助下陈述所有可能的皇后组合,然后检查它们是否是可能的解决方案。例如,一个可能的状态(1 3 4 2)意味着在第1行中queen在第1列中,在第2行中queen在第3列中,依此类推 我认为我做错了什么,因为编译器不喜欢我的循环。我得到的错误类似于:循环关键字应在 代码如下: (loop for i in '(1 2 3 4) nconc (loop for j in '(1 2 3 4)

我刚刚开始使用LispWorks,正在解决4x4 Queen问题。我想做的是在4个for循环的帮助下陈述所有可能的皇后组合,然后检查它们是否是可能的解决方案。例如,一个可能的状态(1 3 4 2)意味着在第1行中queen在第1列中,在第2行中queen在第3列中,依此类推

我认为我做错了什么,因为编译器不喜欢我的循环。我得到的错误类似于:循环关键字应在

代码如下:

(loop for i in '(1 2 3 4) 
  nconc (loop for j in '(1 2 3 4) 
              nconc (loop for k in '(1 2 3 4) 
                          nconc (loop for l in '(1 2 3 4) 


                                     (defvar first 0)
                                     (defvar second 0)
                                     (defvar third 0)
                                     (defvar fourth 0)
                                     (setq first (abs (- 1 i)))
                                     (setq second (abs (- 2 j)))
                                     (setq third (abs (- 3 k)))
                                     (setq fourth (abs (- 4 l)))
                                     (if (and (not (eq first second)) (not (eq first third)) (not (eq first fourth)) (not (eq second third)) 
                                                (not (eq second fourth)) (not (eq first second)) (not (eq third fourth)))
                                           (if (and (or (eq i j) (eq i k) (eq i l) (eq j k) (eq j l)) (or (eq k l)))
                                               (print i j k l)))))))
请帮助我解决嵌套循环,并随时对我的代码进行评论,并可能提出解决此问题的更好方法。请保持它相当基本,我是LispWorks的完全初学者,我以前只做过一些Ada95和Java


提前感谢

您收到错误消息的原因是您的代码在内部循环中的
'(1 2 3 4)
之后缺少关键字
do
。由于您不是从循环中收集结果,而是打印最终结果,因此您也应该在外部循环中使用
do
而不是
ncoc

解决此问题后,会出现另一个错误:
print
仅打印一个对象,因此为了打印所有四个数字,您可以使用例如
(print(list i j k l))

然后程序打印

(1 1 1 1) 
(1 3 1 1) 
(2 2 1 1) 
(4 2 2 2) 
(4 4 3 3) 
(4 4 4 4)
所以逻辑也有问题

但是,还可以对代码进行许多改进:

(loop for i in '(1 2 3 4) 
  nconc (loop for j in '(1 2 3 4) 
              nconc (loop for k in '(1 2 3 4) 
                          nconc (loop for l in '(1 2 3 4) 


                                     (defvar first 0)
                                     (defvar second 0)
                                     (defvar third 0)
                                     (defvar fourth 0)
                                     (setq first (abs (- 1 i)))
                                     (setq second (abs (- 2 j)))
                                     (setq third (abs (- 3 k)))
                                     (setq fourth (abs (- 4 l)))
                                     (if (and (not (eq first second)) (not (eq first third)) (not (eq first fourth)) (not (eq second third)) 
                                                (not (eq second fourth)) (not (eq first second)) (not (eq third fourth)))
                                           (if (and (or (eq i j) (eq i k) (eq i l) (eq j k) (eq j l)) (or (eq k l)))
                                               (print i j k l)))))))
  • 不要使用
    defvar
    在循环中引入新变量
    defvar
    创建动态(“全局”)变量。相反,使用
    let
    ,或者将它们作为循环变量引入,就像您使用
    i
    j
    等所做的那样
  • 不要先创建变量,然后使用
    setq
    更新一次,而是在创建变量时给它们正确的值(使用
    let
    或循环键)
  • 当您比较成对的数字时:不要使用
    eq
    (用于符号)或
    eql
    (用于比较相同类型的两个数字的正确方法),而是使用
    =
    /=
    来比较多个数字,以检查它们是否都相等/不同
  • 再加上对逻辑的一点修改,这将产生以下代码(为了便于说明,该代码引入了一些使用循环关键字的变量,还有一些使用
    let
    ):

    导致

    (2 4 3 1) 
    (3 2 4 1) 
    (4 1 3 2) 
    (4 2 1 3) 
    
    这意味着仍然存在逻辑错误

    希望简化的代码可以很容易地发现错误,这可能与不比较
    (+i1)
    (+j2)
    等有关


    最后:如果您想扩展代码以处理更多的皇后,那么创建递归解决方案将比使用更多嵌套循环的解决方案更好。

    非常感谢您的回复。然而,我似乎真的无法让它工作。我在if子句中添加了(/=(+i1)(+j2)(+k3)(+l4)),但现在它返回nil。你能再给我一点小费吗?我认为即使在对角线上进行abs检查也足够了。谢谢你的光临advance@RichardBerg删除对abs的调用,使测试的第一部分变成(/=(1-i)(2-j)(3-k)(4-l))