# sicp-ex-3.82

meteorgan

```

(define (random-in-range low high)
(let ((range (- high low)))
(+ low (* (random) range))))
(define (random-number-pairs low1 high1 low2 high2)
(cons-stream (cons (random-in-range low1 high1) (random-in-range low2 high2))
(random-number-pairs low1 high1 low2 high2)))

(define (monte-carlo experiment-stream passed failed)
(define (next passed failed)
(cons-stream (/ passed (+ passed failed))
(monte-carlo (stream-cdr experiment-stream)
passed
failed)))
(if (stream-car experiment-stream)
(next (+ passed 1) failed)
(next passed (+ failed 1))))

(define (estimate-integral p x1 x2 y1 y2)
(let ((area (* (- x2 x1) (- y2 y1)))
(randoms (random-number-pairs x1 x2 y1 y2)))
(scale-stream (monte-carlo (stream-map p randoms) 0 0) area)))

;; test. get the value of pi
(define (sum-of-square x y) (+ (* x x) (* y y)))
(define f
(lambda (x)
(not (> (sum-of-square (- (car x) 1) (- (cdr x) 1))
1))))
(define pi-stream (estimate-integral f 0 2 0 2))

```

tango

Meteorgan's solution uses the monte-carlo method with variables passed and failed. Following solution doesn't uses these and relies solely on streams.

``` (define (add-streams s1 s2) (stream-map + s1 s2))
(define ones (cons-stream 1.0 ones))
(define integers (cons-stream 1.0 (add-streams ones integers)))

(define (random-stream lo hi)
(define (random-in-range low high)
(let ((range (- high low)))
(+ low (random range))))
(cons-stream (random-in-range lo hi)
(random-stream lo hi)))

(define (estimate-integral p x1 x2 y1 y2)
(define throw-results
(stream-map (lambda (x) (if (eq? x true) 1.0 0))
(stream-map p
(random-stream x1 x2)
(random-stream y1 y2))))
(define successful-throws
(cons-stream (stream-car throw-results)
successful-throws)))
(define (get-area probability)
(* probability (abs (* (- y2 y1) (- x2 x1)))))
(stream-map get-area
(stream-map / successful-throws integers)))
```

master

Isn't producing random numbers the predicate's job? Doesn't the following simple definition of estimate-integral suffice?

``` (define (estimate-integral P x1 x2 y1 y2)
(let ((width (- x2 x1))
(height (- y2 y1)))
(let ((area (* width height)))
(scale-stream (monte-carlo P 0 0) area))))
```

x3v

Uses the random-in-range procedure previously defined in the book.

```

(define (random-in-range low high)
(let ((range (- high low)))
(+ low (random range))))

(define (rand-range-stream low high)
(cons-stream
(random-in-range low high)
(rand-range-stream low high)))

(define (experiment-stream x1 x2 y1 y2 radius)
(stream-map
(stream-map square (rand-range-stream x1 x2))
(stream-map square (rand-range-stream y1 y2)))))

(define pi-est-stream
(scale-stream (monte-carlo (experiment-stream -1.0 1.0 -1.0 1.0 1.0) 0 0) 4.0))

(exact->inexact (stream-ref pi-est-stream 50000)) ;; ~3.1429
```

krubar

Similar solution to meteorgan's. Requires random-in-range from Excercise 3.5 and monte-carlo from the beginning of section 3.5.5.

``` (define (randoms-ranged low high)
(cons-stream (random-in-range low high)
(randoms-ranged low high)))

(define (integral-estimates P x1 x2 y1 y2)
(define point-in-integral-stream
(stream-map P (randoms-ranged x1 x2) (randoms-ranged y1 y2)))
(monte-carlo point-in-integral-stream 0 0))

(define (in-unit-circle? x y)
(<= (+ (expt (- x 0.5) 2)
(expt (- y 0.5) 2))
(expt 0.5 2)))

(define pi-integral-estimates
(stream-map (lambda (area) (/ area (* 0.5 0.5)))
(integral-estimates in-unit-circle? 0.0 1.0 0.0 1.0)))
```