Domanda

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.

È stato utile?

Soluzione

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

Altri suggerimenti

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))
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top