Найти Харди–Рамануджана номер с помощью схемы R5RS


Я помню, как однажды увижу [Шриниваса Рамануджан], когда он был болен в Патни. Я ехал в такси номер такси 1729 и заметил, что количество показалось мне довольно скучным, и что я надеялся, что это не является неблагоприятным предзнаменованием. "Нет, - ответил он, - это очень интересное число; это наименьшее число можно выразить в виде суммы двух кубов двумя различными способами". [Г. Х. Харди как рассказали в "1729 (число)"]

В "математике гнева" Жозеф Тартаковский рассказывает об этом подвиге:

Ну и что? Дай мне две минуты и мой калькулятор смотреть, и я сделаю то же самое без оказания какого-либо серого вещества.

Я не знаю, как г-н Тартаковский выполнит то доказательство на калькуляторе смотреть, но ниже моей схеме функция, которая перебирает все номера, начинающиеся на 1 и останавливается, когда находит номер, который expressable двумя разными путями путем суммирования кубов двух положительных чисел. И это indeeds возвращает 1729.

Есть две области, в которых я бы признательны за предложения по улучшению. Одна из областей, новые схемы, стиль и идиомы. В другом районе составляет расчеты. Sisc не возвращает точные цифры для корней, даже когда они могли бы быть.

Например (только 27 1/3) дает 2.9999999999999996. Но я получаю точные результаты, когда кубатуры точное количество, (только 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))))))


578
7
задан 29 апреля 2011 в 11:04 Источник Поделиться
Комментарии
1 ответ

Ваш код выглядит нормально, я вижу несколько очень незначительные вещи, чтобы прокомментировать:


  • Там нет необходимости, чтобы определить куб и куб-корень на внутренней области,

  • Используя определение для внутренних функций делает его выглядеть немного яснее,

  • Это относится ко второй части вашего вопроса: Вы используете неточные->точно на число с плавающей точкой, которая может привести к большим рациональных (в том смысле, что вы выделить пару из двух больших целых чисел) - было бы лучше, чтобы избежать этого,

  • Делать это все равно не решит дополнительный тест, что вы делаете, - но это только потому, что вы не уверены, если у вас есть правильный номер, если вы пропустили 1. Учитывая, что она должна быть рядом в целое число, вы можете просто использовать раунд , а затем сделать один чек, сэкономив вам одно испытание.

Фиксация выше, и делать это в одну функцию, которая возвращает число, когда он найден, и с использованием некоторых более "очевидный" имена идентификаторов, я получаю это:

(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))))))

Я бегу это на ракетке, и, похоже, это примерно в 10 раз быстрее (50 мс против 5 мс).

6
ответ дан 30 апреля 2011 в 01:04 Источник Поделиться