;;;; ramanujan.scm -- Compute the N:th Ramanujan number ;;;; ;;;; Copyright (C) 2018 Mikael Djurfeldt ;;;; ;;;; This program is free software; you can redistribute it and/or modify ;;;; it under the terms of the GNU General Public License as published by ;;;; the Free Software Foundation; either version 3, or (at your option) ;;;; any later version. ;;;; ;;;; This program is distributed in the hope that it will be useful, ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;;; GNU General Public License for more details. ;;;; ;;;; You should have received a copy of the GNU General Public License ;;;; along with this program. If not, see . ;;;; (define (ramanujan n) "Return the N:th Ramanujan number (sum of two cubes in more than one way)" (define (ramanujan? w b0) ;; Is w a Ramanujan number? (let loop ((a 1) (b b0) (count 0)) (or (> count 1) (and (<= a b) (let ((s (+ (* a a a) (* b b b)))) (cond ((< s w) (loop (+ 1 a) b count)) ; too small => inc a ((> s w) (loop a (- b 1) count)) ; too large => dec b (else (loop a (- b 1) (+ 1 count))))))))) ; found a sum! (define (iter w b0 n) ;; w is a Ramanujan candidate ;; b0 is the first second term to try ;; n is the number of Ramanujan number still to find ;; We first increase b0 until 1 + b0^3 > w (let ((b0 (let loop ((b b0)) (if (>= (+ 1 (* b b b)) w) b (loop (+ 1 b)))))) (cond ((zero? n) (- w 1)) ; found the last number! ((ramanujan? w b0) (iter (+ 1 w) b0 (- n 1))) (else (iter (+ 1 w) b0 n))))) ; try next candidate (iter 2 1 n))