Scheme - generate random

13,482

Solution 1

The procedure is called, surprisingly enough, random - although the exact syntax might be different depending on the Scheme interpreter in use (read the documentation!), but the general idea is as follows:

(random)
=> 0.9113789707345018

For returning one of two possible values, this will do the trick in Racket:

(define (random-choice a b)
  (if (zero? (random 2)) a b))

Notice that the 2 argument passed to random forces it to randomly return one of two possible values: 0 or 1. So if (random 2) evaluates to 0 then a is returned, otherwise b is returned.

(random-choice 4 2)
=> 4
(random-choice 4 2)
=> 2

Solution 2

Standard Scheme does not provide a random number generator, and although most Scheme implementations provide one, they tend to differ in their details. If you want to write a portable Scheme program, it's easy to build your own random number generator; here's a method due to Knuth:

(define random
  (let ((a 69069) (c 1) (m (expt 2 32)) (seed 19380110))
    (lambda new-seed
      (if (pair? new-seed)
          (set! seed (car new-seed))
          (set! seed (modulo (+ (* seed a) c) m)))
      (/ seed m))))

Calling (random) returns a random fraction between 0 (inclusive) and 1 (exclusive). The random fractions cycle with period m. Calling (random seed) resets the seed of the random number generator, so that two random sequences starting from the same seed will be identical; dates in the form YYYYMMDD make good seeds (that's Knuth's birthday above). If you want to flip a coin, say: (if (< (random) 1/2) 'heads 'tails).

Sometimes you want a random integer over a range. The randint function shown below returns a random integer on the range lo (inclusive) to hi (exclusive); lo defaults to 0:

(define (randint . args)
  (cond ((= (length args) 1)
          (floor (* (random) (car args))))
        ((= (length args) 2)
          (+ (car args) (floor (* (random) (- (cadr args) (car args))))))
        (else (error 'randint "usage: (randint [lo] hi)"))))

Random numbers such as these are good enough for simple simulations, but beware they are not suitable for cryptographic applications. If you are interested, I have several random number generators, including some suitable for cryptographic applications, at my blog.

Solution 3

Since your other question was about implementing a spaceship game in DrRacket, I will assume, that by Scheme you mean one of the teaching languages in DrRacket.

The way to find information on available functions in DrRacket is simple. Write, say, random in the interaction window. Place the cursor on top, and then press F1.

The documentation on the random in htdp-languages is here:

http://docs.racket-lang.org/htdp-langs/beginner.html?q=random#(def.htdp-beginner.((lib._lang/htdp-beginner..rkt)._random))

One way to return a random value:

(list-ref (list "one" "two") (random 2))

Here (random 2) will return 0 or 1. The list-ref will thus return either the entry with index 0 or index 1 of the list.

The advantage of using the above approach is that it is easy to extend to more values than two.

Share:
13,482
tlauer
Author by

tlauer

Updated on June 04, 2022

Comments

  • tlauer
    tlauer almost 2 years

    How do I generate random in Scheme? Is there a special form or would I have to create a procedure? And if so, how do I do that? (I'm trying to create a procedure called random-choice that inputs two strategies and returns one at random.)

  • sepp2k
    sepp2k about 11 years
    Not in standard Scheme it isn't. Most implementations have a facility for creating random numbers, but they don't all use the same name or the same signature. For example in Guile there is a random procedure, but it requires at least one argument and always returns an integer. So your code will cause an error in Guile (and many other Scheme implementations as well, I imagine). It's okay to give implementation-specific answers, if there are no standard answers, but you should at least mention that it is implementation specific and to which implementation it is specific.
  • C. K. Young
    C. K. Young about 11 years
    @sepp2k If by "standard" you include "final" SRFIs (and I do), SRFI 27 specifies an interface for getting random numbers.