Skip to content

Instantly share code, notes, and snippets.

@divs1210
Last active July 16, 2021 20:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save divs1210/41d151ea64c7cbbd63aa84e4b42805bf to your computer and use it in GitHub Desktop.
Save divs1210/41d151ea64c7cbbd63aa84e4b42805bf to your computer and use it in GitHub Desktop.
Arithmetic solver

Code

(import (rnrs))

(define (derive f dx)
  (lambda (x)
    (/ (- (f (+ x dx))
          (f x))
       dx)))

(define (make-improver f dx)
  (let ((df (derive f dx)))
    (lambda (guess)
      (- guess
         (/ (f  guess)
            (df guess))))))

(define (make-good-enough f tolerance)
  (lambda (guess)
    (< (abs (f guess))
       tolerance)))

(define (iterative-improve x improve good?)
  (if (good? x)
      x
      (iterative-improve (improve x)
                         improve
                         good?)))

(define (solve f guess dx tolerance)
  (iterative-improve guess
                     (make-improver f dx)
                     (make-good-enough f tolerance)))

(define (solve-it f y dx tolerance)
  (solve (lambda (x)
           (- (f x) y))
         1.0
         dx
         tolerance))

(define (inverse f dx tolerance)
  (lambda (y)
    (solve-it f y dx tolerance)))

Helpers

(define (println . msgs)
  (for-each display msgs)
  (newline))

(define-syntax spy
  (syntax-rules ()
    ((_ expr)
     (let ((result expr))
       (println (quote expr) " => " result)
       result))))

Test

Test code

(define (test-it)
  (let* ((dx        0.00001)
         (tolerance 0.001))
    (let* ((double (lambda (x) (* 2 x)))
           (halve  (inverse double dx tolerance)))
      (spy (double 3))
      (spy (halve 10)))

    (println)

    (let* ((cube      (lambda (x) (* x x x)))
           (cube-root (inverse cube dx tolerance)))
      (spy (cube 3))
      (spy (cube-root 64)))

    (println)

    (let* ((quad   (lambda (x)
                     (+ (* x x)
                        (* 3 x)
                        5)))
           (unquad (inverse quad dx tolerance)))
      (spy (quad 7))
      (spy (unquad 75)))

    (println)))

Output

(double 3) => 6
(halve 10) => 4.999999999973795

(cube 3) => 27
(cube-root 64) => 4.000017469904781

(quad 7) => 75
(unquad 75) => 7.000000064702703
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment