你知道怎么写这个Scheme函数吗?

时间:2008-11-02 00:58:30

标签: scheme collatz

你能编写一个带一个参数(正整数)和

的函数
  • 如果它是偶数,则将它除以2,或
  • 将它乘以3,如果奇数
  • 则加1

然后返回结果数字。

然后是一个单独的函数,它接受一个参数(一个正整数)并重复将它传递给前一个函数,直到它达到1(此时它停止)。该函数将返回将其减少为1所需的步骤数。

然后另一个函数接受两个参数a和b(两个正整数都带有< = b)并返回最大数量的重复Collat​​z步骤,将范围内的任何单个数字减少到1(包括端点) )。 (Collat​​z步骤指的是上一个功能)。

最后,另一个函数接受两个参数a和b(两个正整数都带有< = b)并返回a和b之间的数字(包括端点),以减少最大数量的Collat​​z步骤到1。

这些功能与Collat​​z问题有关,我发现它非常有趣。 后续函数显然会借用之前定义的其他函数。

知道如何在Scheme代码中显示它吗?

3 个答案:

答案 0 :(得分:3)

我相信这是一个未解决的数论问题。有一种假设认为,每次执行此操作的次数都会减少到一次。

然而,我并不认为计划是正确的工具,而且因为很多人已经决定这是家庭作业,而不是一个合法的问题,我会在c中提供我的解决方案

inline unsigned int step(unsigned int i)
{
    return (i&0x1)*(i*3+1)+((i+1)&0x1)*(i>>1);
}

这将在数字上做一步(没有分支!!!)。下面是你如何进行整个计算:

unsigned int collatz(unsigned int i)
{
    unsigned int cur = i;
    unsigned steps = 0;
    while((cur=step(cur))!=1) steps++;
    return steps;
}

我认为不可能完全删除分支。这是数论问题,因此它适用于极端(并且可能是不必要的)优化。享受

答案 1 :(得分:1)

对于其他两个函数,使用foldl:

(define (listfrom a b)
  (if (= a b)
      (cons a empty)
      (cons a (listfrom (+ 1 a) b))))

(define (max-collatz a b)
  (foldl max 0 (map collatz-loop (listfrom a b))))

(define (max-collatz-num a b)
  (foldl (lambda (c r)
           (if (> (collatz-loop c) (collatz-loop r)) c r))
         a
         (listfrom a b)))    

答案 2 :(得分:0)

执行一次迭代的函数:

(define (collatz x)
  (if (even? x)
      (/ x 2)
      (+ (* x 3) 1)))

此函数接受一个输入并循环,直到达到1.该函数返回到达该状态所需的迭代次数(尝试绘制这个 - 看起来很酷):

(define (collatz-loop x)
  (if (= x 1) 1
      (+ (collatz-loop (collatz x)) 1)))

根据要求,这是collat​​z-loop的尾递归版本:

(define (collatz-loop x)
  (define (internal x counter)
    (if (= x 1) counter
    (internal (collatz x) (+ counter 1))))
  (internal x 1))

此函数采用一个范围并返回到达结尾所需步骤数最多的数字以及步数:

(define (collatz-range a b)
  (if (= a b)
      (cons a (collatz-loop a))
      (let ((this (collatz-loop a))
        (rest (collatz-range (+ a 1) b)))
        (if (< this (cdr rest)) rest
            (cons a this)))))

(collatz-range 1 20) ; returns (18 . 21), which means that (collatz-loop 18) returns 21

这是collat​​z-range,tail recursive:

(define (collatz-range a b)
  (define (internal a best)
    (if (< b a) best
        (internal (+ a 1)
        (let ((x (collatz-loop a)))
          (if (< x (cdr best))
              best
              (cons a x))))))
  (internal a (cons -1 -1)))