-3

我需要在一个 clisp 中创建一个函数,它将集合中的所有奇数相加。例如子集 (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

4 回答 4

2

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

(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
于 2013-05-07T12:00:26.787 回答
1

I was going to do my usual shtick and put on the code-review hat, but having properly formatted your second attempt, there are too many problems here to take an incremental approach. You need to sit down and explain what you intended this code to do.

Specifically, what's going on with x? Is that meant to be a global binding that you're re-setting each time, or did you mean to define a local binding and accidentally forgot that both the ifs need the variable before you get around to it? What are you trying to do with those setqs, and what are you trying to do with those loops (as written, neither do anything)?


[temporarily dons code-review hat]

First up, kindly format your code properly. It's a small thing, but it increases readability by quite a bit.

(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)))))

And with the proper indentation level, quite a few errors just fall out at you right away.

  • First off, that top if has three clauses in it (the if and two setqs for some reason).
  • Second, that second if has no clauses, just a test. Which means it does nothing
  • Third, you're calling some very oddly named functions in the if body. I'm willing to guarantee that ((setq (x a)) (+ x 2) (loop for x from a to b do (+ x 2))) isn't what you mean, because that's calling the function (setq (x a)) on the arguments (+ x 2) and (loop ...).
  • Fourth, you invoke setq in two different incorrect ways. (setq (x (+ a 1)) this is attempting to set the result of calling the function x on (+ a 1) to NIL. (setq (x a)) (+ x 2) this is trying to set the result of calling the function x on a to NIL, then evaluating and discarding (+ x 2).
于 2013-05-07T13:19:12.150 回答
0

我看到的最简单的方法是使用应用程序编程。

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

您可以使用 range 函数生成您的区间,如下所示:

    (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))))
于 2013-05-07T08:33:26.780 回答
0

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

(defun add (a b)
  (cond ((evenp a) (add (+ a 1) b))
        ((> a b)   0)
        (t         (+ a (add (+ a 2) b)))))
于 2013-05-07T14:15:57.993 回答