CPSC 110-08: Computing on Mobile Phones
Spring 2012
Modeling a Fair Coin

CS Principles

This homework addresses several ideas, including creativity, abstraction, algorithms, and programming. It focuses on developing a program to simulate a sequence of coin tosses as a means of testing the "goodness" of App Inventor's pseudo random number generator (PRNG). It addresses the following learning objectives.

Introduction

This homework is a follow-up to the How to Flip a Coin tutorial, where we learned how to use App Inventor's pseudo random number generator (PRNG) to simulate a coin flip.

Recall that App Inventor's PRNG is a generates a random-looking sequence by means of a deterministic function that computes the n+1st value in the sequence from the nth value:

Xn+1 = (aXn + b) mod m

Thus, a PRNG is model of a truly random process. For any such model, it is natural to ask: ow good is App Inventor's PRNG? How well does it model a truly random process?

Is that a Fair Coin?

One way to test the quality of App Inventor's PRNG is to see how well it does at simulating a random process such as flipping a coin. We all know that if you flip a coin it will come up either heads or tails. But suppose you repeatedly ran an experiment where you flip a real coin 10,000 times and it came up heads an average of 3,938 times and tails an average of 6,062 times, as summarized in the following table:

TrialnTossesnHeadsnTails
110,00040006000
210,00039856015
310,00039956005
410,00037006300
510,00040105990
Averages10,00039386062

If you received these results, you would doubt whether the coin is truly fair? Maybe it is rigged somehow?

Similarly, if you are using App Inventor's PRNG to model a coin toss, then over the long run it should produce roughly 50% heads and 50% tails.

In this tutorial we design an app that helps us to test how good the PRNG is at simulating random events. We will use a while loop to generate a sequence of coin flips and count the numbers of heads and tails.

Homework

  1. Download the source code for Fair Coin Experiment app, save it as a zip file on your computer, and then upload it into App Inventor.

  2. Read the description of the app (below), read the app's source code, and figure out how the app works.

  3. Conduct the following experiment on both your phone and the App Inventor emulator:

    Run at least 10,000 trials of the coin-flip experiment on both the phone and the emulator and record the number of total flips, number of heads, and number of tails.

    NOTE: The app is kind of slow. So rather than running 10,000 trials in a single experiment. Run a smaller number of trials -- e.g., 1000 -- and repeat the experiment.

    Not Responding Message: If you get this message, click the "continue" option rather than the quit option -- the app is just slow.

  4. Create a portfolio page for this homework and paste your experiments' results. Then answer and justify your answer to the following question:

    Is App Inventor's PRNG, as implemented on the emulator and as implemented on the phone, a good model for a random process such as flipping a coin?

The Fair Coin Experiment App

Let's write an app to help us perform this experimental test of App Inventor's PRNG.

User Interface

Our app must let the user input how many times they want to 'flip' the coin and must report how many heads and tails were obtained. To do this, our user interface will contain the following components:

ComponentPurpose
TextBoxNumFlipsLet's the user input the number of times to 'flip' the coin
LabelTossLabels the TextBox
LabelHeadsReports the number of heads obtained
LabelTailsReports the number of tails obtained
ButtonStartFlips the coin repeatedly until desired number of flips is obtained
ButtonResetResets all counters so the experiment can be repeated.

The app will use these components to produce the following user interface (click to enlarge):

The idea here is that the user can input a number indicating how many Tosses. When the button is clicked, the app will simulate that many coin tosses and record and display the number of heads and tails.

Data Abstraction -- Variables

What variables do we need for this app? That depends on what objects we want to model and what data we want to remember. In this app we are modeling a two-sided coin, so we should have a Coin variable. And we need to count how many times it comes up heads and tails. So we need a couple of counter variables. And we need a variable to remember how many times the user wants us to 'flip' the coin. Also, because we will need to repeatedly flip the coin, we will need a variable to keep track of the number of times we have repeated the loop.

Thus, our app defines the following variables:

VariablePurpose
CoinModel: Represents a 2-sided coin where 1 represents heads and 2 represents tails
nFlipsLoop limit: Represents how many times the user wants to flip the coin.
nHeadsCounter: Counts the number of heads obtained
nTailsCounter: Counts the number of tails obtained
flipLoop counter: counts how many times we have 'flipped' the coin

Procedural Abstraction

To make it easier to implement our experiment our app will be divided into procedures that represent the basic steps. This will allow us to think about the experiment at a higher level of abstraction.

We'll need a procedure to initialize the experiment -- i.e., set it up. Another procedure to perform a coin flip and keep track of whether it is heads or tails. And another procedure to report the results. This leads to the following design:

ProcedurePurpose
InitializeTheExperimentInitialize all the variables and data we use to keep track of the results.
ReportTheResultsDisplay the number of heads and tails in the user interface.
DoOneCoinFlipSimulate the coin flip and count whether it was a head or a tail.

Algorithms

Let's now develop the algorithms for each of these procedures. The InitializeTheExperiment procedure is just a simple sequence of assignment statements -- i.e., statements that set the values of certain variables:
# Comment: InitializeTheExperiment -- set all the variables to 0
#  and initialize the labels to 0 and get the number of flips from 
#  the text box.

To InitializeTheExperiment
   Set nHeads to 0
   Set nTails to 0
   Set LabelHeads.Text to "Heads: 0"
   Set LabelTails.Text to "Tails: 0"
   Set nFlips to TextBoxNumFlips.Text
#Comment: Set the labels for number of heads and number of tails

To ReportTheResults
   Set LabelHeads.Text to "Heads: " joined-with nHeads
   Set LabelTails.Text to "Tails: " joined-with nTails
#Comment: Generate a random integer between 1 and 2 inclusive and
#  increment the appropriate counter for heads or tails.

To DoOneCoinFlip
    Set Coin to a random integer between 1 and 2
    If Coin = 1 then-do:
       Set nHeads to nHeads + 1
    else-do:
       Set nTails to nTails + 1

Event Handlers

This app has two event handlers, one for each button. The algorithm for the ButtonReset button is very simple. It just needs to call the InitializeTheExperiment procedure that we wrote:

# Comment: When the ButtonReset is clicked, initialize the experiment.

When ButtonReset.Click
   Call InitializeTheExperiment

The algorithm for ButtonStart event requires a loop. When this button is clicked we want to flip the coin nFlips number of times. So we need to initialize our loop counter to 1 and then loop through the steps of flipping the coin and incrementing the counter. When the loop finishes, we should report the results.

# Comment: Repeat the coin flip from 1 to nFlips number of times.

When ButtonStart.Click
   Set flip to 1
   While flip <= nFlips do:
       Call DoOneCoinFlip
       Set flip to flip + 1
   Call ReportTheResults   

Notice how much easier it is to read and understand this algorithm now that we are hiding some of the details in the procedures. This is also true for the App Inventor blocks: