Code Review
Compare your solutions
#|
Упражнение 3.6
Полезно иметь возможность сбросить генератор случайных чисел, чтобы получить последовательность, которая
начинается с некоторого числа. Постройте новую процедуру rand, которая вызывается с аргументом. Этот
аргумент должен быть либо символом generate, либо символом reset. Процедура работает так: (rand 'generate)
порождает новое случайное число; ((rand 'reset) <новое-значение>) сбрасывает внутреннюю переменную
состояния в указанное <новое-значение>. Таким образом, сбрасывая значения, можно получать повторяющиеся
последовательности. Эта возможность очень полезна при тестировании и отладке программ, использующих
случайные числа.
|#
(#%require rackunit)
(define (make-linear-congruent-gen x0)
(let ((m (inexact->exact
(expt 2 (+ 16 (ceiling (log 2 (ceiling (abs x0)))))))))
(let ((a (random m))
(c (random m)))
(lambda (x) (modulo (+ (* a x) c) m)))))
(define (make-rand initial-x)
(let ((next (make-linear-congruent-gen initial-x)))
(let ((current-x initial-x))
(lambda (op)
(cond ((eq? op 'reset)
(lambda (initial-value)
(set! current-x initial-value)))
((eq? op 'generate)
(set! current-x (next current-x))
current-x)
(else current-x))))))
(define rand (make-rand 1000))
(define random-value (rand 'generate))
(define test-value-1 (rand 'generate))
(define test-value-2 (rand 'generate))
(define test-value-3 (rand 'generate))
((rand 'reset) random-value)
(check-equal? test-value-1 (rand 'generate))
(check-equal? test-value-2 (rand 'generate))
(check-equal? test-value-3 (rand 'generate))