Find the Hardy–Ramanujan number using R5RS scheme. Please suggest improvements in idiom and calculations. -
i remember once going see [srinivasa ramanujan] when ill @ putney. had ridden in taxi cab number 1729 , remarked number seemed me rather dull one, , hoped not unfavorable omen. "no," replied, "it interesting number; smallest number expressible sum of 2 cubes in 2 different ways." [g. h. hardy told in "1729 (number)"]
in "math wrath" joseph tartakovsky says feat, "so what? give me 2 minutes , calculator watch, , i'll same without exerting little gray cells." don't know how mr. tartakovsky accomplish proof on calculator watch, following scheme function enumerates numbers starting @ 1 , stops when finds number expressable in 2 seperate ways summing cubes of 2 positive numbers. , indeeds returns 1729.
there 2 areas appreciate suggestions improvement. 1 area is, being new scheme, style , idiom. other area around calculations. sisc not return exact numbers roots, when be. example (expt 27 1/3)
yields 2.9999999999999996. exact retults when cubing exact number, (expt 3 3)
yields 27
. solution exact floor of cube root , test against cube of floor , cube of floor plus one, counting match if either match. solution seems messy , hard reason about. there more straightforward way?
; find hardy-ramanujan number, smallest positive ; integer sum of cubes of 2 positivie integers in ; 2 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 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 3) 1) (/ n 2)) count (let* ((cube-i (cube i)) (tmp (floor (cube-root (- n cube-i))))) (iter (+ 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))))))
your code looks fine, see few minor things comment on:
there's no need define
cube
,cube-root
@ innermost scope,using
define
internal functions makes little clearer,this related second part of question: you're using
inexact->exact
on floating point number can lead large rationals (in sense allocate pair of 2 big integers) -- better avoid this,doing still doesn't solve test -- that's because you're not if have right number of if missed 1. given should close integer, can use
round
, 1 check, saving 1 test.
fixing above, , doing in 1 function returns number when it's found, , using more "obvious" identifier names, this:
(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 (+ 1) count))))))
i'm running on racket, , looks it's 10 times faster (50ms vs 5ms).
Comments
Post a Comment