;; 3-6.scm ;; ;; Exercise 3.6: It is useful to be able to reset a random-number ;; generator to produce a sequence starting from a given value. Design ;; a new rand procedure that is called with an argument that is either ;; the symbol generate or the symbol reset and behaves as follows: ;; ;; (rand ’generate) : produce a new random number ;; ;; ((rand ’reset)〈new-value〉) : resets the internal state variable ;; to the designated〈new-value〉. ;; ;; Thus, by resetting the state, one can generate repeatable ;; sequences. These are very handy to have when testing and debugging ;; programs that use random numbers. ;; ;; ----------------------------------------------------------- ;; ;; Guile scheme has a built-in (random max) that gives a pseudo-random ;; from 0 to max-1. ;; ;; First I'll construct something similar that has an explicit seed ;; in the argument list, similar to the discussion in the next, ;; using the mod arithmetic approach mentioned in the text, and ;; the discussion at en.wikipedia.org/wiki/Linear_congruential_generator . ;; I choose these values : ;; x[n+1] = (A * x[n] + C) mod M ;; M = 2**32 , A = 1103515245 , C = 1013904223 (from Numerical Recipes) (define (next-rand seed) ;; return the next pseudo-random in the sequence, 0 <= seed < 2**32 (let ((A 1103515245) (C 1013904223) (M 4294967296)) ;; 2**32 i.e. 32 bits (modulo (+ (* A seed) C) M))) (define (next-rand-list seed max how-many) ;; return a list of how-many positive pseudo-randoms less than max. ;; (This version used (next-rand seed) and therefore needs an explicit seed.) (if (< how-many 0) '() (let ((next-seed (next-rand seed))) (cons (modulo next-seed max) (next-rand-list next-seed max (- how-many 1)))))) ;; So let's see some pseudo-randoms, eh? (let ((seed 1234567) (how-many 20) (max 10)) (display (next-rand-list seed max how-many)) (newline)) ;; That gives : (8 3 4 5 6 1 6 9 0 7 4 3 2 9 2 1 6 9 4 7 0) ... which looks OK. ;; ---------------------------- ;; ;; Now use that starting point to do what the question asks, ;; replacing (rand-next seed) with (rand 'generate) (define (rand what) ;; your code goes here ;; TODO - write this function. ) (define (rand-list max how-many) ;; return a list of how-many positive pseudo-randoms less than max. ;; (This version uses (rand command) ... which has a seed built in.) (if (< how-many 0) '() (let ((next-seed (next-rand seed))) (cons (modulo next-seed max) (next-rand-list next-seed max (- how-many 1)))))) ;; tests :