方案中的Collat​​z功能

时间:2013-10-10 01:21:56

标签: scheme collatz

所以我试图在方案中迭代地解决collat​​z函数,但我的测试用例一直显示为

(define (collatz n)   
    (define (collatz-iter n counter)
            (if (<=  n 1)
                1
            (if (even? n)  (collatz-iter (/ n 2) (+ counter 1))
                           (collatz-iter (+ (* n 3) 1) (+ counter 1)) 
            )
            )
    )
)

但是,我的测试用例会导致“#[常数13#x2]”。我写错了什么,如果有的话?

3 个答案:

答案 0 :(得分:4)

您忘了拨打collatz-iter。此外,你不清楚你打算用counter做什么,你只是增加它,但从不实际使用它的值 - 你的程序总是返回1(假设Collat​​z猜想是真的,这似乎很有可能。)

我猜你打算退回计数器,所以这里是如何解决你的程序:

(define (collatz n)
  (define (collatz-iter n counter)
    (if (<= n 1)
        counter ; return the counter
        (if (even? n)
            (collatz-iter (/ n 2) (+ counter 1))
            (collatz-iter (+ (* n 3) 1) (+ counter 1)))))
  (collatz-iter n 1)) ; call collatz-iter

这就是wikipedia中的例子:

(collatz 6)
=> 9

(collatz 11)
=> 15

(collatz 27)
=> 112

所以基本上我们计算给定数字的Collat​​z序列的长度。

答案 1 :(得分:2)

当我尝试在Racket中运行您的代码时,我收到错误:

  

在内部定义序列之后没有表达

这告诉我们collatz函数包含collatz-iter定义,但没有表达式来调用它(除了collatz-iter中的递归调用之外)。可以通过添加对(collatz-iter n 0)的调用作为collatz中的最后一行来解决此问题。

然而,当你运行程序时,它总是返回1.不是很有趣。如果您将其更改为返回counter的值,则可以看到序列达到1所需的步数。

(define (collatz n)   
    (define (collatz-iter n counter)
            (if (<=  n 1)
                counter
            (if (even? n)  (collatz-iter (/ n 2) (+ counter 1))
                           (collatz-iter (+ (* n 3) 1) (+ counter 1)) 
            )
            )
    )
  (collatz-iter n 0)
)

我们可以根据Wikipedia Collatz conjecture文章中提供的一些示例进行检查。

> (collatz 6)
8
> (collatz 11)
14
> (collatz 27)
111
> 

答案 2 :(得分:2)

您应该正确缩进代码。正确的格式化,它是

(define (collatz n)   
  (define (collatz-iter n counter)
    (if (<=  n 1)
        1
        (if (even? n)
            (collatz-iter (/ n 2) (+ counter 1))
            (collatz-iter (+ (* n 3) 1) (+ counter 1))))))

显然没有要执行的正文形式,只是一个内部定义。您需要添加对collatz-iter的调用,如下所示:

(define (collatz n)   
  (define (collatz-iter n counter)
    (if (<=  n 1)
        1
        (if (even? n)
            (collatz-iter (/ n 2) (+ counter 1))
            (collatz-iter (+ (* n 3) 1) (+ counter 1)))))
  (collatz-iter n 1))

(我不确定你的初始counter值应该是什么。我假设1是合理的,但也许它应该是零?)更好的是,因为它只是一个身体致电collatz-iter,您可以将其命名为let,这更像是您的原始代码:

(define (collatz n)
  (let iter ((n n) (counter 1))
    (if (<=  n 1)
        1
        (if (even? n)
            (iter (/ n 2) (+ counter 1))
            (iter (+ (* n 3) 1) (+ counter 1))))))

这有点像将内部定义与对本地函数的单个调用相结合。但是,一旦你完成了这个,你会看到它总是返回1,当它最终到达基本情况时(假设Collat​​z猜想是真的,当然)。解决这个问题,你最终会得到:

(define (collatz n)
  (let iter ((n n) (counter 1))
    (if (<=  n 1)
        counter
        (if (even? n)
            (iter (/ n 2) (+ counter 1))
            (iter (+ (* n 3) 1) (+ counter 1))))))