If you're seeing this message, it means we're having trouble loading external resources on our website.

If you're behind a web filter, please make sure that the domains *.kastatic.org and *.kasandbox.org are unblocked.

Main content

Programming a simple simulation

Ever heard the fable about the tortoise and the hare?
A hare makes fun of a tortoise for moving so slowly and challenges the tortoise to a race. The hare speeds ahead in the race, but then seeing that he's so far ahead, he takes a nap. The hare wakes up to discover that the tortoise had slowly but surely overcome him. 🐢> 🐇 !
An illustration of a tortoise walking past a hare that is asleep in the bushes.
Illustration from a children's book. Image source: Project Gutenberg
The fable has inspired people to run actual races between tortoises and hares. I don't have any such animals handy, but I am curious to see if it's really possible: can a tortoise beat a sleepy hare? How fast must the tortoise be and how sleepy must the hare be?
Let's investigate the questions by programming a simulation.

Starting simple

We'll begin by simulating a race between a tortoise and a hare that doesn't take naps. I think we both know the results of that race, but when we're programming, it helps to start with a simpler problem and then add complexity after.
First we need to establish some initial conditions:
  • The length of the race
  • The average speed of the tortoise
  • The average speed of the hare
We also need to keep track of some values that vary during the race:
  • The current position of the tortoise
  • The current position of the hare
We can store both the initial conditions and the varying values in variables.
Here's JavaScript code that initializes those variables:
var tortoiseSpeed = 1;
var hareSpeed = 2;
var raceDistance = 350;

var tortoisePos = 0;
var harePos = 0;
Then we can use a loop that updates the position of the tortoise and the hare and only stops once one of them reaches the finish line.
while (tortoisePos < raceDistance && harePos < raceDistance) {
    tortoisePos += tortoiseSpeed;
    harePos += hareSpeed;
}
Here's the running simulation with that code:
📝 See similar code in: App Lab | Snap | Python
As long as the hare is faster than the tortoise, it will win that race. Now that we've got that working, it's time to make it more interesting.

Adding complexity

Our simulation needs to model the behavior of a lazy hare. We can start by establishing some initial properties about his laziness:
  • How long is he typically awake between naps?
  • When he does nap, how long are the naps?
Here's JavaScript code that stores those properties as variables:
var minsBetweenNaps = 30; 
var napLength = 20;
To figure out when to stop the hare for naptime, we need to also keep track of some values:
  • How long has it been since the last nap?
  • If he's currently napping, how long has it been since the nap started?
This code stores initial values for those variables:
var minsSinceLastNap = 0;
var minsSinceNapStart = 0;
The hare starts off awake and running, so both variables start at 0.
Finally, we need to add logic inside the loop to make the hare take naps.
If the hare doesn't need to nap yet, the code updates the hare position (like before) and increments minsSinceLastNap:
if (minsSinceLastNap <= minsBetweenNaps) {
    harePos += hareSpeed;
    minsSinceLastNap++;
}
If the hare should be napping, the code increments minsSinceNapStart, and once the hare has finished napping, the code resets minsSinceLastNap and minsSinceNapStart to 0:
else {
     if (minsSinceNapStart < napLength) {
          minsSinceNapStart++;
      } else {
          minsSinceLastNap = 0;
          minsSinceNapStart = 0;
      }
}
Check out the code all together in the running simulation below. Which racer wins? How can you change the parameters to make the other racer win instead?
📝 See similar code in: App Lab | Snap | Python

Visualizing the changes

A simulation does not have to have a visual output; it may just have a textual or numeric output like the simulations above. However, a visualization can help the users of a simulation gain a more intuitive understanding of the output.
The way in which we add a visual component to a computer simulation depends on the language we're using and what libraries we have available. In the Khan Academy coding environment, we can use the ProcessingJS library to draw and animate shapes onto the screen, so that's a great fit for visualizing this simulation.
This simulation runs the same logic as before but adds a visualization:
📝 See similar code in: App Lab | Snap | Python

Adding variability

The real world is full of variation. Tortoises and hares vary in their speeds; the slowest tortoise moves at 0.3 km/hr while the fastest moves at 5 km/hr. Plus, within a race, the tortoise and hare won't move at exactly the same speed the whole time; they'll have their fast moments and slow moments.
One way to add variation to a simulation is to generate random numbers. We can find out the expected ranges of a value in the real world and generate values within those ranges.
Try to find all the places that use randomly generated numbers in this version of the simulation, and then restart to see what changes:
📝 See similar code in: App Lab | Snap | Python
Note that this simulation uses more realistic numbers for the speed of the hare versus the tortoise, so you might be a bit shocked by the results. Play around with the nap parameters to see if you can give the tortoise a shot at winning the race.

