Question

I'm having some trouble creating an infinite random stream of numbers from 0 to 9. Here's where I'm at now:

(#%require (only mzscheme random))
(define (input_stream) (cons (random 9) (delay input_stream)))

Only problem is, (random 9) appears to be initiated only once. The stream is indeed random, but the values of the stream remain constant.

I get 7, 7, 7, 7, 7 or 3, 3, 3, 3, 3

Any ideas on how to initiate the random function each time the endless loop starts over? I've searched all over online, but couldn't find any way to tackle this one.

Was it helpful?

Solution

As it is, the random procedure is called only once because you didn't recursively call input_stream again, that's why all the random numbers in the stream are in fact, the same number. You have to guarantee that the pseudo-random number generator is called every time a new value is cons'ed, for example:

(define (random-stream n)
  (cons (random n) (delay (random-stream n))))

Now this stream will contain random numbers in the range 0-9:

(define input_stream (random-stream 10))

Note: I defined n as a parameter jut to make the generated stream parameterizable, it'll work just as well with a fixed value:

(define (random-stream)
  (cons (random 10) (delay (random-stream))))

(define input_stream (random-stream))

For example, to access the first three elements:

(car input_stream)
=> 9 ; random number between 0-9
(car (force (cdr input_stream)))
=> 7 ; random number between 0-9
(car (force (cdr (force (cdr input_stream)))))
=> 8 ; random number between 0-9

Or in general, for generating a list of m random elements from 0 (inclusive) to n (exclusive):

(define (stream-take s m)
  (if (zero? m)
      '()
      (cons (car s)
            (stream-take (force (cdr s)) (sub1 m)))))

(stream-take (random-stream 10) 20)           ; n=10, m=20
=> '(3 3 3 7 0 7 3 2 3 7 6 0 6 4 1 4 6 1 6 9) ; 20 random numbers between 0-9

OTHER TIPS

I'm not sure how much sense it makes to create a random stream, since simply calling (random n) repeatedly will achieve the same effect.

But a nice way to create streams is with stream-cons:

#lang racket

;;; infinite stream of random numbers
(define (random-stream n)
  (stream-cons 
   (random n) 
   (random-stream n)))

It is important how you consume streams, since you might end up getting the first number every time if you do it wrong:

(define S (random-stream 10))

;;; right 
(for/list ((i (range 5)))
  (stream-ref S i))
=> '(7 1 4 8 4)

;;; right
; primitive to take the first n elements of a stream
(define (stream-take s n)
  (for/list ((e s) (i (in-range n)))
    e))
(stream-take S 20)  
=> '(7 1 4 8 4 3 9 8 6 8 4 8 1 1 1 7 0 3 9 4)

;;; wrong
(for/list ((i (range 5)))
  (stream-take S 1))
=> '((7) (7) (7) (7) (7))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top