使用R5RS方案查找Hardy-Ramanujan数字.请提出成语和计算方面的改进建议.

Sha*_*nce 6 scheme

我记得曾经看过[Srinivasa Ramanujan],当他在Putney生病时.我曾乘坐1729号出租车,并说这个数字对我来说相当沉闷,我希望这不是一个不利的预兆."不,"他回答说,"这是一个非常有趣的数字;它是以两种不同方式表达的两个立方体之和的最小数字." [GH Hardy在"1729(号码)"中说道]

"数学愤怒"中,约瑟夫·塔尔塔科夫斯基谈到了这一壮举,"那又怎么样?给我两分钟和我的计算器表,我会做同样的事情而不会施加任何小灰色细胞." 我不知道Tartakovsky先生将如何在计算器手表上完成该证明,但以下是我的方案函数,它枚举从1开始的数字,当它找到一个可以通过求和的多维数据集的两个单独方式表达的数字时停止两个正数.并且它的契约返回1729年.

有两个方面我会赞赏改进建议.一个领域是,对计划,风格和习语不熟悉.另一个区域是围绕计算.Sisc不会返回根的确切数字,即使它们可以.例如,(expt 27 1/3)产量为2.9999999999999996.但是当确定一个确切的数字,(expt 3 3)收益率时,我确实得到了确切的结果27.我的解决方案是获得立方根的确切底面,然后测试地板的立方体和地板的立方加一,如果匹配则计算为匹配.这个解决方案看起来很混乱,难以推理.有更简单的方法吗?

; Find the Hardy-Ramanujan number, which is the smallest positive
; integer that is the sum of the cubes of two positivie integers in
; two seperate ways.
(define (hardy-ramanujan-number)
  (let ((how-many-sum-of-2-positive-cubes
          ; while i^3 + 1 < n/1
          ;     tmp := exact_floor(cube-root(n - i^3))
          ;     if n = i^3 + tmp^3 or n = i^3 + (tmp + 1) ^3 then count := count + 1
          ; return count
          (lambda (n)
            (let ((cube (lambda (n) (expt n 3)))
                  (cube-root (lambda (n) (inexact->exact (expt n 1/3)))))
              (let iter ((i 1) (count 0)) 
                (if (> (+ (expt i 3) 1) (/ n 2))
                    count
                    (let* ((cube-i (cube i))
                           (tmp (floor (cube-root (- n cube-i)))))
                      (iter (+ i 1)
                        (+ count
                          (if (or (= n (+ cube-i (cube tmp)))
                                  (= n (+ cube-i (cube (+ tmp 1)))))
                              1
                              0))))))))))
    (let iter ((n 1))
      (if (= (how-many-sum-of-2-positive-cubes n) 2)
          n
          (iter (+ 1 n))))))
Run Code Online (Sandbox Code Playgroud)

Eli*_*lay 6

你的代码看起来很好,我看到一些非常小的事情要评论:

  • 没有必要定义cubecube-root在最内层范围内,

  • 使用define了内部功能使得它看起来更清晰一点,

  • 这与你问题的第二部分有关:你使用inexact->exact浮点数可以导致大的有理数(在你分配一对两个大整数的意义上) - 最好避免这种情况,

  • 这样做仍然无法解决你所做的额外测试 - 但这只是因为你不确定你是否有正确的数字,如果你错过了1.鉴于它应该接近整数,你可以只是使用round然后进行一次检查,为您节省一次测试.

修复上面的内容,并在一个函数中执行它,当它找到时返回数字,并使用一些更"明显"的标识符名称,我得到这个:

(define (hardy-ramanujan-number n)
  (define (cube n) (expt n 3))
  (define (cube-root n) (inexact->exact (round (expt n 1/3))))
  (let iter ([i 1] [count 0])
    (if (> (+ (cube i) 1) (/ n 2))
      (hardy-ramanujan-number (+ n 1))
      (let* ([i^3   (cube i)]
             [j^3   (cube (cube-root (- n i^3)))]
             [count (if (= n (+ i^3 j^3)) (+ count 1) count)])
        (if (= count 2) n (iter (+ i 1) count))))))
Run Code Online (Sandbox Code Playgroud)

我在Racket上运行它,它看起来快了大约10倍(50ms vs 5ms).