算斐波纳契"成本"在计划中

时间:2014-10-22 23:53:28

标签: scheme

我必须创建一个能够找到" cost"斐波那契数。我的Fibonacci代码是

(define fib (lambda (n) (cond
                      ((< n 0) 'Error)
                      ((= n 0) 0)
                      ((= n 1) 1)
                      (else (+ (fib (- n 1)) (fib (- n 2)))))))

用于评估fib数的每个+或 - 值为1美元。每个&lt;或者&gt;价值0.01美元。例如,1值0.01美元,2值3.03美元等。我不知道如何计算+, - ,&lt;和&gt;的数量。我的fibCost代码中是否需要fib代码?

4 个答案:

答案 0 :(得分:1)

快速而肮脏的解决方案是在每次启动成本过程时定义counter变量,并使用递归的每个分支处的相应值更新它。例如:

(define (fib-cost n)
  (let ((counter 0)) ; counter initialized with 0 at the beginning
    (let fib ((n n)) ; inner fibonacci procedure
      ; update counter with the corresponding cost
      (set! counter (+ counter 0.01))
      (when (> n 1)
        (set! counter (+ counter 3)))
      (cond ((< n 0) 'Error)
            ((= n 0) 0)
            ((= n 1) 1)
            (else (+ (fib (- n 1)) (fib (- n 2))))))
    counter)) ; return the counter at the end

回答你的第二个问题 - 不,我们不需要整个fib代码;鉴于我们对斐波纳契的实际价值不感兴趣,可以进一步简化上述内容,只需进行必要的调用并忽略返回的值:

(define (fib-cost n)
  (let ((counter 0)) ; counter initialized with 0 at the beginning
    (let fib ((n n)) ; inner fibonacci procedure
      ; update counter with the corresponding cost
      (set! counter (+ counter 0.01))
      (when (> n 1)
        (fib (- n 1))
        (fib (- n 2))
        (set! counter (+ counter 3))))
    counter)) ; return the counter at the end

答案 1 :(得分:1)

我不确定您是否想要解决方案是否包含原始代码。有直接的计算成本的方法,但我认为看看类似于检测现有代码的方法很有意思。也就是说,我们可以更改以便与原始代码非常相似的东西能够计算出我们想要的东西吗?

首先,我们可以用一些间接替换算术运算符。也就是说,您可以调用(+ x y),而不是调用(op + 100 x y),这会增加total-cost变量。

(define (fib n)
  (let* ((total-cost 0)
         (op (lambda (fn cost . args)
               (set! total-cost (+ total-cost cost))
               (apply fn args))))
    (let fib ((n n))
      (cond 
        ((op < 1 n 0) 'error)
        ((= n 0) 1)
        ((= n 1) 1)
        (else (op + 100
                  (fib (op - 100 n 1))
                  (fib (op - 100 n 2))))))
    total-cost))

但这并不能让我们保留原始代码。我们可以通过定义算术运算符的本地版本,然后使用原始代码来做得更好:

(define (fib n)
  (let* ((total-cost 0)
         (op (lambda (fn cost)
               (lambda args
                 (set! total-cost (+ total-cost cost))
                 (apply fn args))))
         (< (op < 1))
         (+ (op + 100))
         (- (op - 100)))
    (let fib ((n n))
      (cond 
        ((< n 0) 'error)
        ((= n 0) 1)
        ((= n 1) 1)
        (else (+ (fib (- n 1))
                 (fib (- n 2))))))
    total-cost))

> (fib 1)
1
> (fib 2)
303
> (fib 3)
605
> (fib 4)
1209

这种方法的好处在于,如果你开始使用宏来做一些源代码操作,你实际上可以将它用作一种穷人的分析器或跟踪系统。 (当然,我建议坚持使用实现提供的更强大的工具,但有时候这样的技术会很有用。)

此外,这甚至不会 来计算Fibonnaci数。它仍然是因为我们(apply fn args)计算的,但是如果我们删除它,那么我们甚至都不会调用原始的算术运算。

答案 2 :(得分:0)

只要您在 else 部分中递归调用代码,就可以+/-。因此,只要您输入else部分,就可以轻松计算其中的3个。一个用于 f(n-1),一个用于 f(n-2),一个用于 f(n-1)+ f(n-2)

答案 3 :(得分:0)

只是为了好玩,使用语法扩展(又名“宏”)的解决方案。

让我们定义以下内容:

(define-syntax-rule (define-cost newf oldf thiscost totalcost)
  (define (newf . parms)
    (set! totalcost (+ totalcost thiscost))
    (apply oldf parms)))

现在我们根据您想要付出代价的原始程序创建程序:

(define-cost +$ + 100 cost)
(define-cost -$ - 100 cost)
(define-cost <$ <   1 cost)

所以使用+$会添加一个并将成本计数器增加1,依此类推。

现在我们调整初始程序以使用新定义的程序:

(define fib
  (lambda (n)
    (cond
      ((<$ n 0) 'Error)
      ((= n 0) 0)
      ((= n 1) 1)
      (else 
       (+$ (fib (-$ n 1)) (fib (-$ n 2)))))))

为方便起见,我们创建一个宏来返回过程的结果及其成本:

(define-syntax-rule (howmuch f . args)
  (begin
    (set! cost 0)
    (cons (apply f 'args) cost)))

然后是成本变量

(define cost #f)

然后我们去了

> (howmuch fib 1)
'(1 . 1)
> (howmuch fib 2)
'(1 . 303)
> (howmuch fib 10)
'(55 . 26577)
> (howmuch fib 1)
'(1 . 1)