UVa 10120礼品?!在Common Lisp?

时间:2012-02-01 21:54:01

标签: lisp common-lisp

我正在学习常见的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))
   )

从上面可以看出,一般的想法是简单地使用给定的合法移动生成器应用广度搜索功能,并且希望通过分析它的输出我们可以确定我们是否可以达到目标状态。如果上面的代码太混乱,我很乐意回答任何问题,再次感谢!

2 个答案:

答案 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)

有些事情显而易见:

  • 您有两个合法的回报值,“让我试试!”,“不要取笑我!”。你拼错了第一个,改写了第二个,并添加了许多没有用于问题的字符串(它们是否意味着评论?)。
  • 说明会调用变量NM,但您的尝试会使用参数NG。为什么要迷惑自己?可以称他们为NM,或者(更好)使用有意义的名称,例如rock-numbergift-place

现在,让我们看看你的程序结构。

(defun gift (N G)
  (setq CR 9)
  (setq i 3))

这些setq指令此时有未定义的行为,因为CRI尚未定义。许多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。我不明白这是怎么回事。

从风格上讲,您应该使用例如letdo或扩展的loop关键字:for:with,将变量保持为本地变量,然后将它们传递给需要它们作为参数的函数。这使得更容易推断正在发生的事情。

我认为解决方案算法的心理模型有点混乱。我会以这样一种方式构造它,使你在跳跃之后循环并保留一组你可能在经过这么多次跳跃之后开启的岩石。小N的特殊处理似乎并没有真正提高效率。如果您有N&gt;的证明49总是有一个解决方案,另一方面,你应该有一个保护条款和一个概述证明的评论。