加号和减号之间的差异

时间:2015-10-03 20:35:28

标签: lisp common-lisp

好吧,所以我在Lisp中编写一个程序来解决拼图(http://www.tilepuzzles.com/default.asp?p=12),我的两个函数都有问题。我有单独的功能来“交换”空的瓷砖与它的上方,下方,左侧或右侧,但只有上面和左侧工作。 switch_above和switch_below之间的唯一区别是在一个中使用+而在另一个中使用-(参见代码),据我所知,这是造成问题的原因。< / p>

;;Switches the Empty tile with whatever is above it
(defun switch_above (state)
  (let ((x (nth (- (find_empty state) 3) state)))    ;;Find the number that   is above the Empty tile, set as X
    (setf (nth (find_empty state) state) x)          ;;Replace the Empty tile with X
    (setf (nth (position x state) state) 'E)) state) ;;Put Empty tile where X was

;;Switches the Empty tile with whatever is below it
(defun switch_below (state)
  (let ((x (nth (+ (find_empty state) 3) state)))    ;;Find the number that is below the Empty tile, set as X
    (setf (nth (find_empty state) state) x)          ;;Replace the Empty tile with X
    (setf (nth (position x state) state) 'E)) state) ;;Put Empty tile where X was

“状态”列表设置如下: (1 2 3 4 E 5 6 7 8)其中E是空图块

find_empty返回空图块的位置,因此它将在上述状态下返回4.

撰写时switch_above可以正常使用,但switch_below没有。

1 个答案:

答案 0 :(得分:4)

考虑在SETF中执行第一次switch_below时会发生什么。

ROTATEF旋转地点

尝试使用Common Lisp宏ROTATEF。见这个例子:

CL-USER 76 > (defun find-empty (state)
               (position 'e state))
FIND-EMPTY

CL-USER 77 > (defun switch-below (state &aux (empty-pos (find-empty state)))
               (rotatef (nth empty-pos       state)
                        (nth (+ empty-pos 3) state))
               state)
SWITCH-BELOW

CL-USER 78 > (switch-below '(1 2 3 4 E 5 6 7 8))
(1 2 3 4 7 5 6 E 8)

顺便说一句:如果有人想知道为什么我在上面的交互中使用了引用列表。在Common Lisp中,修改文字列表的后果是未定义的。好吧,我们使用的是Lisp Listener(Read Eval Print Loop)。 read部分通常为每个交互分配一个新的新列表,并且在实现中通常这些列表不受任何保护。怎么可能出错? a)列表可以再次受到保护修改。 b)它可以与其他列表共享结构(可能很难被用户检测到)。

在程序中最好写一些像

这样的东西
(switch-below (copy-list '(1 2 3 4 E 5 6 7 8)))

避免上述问题。