Lisp递归方使用一个变量

时间:2017-02-20 14:17:10

标签: lisp common-lisp

这是试用代码

(defun f (a n)
    (if (zerop n)
        1
        (* a (f a (- n 1)))))

(f 3)应返回27,(f 4)应返回256

我尝试使用两个变量,但这违反了规则。

是否可以使用递归使用一个变量?

感谢您的任何想法

5 个答案:

答案 0 :(得分:1)

我不知道CL,但我知道Clojure和其他使用递归的语言。

如果递归函数有1个参数作为累加器,但仅在第一次调用时设置,则典型的方法是将f包装在另一个函数中。有两种(基本相同)的方法:

(defun g (a n)
    (if (zerop n)
        1
        (* a (g a (- n 1)))))

(defun f (n)
    ; I'm assuming you want the initial value of "a" to be 1
    (g 1 n))

或者,更简洁:

(defun f (n)
  (let (g (fn (n)
            (if (zerop n)
              1
              (* a (g a (- n 1))))))))
    ; Instead of f being recursive, f calls g, which is recursive
    (g 1 n))

请原谅任何语法错误。

答案 1 :(得分:1)

使用附加变量进行倒计时将是理智的选择,但您不需要为此仅更改一个数字参数输入的合约。你可以帮忙做到这一点:

(defun exptnn (n)
  "Get the (expt n n)"
  (check-type n integer)
  (labels ((helper (acc count)
             (if (zerop count)
                 acc
                 (helper (* acc n) (1- count)))))
    (if (< n 0) 
        (/ 1 (helper 1 (- n)))
        (helper 1 n))))

现在只用一个参数来解决没有任何帮助的问题是可能的,因为已经有一个解决方案,但我必须说这就像在Brainf*ck中编程而没有快乐!

答案 2 :(得分:1)

CL-USER 15 > (defun f (n)
              (labels ((g (m)
                         (if (zerop m)
                             1
                           (* n (g (1- m))))))
                (g n)))
F

CL-USER 16 > (f 0)
1

CL-USER 17 > (f 1)
1

CL-USER 18 > (f 2)
4

CL-USER 19 > (f 3)
27

CL-USER 20 > (f 4)
256

CL-USER 21 > (loop for i below 10 collect (f i))
(1 1 4 27 256 3125 46656 823543 16777216 387420489)

答案 3 :(得分:1)

这是一个解决方案,其中不使用具有多个参数的函数(=+*logandash除外;另请注意,logandash始终将常量作为第二个参数,因此它们也可以作为一元函数实现。)

这个想法是&#34;隐藏&#34;使用奇数/偶数位的单个整数中明显的递归方法所需的两个参数。

(defun pair (n)
  (if (= n 0)
      0
      (+ (* 3 (logand n 1))
         (ash (pair (ash n -1)) 2))))

(defun pair-first (p)
  (if (= p 0)
      0
      (+ (logand p 1)
         (ash (pair-first (ash p -2)) 1))))

(defun pair-second (p)
  (pair-first (ash p -1)))

(defun subsec (p)
  (if (= 2 (logand p 2))
      (- p 2)
      (+ (logand p 1) 2 (ash (subsec (ash p -2)) 2))))

(defun pairpow (p)
  (if (= (pair-second p) 1)
      (pair-first p)
      (* (pair-first p)
         (pairpow (subsec p)))))

(defun f (n)
  (pairpow (pair n)))

当然没有合理的实际用途;但确实是一个有趣的运动。

答案 4 :(得分:0)

是的,这是可能的:

(defun f (n)
  (cond
    ((numberp n)
      (f (cons n n)))
    ((zerop (car n))
      1)
    (t
      (* (cdr n)
         (f (cons (1- (car n))
                  (cdr n)))))))

技巧是你可以将任何数据结构(包括一对数字)存储在一个变量中。

或者,您可以使用标准库中的帮助程序:

(defun f (n)
  (apply #'*
         (loop repeat n collect n)))

但是这不使用递归。或者干脆:

(defun f (n)
  (expt n n))