A Million Random Digits with 100,000 Normal Deviates1 is a book that was published in 1955 by the RAND Corporation2. The book — that mainly consists of a table with a long sequence of randomly generated digits, as the title suggests — was important in the 20th century in the fields of statistics and random numbers. From 1947 it was constructed by means of an electronic simulation of a roulette wheel that was connected on a computer, and of which the results were meticulously filtered and tested before being added to the table.

willekeurige cijfers

The RAND table meant an important break-through in working with random numbers, since a table of this size and coincidence degree was not available before. Apart from the availability in book format, the digits could also be ordered on punch cards. the table was mainly used in statistics and with the experimental purpose of scientific experiments, primarily those that used so-called Monte Carlo-simulations3. The book was one of the last in a sequence of tables with random numbers that were produced from the middle of the twenties until the fifties. From then on, the rise of computers allowed generating pseudo-random numbers in a faster way than they could be looked up in tables.

The book was republished in 2001 (ISBN 0-8330-3047-7) with a new prologue from Michael D. Rich, Executive Vice President of the RAND Corporation. Since then, it has received a lot of funny comments on Amazon.com4:

The average readers rewards the book with four stars.

Preparation

In the random module from the Standard Python Library5 a datatype Random is defined, that can be used to make pseudo-random choices. After all, a computer can never really work randomly, but always has to execute an algorithm that simulates coincidence. Such algorithms calculate, for example, a next choice based on the previous choice. The first time a choice must be made, however, these algorithms need a set start point because there was no previous choice. This is the so-called seed. The example session below illustrates how setting this seed can influence making random choices.

>>> characters = 'UNCOPYRIGHTABLE'

>>> from random import Random
>>> generator = Random()

>>> [generator.choice(characters) for _ in range(10)]
['E', 'Y', 'R', 'A', 'C', 'P', 'T', 'I', 'I', 'L']
>>> [generator.choice(characters) for _ in range(10)]
['I', 'R', 'C', 'I', 'H', 'T', 'H', 'R', 'T', 'L']

>>> generator.seed(3)
>>> [generator.choice(characters) for _ in range(10)]
['O', 'H', 'G', 'C', 'Y', 'E', 'H', 'I', 'T', 'H']
>>> [generator.choice(characters) for _ in range(10)]
['N', 'H', 'U', 'E', 'L', 'I', 'P', 'G', 'O', 'O']

>>> generator.seed(3)
>>> [generator.choice(characters) for _ in range(10)]
['O', 'H', 'G', 'C', 'Y', 'E', 'H', 'I', 'T', 'H']
>>> [generator.choice(characters) for _ in range(10)]
['N', 'H', 'U', 'E', 'L', 'I', 'P', 'G', 'O', 'O']

>>> generator.seed(17)
>>> [generator.choice(characters) for _ in range(10)]
['G', 'R', 'B', 'P', 'Y', 'P', 'C', 'B', 'A', 'A']
>>> [generator.choice(characters) for _ in range(10)]
['G', 'T', 'P', 'N', 'E', 'U', 'O', 'R', 'L', 'A']

In a first instance, a new object of the class Random is made. Because no seed is given at that moment, the system time (the time that the computer reads on its clock) is used as seed. After that, the method choice is used to choose a random object from a given compound object (in this case a random character from the string UNCOPYRIGHTABLE).

Setting a new seed is done by means of the seed methode. To this method, any (immutable) object can be given, that is then used as a new seed. The value None means that the system time will be used as seed. If you watch the session above closely, you will see that setting that setting the same seed as a start base (illustrated here by means of the seed 3) will result in the same sequence being made over and over. Because of this, you can have the randomness of you programs go predictable in a certain sense.

Assignment

Define a class CharacterGenerator with which a random sequence of characters can be generated in a predictable way. These characters are chosen randomly from the alphabet given. For this, the objects of the class CharacterGenerator must contain at least the following methods:

Example

>>> digits = CharacterGenerator(3)
>>> digits 
CharacterGenerator(3)

>>> digits.sequence()
'3'
>>> digits.sequence(19)
'9825979190748337887'
>>> digits.sequence(30)
'623286012904047966697251027346'

>>> digits.sequence()
>>> digits
CharacterGenerator(3)
>>> digits.sequence(20)
'39825979190748337887'
>>> digits.sequence(30)
'623286012904047966697251027346'

>>> digits.reset(7)
>>> digits
CharacterGenerator(7)
>>> digits.sequence(20)
'52601815908301661318'
>>> digits.sequence(30)
'609139099603082462819482199351'

>>> CharacterGenerator(None)
Traceback (most recent call last):
AssertionError: no seed was given

>>> spam1 = CharacterGenerator(3, 'SPAM')
>>> spam2 = CharacterGenerator(3, 'SPAM')
>>> spam1.sequence(10)
'PPAMSSMAPP'
>>> spam2.sequence(10)
'PPAMSSMAPP'
>>> spam1
CharacterGenerator(3, alphabet='SPAM')