Random numbers

randint, choice and seeds: dice, random tunes and a robot that wanders.

F3.7Strings, lists and recordsGCSE12 min

Covers OCR J277 2.2.3 Additional programming techniques · AQA 8525 3.2.9 Random number generation in a programming language · Edexcel 1CP2 6.6.1 Built-in, library and user-devised subprograms

Do this lesson in the simulator

Games roll dice, simulations need unpredictable events, and a robot that explores a room gets stuck in corners less if it sometimes turns a random amount. Python's random library makes numbers that cannot be predicted.

randint

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

import random

roll = random.randint(1, 6)
print("you rolled", roll)
for i in range(5):
    print(random.randint(1, 6), end=" ")
print()

Run this in the simulator

Run it several times: the numbers change. random.randint(1, 6) gives a whole number from 1 to 6, and unlike range, both ends are included, so 6 can come up.

A number line from 0 to 7: randint(1, 6) can give 1 to 6, while range(1, 6) gives 1 to 5 and leaves out 6random.randint(1, 6)012345676 can come uprange(1, 6)012345676 left outfilled dot: can come out
randint includes both of its ends, so a dice roll can be 6. range stops before its second number, so range(1, 6) never reaches 6. Mixing them up is a common exam slip.

import random brings in the library, the same way from bugbot import * brings in the robot. Because it was imported with plain import, its functions are written with random. in front.

Other random choices

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

import random

print(random.random())                         # a real number from 0 up to 1
print(random.uniform(10, 20))                  # a real number between 10 and 20
colour = random.choice(["red", "green", "blue", "yellow"])
print("today's colour is", colour)
led(colour)

Run this in the simulator

random.choice picks one item from a list. random and uniform give real numbers, for when a whole number is not enough.

A robot that wanders

Random turns stop a robot repeating the same path forever:

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

import random

for step in range(8):
    if distance() > 25:
        forward(60, distance=10)
    else:
        angle = random.choice([90, -90, 135, -135])
        print("too close, turning", angle)
        tone(330, 0.1)
        turn_right(30, angle=angle)
print("wandered to", position())

Run this in the simulator

Run it a few times and compare the trails. The program is the same, but each run takes a different route.

Checking your odds

A random program is hard to test, because each run is different. One way is to run it many times and count:

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

import random

counts = [0, 0, 0, 0, 0, 0]
for i in range(600):
    roll = random.randint(1, 6)
    counts[roll - 1] = counts[roll - 1] + 1
print("ones to sixes:", counts)

Run this in the simulator

Each face should come up about 100 times in 600 rolls, but rarely exactly 100. counts[roll - 1] uses the roll as an index: a roll of 1 counts in item 0.

A bar chart of how many times each face came up in one run of 600 rolls, all close to 100 but none exactly050100count104roll 1counts[0]102roll 2counts[1]103roll 3counts[2]94roll 4counts[3]113roll 5counts[4]84roll 6counts[5]
One run of the lesson's loop. Every face lands near the expected 100 but none exactly: here from 84 to 113. Your run will give different counts. Each roll counts in the item one below it, so roll 1 is counts[0].

Random, but the same every time

Tasks in these lessons need to check your program the same way on every run, so a task that uses random numbers fixes them: the same "random" numbers come out each time you run that task. Programmers do this on purpose when testing, by setting a seed:

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

import random

random.seed(42)
print(random.randint(1, 100), random.randint(1, 100))
random.seed(42)
print(random.randint(1, 100), random.randint(1, 100))

Run this in the simulator

Same seed, same numbers. Take the seed lines out and they vary again. Computers make these numbers with a formula, which is why they are called pseudo-random.

Two runs seeded with 42 giving the same two numbers, and a run with a different seed giving different onesrandom.seed(42)formula8215...random.seed(42)formula8215...random.seed(43)formula537...the samedifferenteach number is worked out from the one before, starting from the seed
The numbers come from a formula that starts at the seed. The same seed always gives the same list, 82 then 15 for seed 42, and a different seed gives a different list.

Task: dice drive

Roll a dice three times with random.randint(1, 6). For each roll, print roll: <n> and drive forward <n> * 5 cm. At the end print total: <cm> with the total distance, worked out from the rolls. This task fixes its random numbers, so you get the same rolls each run.

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

import random

total = 0

Challenges

  1. Flash the LED a random number of times, from 3 to 8, and ask the user to count the flashes.
  2. Play ten notes chosen at random from a list of notes: a random tune.
  3. Make the wandering robot turn a random whole number of degrees between 90 and 180, either way.

Past paper questions on this

Real exam questions that test this, each worked through with a program you can run.