对于一项任务,我必须使用命名光盘在 Common LISP 中创建河内塔。我需要得到如下所示的输出:
[1]> (hanoi '(Small Medium Large))
Moved SMALL from Peg 1 to Peg 3
Moved MEDIUM from Peg 1 to Peg 2
Moved SMALL from Peg 3 to Peg 2
Moved LARGE from Peg 1 to Peg 3
Moved SMALL from Peg 2 to Peg 1
Moved MEDIUM from Peg 2 to Peg 3
Moved SMALL from Peg 1 to Peg 3
NIL
[2]> peg1
NIL
[3]> peg2
NIL
[4]> peg3
(Small Medium Large)
然而,当我运行我创建的程序时,我得到如下输出:
[1]> (hanoi '(Small Medium Large))
Move SMALL from Peg 1 to Peg 2
Move SMALL from Peg 1 to Peg 2
Move NIL from Peg 2 to Peg 2
Move SMALL from Peg 1 to Peg 2
Move NIL from Peg 2 to Peg 1
Move NIL from Peg 2 to Peg 2
Move SMALL from Peg 1 to Peg 2
NIL
[2]> peg1
(Small Medium Large)
[3]> peg2
NIL
[4]> peg3
NIL
这是我的代码:
(defvar *peg1* '())
(defvar *peg2* '())
(defvar *peg3* '())
(defun peg-name (peg)
(cond ((equal peg *peg1*) "Peg 1")
((equal peg *peg2*) "Peg 2")
((equal peg *peg3*) "Peg 3")))
(defun move-disk (from to)
(format t "Move ~a from ~a to ~a~%" (first from) (peg-name from) (peg-name to))
(push (pop from) to))
(defun transfer (n source aux dest)
(if (> n 0)
(progn
(transfer (1- n) source dest aux)
(move-disk source dest)
(transfer (1- n) aux source dest))))
(defun hanoi (disk-list)
(setq *peg1* disk-list)
(transfer (length disk-list) *peg1* *peg2* *peg3*))
代码的问题显然是 move-disk 函数,因为它只是在调用后丢弃结果。但我不确定我如何准确地确定我应该从哪些全局变量中推送和弹出。我一直在摆弄使用一个大列表来表示塔并将钉子作为子列表,但是我在确定要修改列表的哪一部分时遇到了同样的问题。任何帮助,将不胜感激。我觉得我完全处于死胡同。