What's excluded?

This simulation is an abstraction of a real world scenario. It attempts to include the most significant parameters about the scenario, but it cannot include everything.
Here are some ideas for excluded details that might affect the race:
  • whether each racer moves in a straight path or meanders
  • whether each racer has the calories necessary to keep racing
  • whether either racer risks overheating during the race
🤔 What else is the simulation missing? How could the simulation be more realistic? What parameters would let us investigate more possibilities?

🙋🏽🙋🏻‍♀️🙋🏿‍♂️Do you have any questions about this topic? We'd love to answer—just ask in the questions area below!

Want to join the conversation?

  • blobby green style avatar for user Samantha Doshier
    what does it mean to add variation to a simulation
    (4 votes)
    Default Khan Academy avatar avatar for user
    • starky ultimate style avatar for user KLaudano
      We can use randomness to change aspects of the simulation and add some variation. For example, we could randomize the color of a flower or the path of a ball. This can make the simulation more interesting as it would change every time we would run it.
      (6 votes)
  • eggleston green style avatar for user Jeronimo
    QUESTION ABOUT : The code just before "Visualizing the changes". Is my reasoning below correct? Tortoise is making one extra step per each Hare nap, Hare is sleeping for 20 minutes, so the tortoise must make 20 more steps while the Hare is sleeping, but we can see that it makes 21 steps. The hare is resting one minute after he is done having a nap, which was not nebtioned in the description, therefore was not the original intension. You can also see it in the Simulation if you make the framerate 1 and count, tortoise is making one extra step per each Hare nap.

    I counted the total time the Hare slept with "var count = 0". I put "count++" here "if (minsSinceNapStart < napLength)" and "println(count)" after the whole code, so that it shows me the total time the hare was sleeping. The results were as follows: Total nap time = 100; Hare position = 350; Tortoise position = 280. So we could say that the whole race took 280 minutes, since tortoise is constantly moving at a rate 1 step per minute. However when we calculate the time of the race with HARE it does not coincide: 350/2 = 175 minutes the hare was running, and the rest amount of time he was having a nap 100 minutes, which gives us 175+100=275 minutes. The race took 280 minutes if we calculate with tortoise and 275 minutes if we do the same with the Hare. I found that the problem was as follows: the loop runs updating the var minsSinceNapStart 20 times, each time it updates the tortoisePos. so far so good. But after the variable napLength stores 20, next time the loop runs it updates tortoisePos, but does not update the harePos, because the loop checks the condition it sees that minsSinceNapStart is equal to naplength so it moves forward to the last else condition that updates the variables minsSinceLastNap = 0; minsSinceNapStart = 0. So it appears that after having slept for 20 minutes not moving, the Hare is also not moving for one extra minute after he wakes up, while the tortoise does make a step. So we must add an extraline to the last ELSE condition of the loop "harePos += hareSpeed". If we do so the results are as follows: Total nap time = 100; Hare position = 350 ; Tortoise position = 275! If we calculate now we will see that there are no mismatches this time: 350/2=175. 175+100=275, which is equal to the time tortoise was moving. You can also see it in the Simulation, tortoise is making one extra step per each Hare nap.
    The edited code:
    var tortoiseSpeed = 1;
    var hareSpeed = 2;
    var raceDistance = 350;
    var minsBetweenNaps = 30;
    var napLength = 20;

    var tortoisePos = 0;
    var harePos = 0;
    var minsSinceLastNap = 0;
    var minsSinceNapStart = 0;
    var count = 0;
    while (tortoisePos < raceDistance && harePos < raceDistance) {
    tortoisePos += tortoiseSpeed;
    if (minsSinceLastNap <= minsBetweenNaps) {
    harePos += hareSpeed;
    minsSinceLastNap++;
    } else {
    if (minsSinceNapStart < napLength) {
    minsSinceNapStart++;
    count++;
    } else {
    minsSinceLastNap = 0;
    minsSinceNapStart = 0;
    harePos += hareSpeed;
    }
    }
    }

    println("The total time the hare was having a nap is " + count + " minutes");
    println("Tortoise position: " + tortoisePos);
    println("Hare position: " + harePos);
    (3 votes)
    Default Khan Academy avatar avatar for user
  • hopper cool style avatar for user Lucky
    one racer could have an emergency and have to forfeit the race.
    whether there is a tornado that destroys the finish line. no finish line, no end to the race.
    whether there is a referee who can say who won the race.
    whether or not the race is actually just a simulation that has bias input. Maybe the code is not precise.
    (2 votes)
    Default Khan Academy avatar avatar for user