递归lisp函数来解决N-Queen

时间:2015-09-23 03:58:17

标签: recursion common-lisp n-queens

更新:代码应该现在编译,没有错误或警告。对前一个抱歉。我现在遇到的问题是运行时(或任何其他整数)

(NxNqueen-solver 10)

函数 getqueencol 将返回nil,因为首先在棋盘上没有皇后,因此皇后可能会有一个(=数字为零)放在这里因为tcol是零。我认为每当没有女王作为女王可以放置在这里函数的参数传递时,就会发生这种情况。

请分享一些有关如何解决此问题的建议。提前谢谢。

这是代码

(defvar *board* (make-array '(10 10) :initial-element nil)) 


(defun getqueencol (row n)
"Traverses through the columns of a certain row
 and returns the column index of the queen."
  (loop for i below n
        do (if (aref *board* row i)
               (return-from getqueencol i))))

(defun print-board (n)
"Prints out the solution, e.g. (1 4 2 5 3),
 where 1 denotes that there is a queen at the first 
 column of the first row, and so on."
  (let ((solutionlist (make-list n)))
    (loop for row below n
          do (loop for col below n
                   do (when (aref *board* row col)
                        (setf (nth row solutionlist) col))))
    (print solutionlist)))


(defun queen-can-be-placed-here (row col n)
"Returns t if (row,col) is a possible place to put queen, otherwise nil."
  (loop for i below n
       do (let ((tcol (getqueencol i n)))
            (if (or (= col tcol) (= (abs (- row i)) (abs (- col tcol))))
                (return-from queen-can-be-placed-here nil)))))



(defun backtracking (row n)
"Solves the NxN-queen problem with backtracking"
  (if (< row n)
      (loop for i below n
          do (when (queen-can-be-placed-here row i n)
                  (setf (aref *board* row i) 't)
                  (return-from backtracking (backtracking (+ row 1) n))
                  (setf (aref *board* row i) 'nil))
    (print-board n))))

(defun NxNqueen-solver (k)
"Main program for the function call to the recursive solving of the problem"
  (setf *board* (make-array '(k k) :initial-element nil))
  (backtracking 0 k))

1 个答案:

答案 0 :(得分:5)

你说你编译了你的代码。情况可能不是这样,因为那时你会看到编译器抱怨错误。您希望确保真正编译代码并更正代码,以便编译时没有错误和警告。

您可能希望摆脱代码中的错误/问题(请参阅Renzo的评论),然后查看算法问题。当代码包含错误时,我很难理解算法问题。

  • SETQ不会引入变量,变量必须在某处定义

  • DEFVAR在函数内部没有任何意义。

  • (let (x (sin a)) ...)这样的东西肯定是错的。 LET的语法需要在绑定列表周围添加一对括号。

  • RETURN-FROM将第一个参数作为要返回的现有的名称。可选的第二个参数是返回值。获取正确的语法并从正确的块返回。

  • 在致电MAKE-ARRAY时指定默认值:(make-array ... :initial-element nil),否则不清楚它是什么。

  • 变量*board*未定义

<强>风格

    LOOP中的
  • for i to (1- n)更简单for i below n

  • 您不需要引用NILT

  • (if (eq foo t) ...)可能更简单地写为(if foo ...)。特别是如果foo的值为NILT

  • (if foo (progn ...))只是(when foo ...)

我不确定您声称您的代码是在编译的。它没有编译。

每个函数都有编译器警告。您应该检查编译器警告并解决问题。

(defun getqueencol (row)
"Traverses through the columns of a certain row
 and returns the column index of the queen."
  (loop for i below n
        do (if (aref board row i)
               (return-from getqueencol i))))

编译器抱怨:

;;;*** Warning in GETQUEENCOL: N assumed special
;;;*** Warning in GETQUEENCOL: BOARD assumed special

n在哪里定义? board来自哪里?

(defun print-board (board)
"Prints out the solution, e.g. (1 4 2 5 3),
 where 1 denotes that there is a queen at the first 
 column of the first row, and so on."
  (let (solutionlist)
    (setq solutionlist (make-list n)))
  (loop for row below n
        do (loop for col below n
               do (when (aref board row col)
                      (setf (nth row solutionlist) col))))
  (print solutionlist))

LET毫无意义。 (let (foo) (setq foo bar) ...)(let ((foo bar)) ...)

为什么没有定义解决方案列表?看看LET ......这没有意义。

n来自哪里?

(defun queen-can-be-placed-here (row col)
"Returns t if (row,col) is a possible place to put queen, otherwise nil."
  (loop for i below n
       do (let (tcol)
            (setq tcol (getqueencol i)))
       (if (or (= col tcol) (= (abs (- row i)) (abs (- col tcol))))
          (return-from queen-can-be-placed-here nil))))

n来自哪里? LET毫无意义。

(defun backtracking (row)
"Solves the NxN-queen problem with backtracking"
  (if (< row n)
      (loop for i below n
          do (when (queen-can-be-placed-here row i)
                  (setf (aref board row i) 't)
                  (return-from backtracking (backtracking (+ row 1)))
                  (setf (aref board row i) 'nil))
    (print-board board))))

n来自哪里? board定义在哪里?

(defun NxNqueen-solver (k)
"Main program for the function call to the recursive solving of the problem"
    (let (n board)
          (setq n k)
          (setq board (make-array '(k k) :initial-element nil)))
        (backtracking 0))

为什么在setq时使用let?本地变量nboard未使用。

MAKE-ARRAY需要一个数字列表,而不是符号列表。

我建议您使用基本的Lisp介绍(Common Lisp: A Gentle Introduction to Symbolic Computation - 免费下载)和Lisp参考(CL Hyperspec)。