Lisp函数从子集中添加奇数

时间:2013-05-07 07:41:36

标签: numbers lisp add subset

我需要在clisp中创建一个函数来添加一个set中的所有奇数。例如子集(2,8),结果将是15(3 + 5 + 7)。任何建议? 我确实有这样的东西,其中a是集合的开头,b是它的结尾。

(defun add (a b)
(if(and(< a x) (> b x))
    (if(even(x))
        ((setq ( x (+a 1))) (+ x 2))
        ((setq(x a)) (+ x 2))
            )))

编辑:

(defun add (a b)
(if(and(< a x) (> b x))
    (if(evenp x))
        ((setq ( x (+a 1))
            (loop for x from a to b do (+ x 2))))
        ((setq(x a)) (+ x 2)
            (loop for x from a to b do (+ x 2)))
                ))

4 个答案:

答案 0 :(得分:2)

最直接的方法是使用LOOPLOOP解决方案非常简单:

(defun sum-odds (start end)
  (loop for i from start to end 
        when (oddp i) sum i))

(sum-odds 2 8)
=> 15

对于迭代,您也可以使用DO,但是您必须更明确地了解一切是如何工作的(并且您还有更多选项):

(defun sum-odds2 (begin end)
  (do ((sum 0)
       (i begin (1+ i)))
      ((= i end) sum)
    (when (oddp i)
      (incf sum i))))

(sum-odds2 2 8)
=> 15

如果你确实使用了一个创建包含整数范围的列表的解决方案(它创建了一堆垃圾收集的中间列表),正如其他一些答案中所建议的那样,你应该考虑遍历该列表的次数(没有理由不止一次遍历它)。您可以使用REDUCE将列表元素与:key参数相加,使奇数看起来像自己,偶数看起来像0

(defun sum-odds3 (list)
  (reduce '+ list
          :key (lambda (n)
                 (if (oddp n)
                   n
                   0))))

(sum-odds3 '(2 3 4 5 6 7 8))
=> 15

答案 1 :(得分:1)

我打算按照惯常的做法进行代码审查,但是如果你的第二次尝试格式正确,那么这里有太多的问题需要采取增量方法。您需要坐下来解释您希望此代码执行的操作。

具体来说,x发生了什么?这是否意味着您每次都要重新设置一个全局绑定,或者您是否意味着定义一个本地绑定并意外忘记if s需要变量才能到达它之前?你想对那些setq做什么,你想用那些loops做什么(如同书面做的那样,什么都不做)?


[暂时没有代码审查帽子]

首先,好心format your code properly。这是一件小事,但它可以提高可读性。

(defun add (a b)
  (if (and (< a x) (> b x))
     (if (evenp x))
     ((setq (x (+ a 1))
            (loop for x from a to b do (+ x 2))))
     ((setq (x a)) (+ x 2)
      (loop for x from a to b do (+ x 2)))))

如果有适当的缩进级别,很多错误就会立即消失。

  • 首先,顶部if中有三个子句(if和两个setq由于某种原因)。
  • 其次,第二个if没有条款,只是一个测试。这意味着什么都不做
  • 第三,你在if身体中调用了一些非常奇怪的命名函数。我愿意保证((setq (x a)) (+ x 2) (loop for x from a to b do (+ x 2)))不是你的意思,因为它在参数(setq (x a))(+ x 2)上调用函数(loop ...)
  • 第四,您以两种不同的方式调用setq(setq (x (+ a 1))这是尝试将x上的函数(+ a 1)设置为NIL的结果。 (setq (x a)) (+ x 2)这是尝试将x上的函数a设置为NIL,然后评估并放弃(+ x 2)

答案 2 :(得分:0)

我认为最简单的方法是使用应用程序编程。

    (defun range (max &key (min 0) (step 1))
      (loop for n from min below max by step
        collect n))

您可以使用范围功能生成您的间隔,如下所示:

    (range 8 :min 2) => (2 3 4 5 6 7)

然后使用remove-if-not:

进行过滤
    (remove-if-not #'oddp (range 8 :min 2)) => (3 5 7)

并对结果应用添加:

    (apply #'+ (remove-if-not #'oddp (range 8 :min 2))) => 15

您也可以在函数中包含上述内容:

    (defun add (a b)
      (apply #'+ (remove-if-not #'oddp (range b :min a))))

答案 3 :(得分:0)

在修复语法问题之前,您还没有遇到算法问题。你显然已经猜到了一个解决方案,甚至还没有编译你的猜测。您的代码将无法编译,也无法运行。你正在研究类似Lisp的语言,因为它们允许进行微不足道的探索。所以探索。

(defun add (a b)
  (cond ((evenp a) (add (+ a 1) b))
        ((> a b)   0)
        (t         (+ a (add (+ a 2) b)))))