我正在学习常见的lisp我已经从uVA数据库(http://acm.uva.es/p/v101/10120.html)和广泛的搜索功能(它接受了开始点,目标点和合法移动生成器),我已经理解了我的意思是如何得到答案,但Lisp只是不同意我。关于如何从这一点开始,我可以提供一些建议吗?下面是给定问题的链接以及我的两个尝试使用lisp源代码的解决方案。任何帮助将不胜感激!谢谢!
1
(defun gift (N G)
(setq CR 9)
(setq i 3)
(cond ((= N G) "N and G equal")
((< N G) "Gift it on a rock outside limits")
((> N 49) "number of rocks is bigger than 49 - it will work")
((< N 9) "number of rocks is less than 9, it wont work")
((= N 0) "number of rocks is 0, it wont work")
((= G 0) "gift isn't on a rock, it wont work"))
(loop
(setq I (+ I 1))
(setq I (-(* I 2) 1))
(setq CR 9)
(breadth-search CR G #'lmg-moves)
(when (= CR G) (return "Let me Try!"))
(when (> CR N) (return "Don't laugh at me!"))
))
(defun lmg-moves (I)
(list (+ 9 I)
(- 9 I)
))
2
(defvar *currentRock* 9)
(defvar *iterator* 3)
(defun gift (N G)
(setq *iterator* (+ *iterator* 1))
;; (breadth-search *currentRock* G #'LMG)
)
(defun LMG (a)
(+ a (-(* *iterator* 2) 1))
)
从上面可以看出,一般的想法是简单地使用给定的合法移动生成器应用广度搜索功能,并且希望通过分析它的输出我们可以确定我们是否可以达到目标状态。如果上面的代码太混乱,我很乐意回答任何问题,再次感谢!
答案 0 :(得分:2)
其他潜在问题:
你正在使用LOOP错误。有关循环的信息,请参阅PCL。我稍微改了一下,但我不知道你在尝试什么。
建议SETF优于SETQ,因为SETF更通用。INCF将地方增加1。
你的缩进很糟糕;如果你修正了,你会注意到你从COND的末端掉进了LOOP。我建议在这里使用Lisp的自动缩进编辑器。 (Emacs是备用的)。
(defun gift (N G)
(setq CR 9)
(setq i 3)
(cond ((= N G) "N and G equal")
((< N G) "Gift it on a rock outside limits")
((> N 49) "number of rocks is bigger than 49 - it will work")
((< N 9) "number of rocks is less than 9, it wont work")
((= N 0) "number of rocks is 0, it wont work")
((= G 0) "gift isn't on a rock, it wont work")) )
(loop
while t
do
(setq I (+ I 1))
(setq I (-(* I 2) 1))
(setq CR 9)
(breadth-search CR G #'lmg-moves)
(when (= CR G)
(return "Let me Try!"))
(when (> CR N)
(return "Don't laugh at me!"))))
答案 1 :(得分:2)
有些事情显而易见:
N
和M
,但您的尝试会使用参数N
和G
。为什么要迷惑自己?可以称他们为N
和M
,或者(更好)使用有意义的名称,例如rock-number
和gift-place
。现在,让我们看看你的程序结构。
(defun gift (N G)
(setq CR 9)
(setq i 3))
这些setq
指令此时有未定义的行为,因为CR
和I
尚未定义。许多Lisp实现将隐式创建这些名称的全局特殊变量,但依赖它是不好的风格。我觉得你想在这里使用let
,就像这样:
(defun gift (rock-number gift-place)
(let ((current-rock 0)
(jump-number 0))
;; ...
))
请注意,您应该从头开始,因为当礼物在1号或4号岩石上时,您会错过解决方案。
接下来,cond
形式:它是死代码,因为它没有副作用,你立即丢弃它的返回值。因此,最好是评论,你应该对此进行评论。
最后,我们有了这个有趣的循环:
(loop
(setq I (+ I 1))
(setq I (-(* I 2) 1))
(setq CR 9)
(breadth-search CR G #'lmg-moves)
(when (= CR G) (return "Let me Try!"))
(when (> CR N) (return "Don't laugh at me!"))))
我不知道breadth-search
做了什么,但似乎你真的依赖于对全局特殊变量的操纵。我不能说这里会发生什么。但是,我可以看到几个问题:
I
进入序列1,3,7,15 ......,但跳跃序列顺序为1,2,3,4 ......而跳跃距离序列为1,3,5,7 ......即使是总是向右跳的岩石也是不同的顺序(1,4,9,16 ......)。CR
重置为9。我不明白这是怎么回事。从风格上讲,您应该使用例如let
,do
或扩展的loop
关键字:for
和:with
,将变量保持为本地变量,然后将它们传递给需要它们作为参数的函数。这使得更容易推断正在发生的事情。
我认为解决方案算法的心理模型有点混乱。我会以这样一种方式构造它,使你在跳跃之后循环并保留一组你可能在经过这么多次跳跃之后开启的岩石。小N
的特殊处理似乎并没有真正提高效率。如果您有N
&gt;的证明49总是有一个解决方案,另一方面,你应该有一个保护条款和一个概述证明的评论。