Scheme - 加速重度递归函数

时间:2016-03-07 22:38:46

标签: performance recursion optimization scheme racket

我必须编写一个Scheme谓词来计算定义为的函数f(N - > N):

  • 如果n< 4:f(n)=(n ^ 2)+ 5
  • 如果n≥4:f(n)= [f(n-1)+ f(n-2)] * f(n-4)

我编写了一个有效的简单谓词:

(define functionfNaive
  (lambda (n)
    (if (< n 4) (+ (* n n) 5)
        (* (+ (functionfNaive (- n 1)) (functionfNaive (- n 2))) 
           (functionfNaive (- n 4))))))

现在,我尝试使用累加器的方法,但它不起作用...... 我的代码:

(define functionf
  (lambda(n)
    (functionfAux n 5 9 14)))

(define functionfAux
 (lambda (n n1 n2 n4)
   (cond
     [(< n 4) (+ (* n n) 5)]
     [(= n 4) (* n1 (+ n2 n4))]
      [else (functionfAux (- n 1) n2 n4 (* n1 (+ n2 n4)))])))

3 个答案:

答案 0 :(得分:4)

根据要求,这是一个代码的备忘版本,其性能优于天真版本:

(define functionf
  (let ((cache (make-hash)))
    (lambda (n)
      (hash-ref!
       cache
       n
       (thunk
        (if (< n 4)
            (+ (* n n) 5)
            (* (+ (functionf (- n 1)) (functionf (- n 2))) (functionf (- n 4)))))))))

BTW ...计算大n值的结果非常快,但打印需要花费很多时间。要测量时间,请使用

之类的内容
(time (functionf 50) 'done)

这是一个通用的memoize程序,如果你需要它:

(define (memoize fn)
  (let ((cache (make-hash)))
    (λ arg (hash-ref! cache arg (thunk (apply fn arg))))))

在您的情况下可以像

一样使用
(define functionf
  (memoize
   (lambda (n)
     (if (< n 4) 
         (+ (* n n) 5)
         (* (+ (functionf (- n 1)) (functionf (- n 2))) (functionf (- n 4)))))))

答案 1 :(得分:1)

首先,那不是谓词。 Predicate是一个返回布尔值的函数。

要计算 n 结果,请从前四个开始计算,并保持最后四个已知元素。到达 n 时停止:

(define (step a b c d n)
  (list b c d (* (+ c d) a)) (+ n 1)))

等。简单。第一个电话会是(step 5 6 9 14 3)

答案 2 :(得分:1)

递归树的深度可能是最大的问题,因此可能使用迭代,这意味着使用一些变量来记忆中间过程。

#lang racket
(define (functionf n)
        (define (iter now n1 n2 n3 n4 back)
          (if (= n now)
              back
              (iter (+ now 1) back n1 n2 n3 (* n3 (+ back n1)))))
        (if (< n 4)
            (+ 5 (* n n))
            (iter 4 14 9 6 5 125)))

(functionf 5)

这样,堆栈的深度只有1,代码加速了。