- Read By
- Wednesday, Oct 31, 2018
- Summary
- Up to this point, all of the programs we have written are,
in some sense, predictable. That is, the output depends only on the
input. However, we want some programs, such as games and simulations,
to be less predictable. We may also want to have make drawings using
unpredictable procedures, so that we can derive inspiration from
unexpected results. In this reading, we consider Scheme’s tools for
supporting such unpredictability, particularly the
`random`

procedure.

Many computing applications involve the simulation of games or events, with the hope of gaining insights and identifying underlying principles. In some cases, simulations can apply definite, well-known formulae. For example, in studying the effect of a pollution source in a lake or stream, one can keep track of pollutant concentrations in various places. Then, since the flow of water and the interactions of pollutants is reasonably well understood, one can follow the flow of the pollutants over a period of time, according to known equations.

In other cases, specific outcomes involve some chance. For example, when an automobile begins a trip and encounters a traffic light, it may be a matter of chance whether the light is green, yellow, or red. Similar uncertainties arise when considering genetic mutations or when tabulating outcomes involving flipping a coin, tossing a die, or dealing cards. In these cases, one may know about the probability of an event occurring (a head occurs about half the time), but the outcome of any one event depends on chance.

In studying events that involve some chance, one approach is to model the event or game, using a random-number generator as the basis for decisions. If such a model is simulated many times on a computer, the results may give some statistical information about what outcomes are likely and how often each type of outcome might be expected to occur. This approach to problem solving is called the *Monte Carlo Method*.

`random`

procedureA random number generator for a typical computer language is a procedure
that produces an unpredictable value each time it is called. Such
procedures simulate a random selection process. Scheme provides the
procedure `random`

for this purpose. This procedure returns integer
values that depend on its parameter. In particular, `random`

returns an
unpredictable integer value between 0 and one less than its parameter,
inclusive. By “unpredictable” we mean that we are unlikely to be
able to predict the number that `random`

will return.

```
> (random 10)
1
> (random 10)
9
> (random 10)
7
> (random 10)
0
> (random 10)
5
> (random 10)
1
> (random 10)
0
```

We can use `random`

to write a program to simulate the rolling of a die. The simulation generates integers from 1 to 6, to correspond to the faces on the die cube. The details of this simulation are shown in the following procedure:

```
;;; Procedure:
;;; roll-a-die
;;; Parameters:
;;; None
;;; Purpose:
;;; To simulate the rolling of one six-sided die.
;;; Produces:
;;; An integer between 1 and 6, inclusive.
;;; Preconditions:
;;; [None]
;;; Postconditions:
;;; Returns an integer between 1 and 6, inclusive.
;;; It should be difficult (or impossible) to predict which
;;; number is produced.
(define roll-a-die
(lambda ()
(+
(random 6) ; a value in the range [0 .. 5]
1))) ; now in the range [1 .. 6]
```

We can use that procedure to simulate the roll of multiple dice.

```
;;; Procedure:
;;; roll-dice
;;; Parameters:
;;; n, an integer
;;; Purpose:
;;; Roll n six-sided dice and make a list of their values.
;;; Produces:
;;; rolls, a list of integers
;;; Preconditions:
;;; [No additional]
;;; Postconditions:
;;; (length rolls) = n
;;; Each element of rolls is a value between 1 and 6.
;;; The values in rolls are reasonably evenly distributed.
;;; The values in rolls are difficult to predict.
(define roll-dice
(lambda (n)
(if (zero? n)
null
(cons (roll-a-die) (roll-dice (- n 1))))))
```

We can also use `random`

to select “unpredictable” elements of a list.
Let’s start with a simple procedure.

```
;;; Procedure:
;;; random-elt
;;; Parameters:
;;; lst, a non-empty list
;;; Purpose:
;;; Unpredictably pick an element of lst.
;;; Produces:
;;; val, a value
;;; Preconditions:
;;; [No additional]
;;; Postconditions:
;;; * val is an element of lst.
;;; * If lst contains more than one element, it is difficult to predict
;;; which element val is.
(define random-elt
(lambda (lst)
(list-ref lst (random (length lst)))))
```

There are many ways to apply `random-elt`

. For example, here’s
a collection of procedures that make an unpredictable sentence.

```
(define sentence
(lambda ()
(string-append
(random-person) " "
(random-transitive-verb) " "
(random-object) ".")))
(define random-person
(let ([people (list "Anh Thu" "Charlie" "Fahmida" "Halle"
"John" "Maisy" "Yesheng" "Zoe")])
(lambda ()
(random-elt people))))
(define random-transitive-verb
(let ([verbs (list "saw" "watched" "threw" "ate" "borrowed")])
(lambda ()
(random-elt verbs))))
(define random-object
(let ([articles (list "the" "a")]
[adjectives (list "heavy" "blue" "green" "hot" "cold" "disgusting")]
[nouns (list "cup of coffee" "computer" "classroom"
"PBJ algorithm" "homework assignment")])
(lambda ()
(string-append
(random-elt articles) " "
(random-elt adjectives) " "
(random-elt nouns)))))
```

Here’s one example of the primary procedure in action.

```
> (sentence)
"Anh Thu borrowed a cold cup of coffee."
```

`random`

a. When you give the procedure `random`

the parameter * n*, it will produce one of how many unique values? What is the smallest value? What is the largest?

b. Evaluate the expression `(random 10)`

several times. What values do you get?

c. What values do you expect to get if you call `random`

with 1 as a parameter?

d. Check your hypothesis experimentally.

e. What do you expect to happen if you call `random`

with 0 or -1 as a parameter?

f. Check your hypothesis experimentally.

g. What do you expect to happen if you call `random`

with non-integer parameters.

h. Check your hypothesis experimentally.

i. Try calling `random`

with no parameters. What happens?

a. Add the following two procedures to the definitions pane.

```
;;; Procedure:
;;; roll-a-die
;;; Parameters:
;;; None
;;; Purpose:
;;; To simulate the rolling of one six-sided die.
;;; Produces:
;;; An integer between 1 and 6, inclusive.
;;; Preconditions:
;;; [None]
;;; Postconditions:
;;; Returns an integer between 1 and 6, inclusive.
;;; It should be difficult (or impossible) to predict which
;;; number is produced.
(define roll-a-die
(lambda ()
(+
(random 6) ; a value in the range [0 .. 5]
1))) ; now in the range [1 .. 6]
;;; Procedure:
;;; roll-dice
;;; Parameters:
;;; n, an integer
;;; Purpose:
;;; Roll n six-sided dice and make a list of their values.
;;; Produces:
;;; rolls, a list of integers
;;; Preconditions:
;;; [No additional]
;;; Postconditions:
;;; (length rolls) = n
;;; Each element of rolls is a value between 1 and 6.
;;; The values in rolls are reasonably evenly distributed.
;;; The values in rolls are difficult to predict.
(define roll-dice
(lambda (n)
(if (zero? n)
null
(cons (roll-a-die) (roll-dice (- n 1))))))
```

b. Using `roll-dice`

, roll ten dice.

c. Using `roll-dice`

, roll ten dice. (Yes, this instruction is the same
as the previous instruction. You should do it twice.)

d. Did you get the same list of values each time? Why or why not?

e. What other procedures have you encountered that may return different values each time you call them with the same parameters?