lisp 正负之间的区别
lisp difference between plus and minus
好吧,我正在用 Lisp 编写一个程序来解决拼图难题 (http://www.tilepuzzles.com/default.asp?p=12),但我的两个函数有问题。我对 "swap" 空磁贴有单独的功能,上面、下面、左侧或右侧都有一个,但只有上方和左侧有效。 switch_above 和 switch_below 之间的唯一区别是在一个中使用 +
而在另一个中使用 -
(见代码),据我所知是什么导致了问题。
;;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
"state"列表是这样设置的:
(1 2 3 4 E 5 6 7 8)
其中 E 是空方块
find_empty
returns 空块的位置,所以它会 return 4 在上面的状态。
如上所写,switch_above
有效,但 switch_below
无效。
想一想当您在 switch_below
中执行第一个 SETF
时会发生什么。
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 监听器中(一个 Read Eval Print Loop)。 read
部分通常为每个交互分配一个全新的列表,并且在实现中通常这些列表不受任何保护。会出什么问题? a) 可以保护列表不被修改。 b) 它可以与其他列表共享结构(这可能很难被用户检测到)。
在程序中最好这样写
(switch-below (copy-list '(1 2 3 4 E 5 6 7 8)))
避免上述问题。
好吧,我正在用 Lisp 编写一个程序来解决拼图难题 (http://www.tilepuzzles.com/default.asp?p=12),但我的两个函数有问题。我对 "swap" 空磁贴有单独的功能,上面、下面、左侧或右侧都有一个,但只有上方和左侧有效。 switch_above 和 switch_below 之间的唯一区别是在一个中使用 +
而在另一个中使用 -
(见代码),据我所知是什么导致了问题。
;;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
"state"列表是这样设置的:
(1 2 3 4 E 5 6 7 8)
其中 E 是空方块
find_empty
returns 空块的位置,所以它会 return 4 在上面的状态。
如上所写,switch_above
有效,但 switch_below
无效。
想一想当您在 switch_below
中执行第一个 SETF
时会发生什么。
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 监听器中(一个 Read Eval Print Loop)。 read
部分通常为每个交互分配一个全新的列表,并且在实现中通常这些列表不受任何保护。会出什么问题? a) 可以保护列表不被修改。 b) 它可以与其他列表共享结构(这可能很难被用户检测到)。
在程序中最好这样写
(switch-below (copy-list '(1 2 3 4 E 5 6 7 8)))
避免上述问题。