Categories
DIY Science Issue 4

Simulating the bean machine

🕒 14 min

We’re doing this issue’s DIY Science a bit unconventionally: today, you’ll write your own program to simulate a bean machine, also known as the Galton board. What’s a bean machine, why is that interesting and how to write your first program – find out in today’s post.

Take a look at this video.

The normal distribution. Diagram by M. W. Toews, Wikimedia Commons.

The falling beans approach a normal distribution, pictured left. That’s not a coincidence (if you haven’t gathered that from the curve on the device): this device is called a bean machine (or a Galton board) and it was built by Sir Francis Galton to demonstrate that very occurrence. So, how does that happen? And why do we care? To answer these questions, let’s build our own bean machine.

Building a bean machine in real life requires a lot of handywork. My original idea was to build it from wood, but I realised there’s a much easier way to demonstrate this effect: simulating it.

To do justice to the device, we need to take a look at how it works.

The bean machine on the left has 13 slots at the bottom and 10 rows of pegs through which beans fall into their slots. As you can see, there’s just one way to land in the rightmost slot (poorly drawn in orange here), while there are many more ways for a bean to land in the central slot. Hitting every peg, a bean can go left or right, which ultimately decides the slot it lands in.

Knowing this, we can effectively simulate the bean machine in code. To show this effect better, we’ll be simulating a bean machine that has 12 rows of pegs, but you can play around with the code to see what you can do!

The image on the left is based on work by Matemateca on Wikimedia Commons and shared under CC-BY-SA 4.0.

To build our simulation (and purely for the sake of simplicity, trust me) we’ll be using a programming language called JavaScript, along with a document language called HTML. It’s built into your browser, so you don’t need to set anything up.

The only thing you’re going to need is a text editor: I’d recommend something like Visual Studio Code, which is free and open source, but Notepad (or TextEdit or Gedit if you’re on a Mac or Linux computer) will also do fine if you’re in a hurry or can’t install apps. (I should probably mention that visual editors, such as Word, won’t work – you need to use something built for programming.)

To set up your work environment, open up your text editor and just save a blank file as Galton.html – your editor will now allow you to write in a new file format called HTML, which is a language used to build web pages.

You can open it in your browser to run the web page. You should see a blank page, but that’s okay. If you’re wondering if everything works properly, try typing something and seeing if it shows up properly in your web browser when you refresh the page. Whenever you change something in your HTML file, refresh the page in your browser to see the changes.

Building an interface

This is by far the most challenging and boring part of this project. If you’re not interested in this part, feel free to copy-paste the code below and skip to actually writing the code that simulates the randomness. If you haven’t ever done anything in HTML, and you’re interested in how this language works, take a look at this tutorial and come back here.

I’ll gloss over the way HTML works, but you should know the basics:

  • the things in <parentheses> are called opening tags
  • the things in </parentheses> are called closing tags
  • div and span tags are used to contain content, which can be other tags, objects or text
  • those tags form something called a document tree
  • you can manipulate and change the document tree using a programming language called JavaScript, allowing you to write apps for browsers

Here’s the code we’ll be writing:

Here’s the interface we’re going to be building.

The classes we can use to target a type of object are denoted by a dot (.) sign in front of their name, while the ids we can use to target a single object are denoted by a hash (#) sign in front of their name.

We need to build a basic webpage first – just as a simple interface to show our simulation’s results.

To do this, we start by writing a very simple HTML page, which doesn’t show or do almost anything:

<!DOCTYPE html>
<html>
	<head>
		<title>Galton board</title>
        </head>
	<body>
        </body>
</html>

We’ll put our styles and scripts in the head section and our interface template in the body section.

Now, let’s start building our slots (which I’ll be calling bins from now on).

To do this, we’re going to use div elements (which, in HTML, are just container elements).

Inside of our div elements we’ll put empty span elements (which we’ll use to contain our beans). A span element is also just a container element – it doesn’t have any meaning by itself.

We’re going to give our div elements a class called bin, so that we can apply the same styling to all of them. We’re also going to give them an id, so that we can reference a particular bin and so that we can properly position it.

Having all that in mind, we could define a single bin with something like this:

<div class="bin" id="bin1">
			<span></span>
</div>

So, we could define our 13 bins by just copying and pasting this and changing the id:

		<div class="bin" id="bin1">
			<span></span>
		</div>
		<div class="bin" id="bin2">
			<span></span>
		</div>
		<div class="bin" id="bin3">
			<span></span>
		</div>
		<div class="bin" id="bin4">
			<span></span>
		</div>
		<div class="bin" id="bin5">
			<span></span>
		</div>
		<div class="bin" id="bin6">
			<span></span>
		</div>
		<div class="bin" id="bin7">
			<span></span>
		</div>
		<div class="bin" id="bin8">
			<span></span>
		</div>
		<div class="bin" id="bin9">
			<span></span>
		</div>
		<div class="bin" id="bin10">
			<span></span>
		</div>
		<div class="bin" id="bin11">
			<span></span>
		</div>
		<div class="bin" id="bin12">
			<span></span>
		</div>
		<div class="bin" id="bin13">
			<span></span>
		</div>

Now, we need to give them some styling: we can make them look like bins or slots by giving them a left, right and bottom border. We can also make them have a fixed width, say 70px (the px here doesn’t mean pixels in definition, but 1px in your style does approximately equal one pixel on your screen).

We can also make them have a fixed height. To do all of this, we need a <style> tag in our <head> section.

<style>
.bin{
				width: 70px;
				height: 900px;
				border-left: 3px solid black;
				border-right: 3px solid black;
				border-bottom: 3px solid black;
				
			}
</style>

Now, we also need to position our bins and make them not overflow. As we’ll be using the * sign to symbolize a bean, to prevent them from overflowing, we can just tell our browser to break the ‘word’ where it’s necessary:

<style>
.bin{
				width: 70px;
				height: 900px;
				border-left: 3px solid black;
				border-right: 3px solid black;
				border-bottom: 3px solid black;
				display: inline-block;
				position: fixed;
				bottom: 3px;
				word-break: break-all;
			}
</style>

Furthermore, to position our bins properly, we need to give them a position. We can do this by specifying the left property (how far away from the left border of the screen they are) in the style tag:

#bin1{
				left: 0;
			}
			#bin2{
				left: 80px;
			}
			#bin3{
				left: 160px;
			}
			#bin4{
				left: 240px;
			}
			#bin5{
				left: 320px;
			}
			#bin6{
				left: 400px;
			}
			#bin7{
				left: 480px;
			}
			#bin8{
				left: 560px;
			}
			#bin9{
				left: 640px;
			}
			#bin10{
				left: 720px;
			}
			#bin11{
				left: 800px;
			}
			#bin12{
				left: 880px;
			}
			#bin13{
				left: 960px;
			}

Finally, we need to make the beans fall to the bottom, as we’re not trying to build a simulation in zero-gravity 🙂 To do this, put this into your style tag – this code positions the span element to the bottom of the bin:

.bin span{
				position: absolute;
			    bottom: 0;
			    right: 0;
			}

Now that we have bins, we need to build a simple interface for controlling our simulation where we could specify the number of beans we’ll be dropping and run the simulation at the click of a button.

To do this, we’ll place a div called interface with some input elements. The h1 element is a title for our page, while label and input are very self-descriptive when you look at their attributes. We use br to create a line break.

<div class="interface">
			<h1>A simple bean machine</h1>
			<label for="numberOfBeans">Number of beans</label>
			<input type="number" value="1" id="numberOfBeans">
			<br>
			<input type="button" onclick="dropBeans()" value="Drop beans">
		</div>

The important part here is the onclick=”dropBeans()” attribute on the button, which tells the browser to run our simulation (we’ll write a function called dropBeans later) when the button is clicked.

To position our interface properly and to give it a bit of a better look, we’ll add this to our style – giving the whole document a nicer font and positioning the interface at a fixed position, 20px from the top and 1080px from the left side of the screen.

body{
				font-family: 'Helvetica', 'Roboto', 'Arial', sans-serif;
			}
			.interface{
				position: fixed;
				top: 20px;
				left: 1080px;
			}

Our interface should look like this now:

We’re finally done with building our interface: now we have to write the simulation itself.

Simulating the beans

As I mentioned before, we’ll be using JavaScript – a programming language built into browsers – to simulate the bean machine. To start writing JavaScript code, open a script tag in the head section like so:

<script>
</script>

We’ll start by building a simple function that drops the specified number of beans into their bins – the bin that the bean will be dropped in will depend on the outcome of another function.

We need to take the value of the form – we can access it by using document.querySelector(‘#numberOfBeans’).value (which basically says ‘find the element with the id numberOfBeans in the document and return its value’) – and run a loop that places that many beans into the bins.

To place a bean into a bin, we’ll just put a * in the span element in it.

We can access the internal content of an element using document.querySelector(selector).innerHTML and we can use the children property to seek a specific child.

As the span element is the only child of a bin, we can use document.querySelector(‘#bin3’).children[0].innerHTML to access its internal content, which we can assign a value to.

Of course, we can use a result of a calculation for the selector, so document.querySelector(‘#bin’+binToDropIn).children[0].innerHTML also makes sense.

To determine which bean gets into which bin, we’ll write another function called selectBin later on, but if you want to test if this works, make dropIn equal a number.

	function dropBeans(){
				for(var i=0;i<document.querySelector('#numberOfBeans').value;i++){
					var dropIn = selectBin();
					document.querySelector('#bin'+dropIn).children[0].innerHTML = document.querySelector('#bin'+dropIn).children[0].innerHTML + '*';
				}
			}

Now we need to actually write our selectBin function.

To do justice to the machine, we need to replicate the way it operates, not its end result.

In the machine itself, each bean hits a peg 12 times, each time going left or right. In our case, we’ll be doing that by starting at the leftmost bin (as position=1 would suggest) and run a loop 12 times that can either move the bean right or make it stay at that same place.

To determine that, we’re using Math.random(), a function that gives you a random number in the [0,1] range and making it give us either 0 or 1, which we’ll add up to the position. We make it give us a whole number by truncating it, and we normalise its values by adding 0.5 to it – we’re basically rounding.

function selectBin(){
				var position=1;
				for(var k=0;k<12;k++){
					position+=Math.trunc((Math.random()+0.5));
				}
				return position;
			}

With this written, we’re done. Our machine works!

You can try it out here, but make sure you’re on a computer.

If you want, you can also find my source code here.

So… why?

By dropping thousands of beans, we can see that their distribution really does look a lot like the normal distribution:

Why does this happen? And why is it important? To answer these questions, we need to understand what the normal distribution (also called a Gaussian distribution) even is.

If you try to look it up on Wikipedia, you’ll encounter some very mathematical definitions, but in summary, a distribution is a probability function that describes how the values of a variable are distributed. However, the normal distribution is a bit more interesting than that: it’s a symmetric distribution where probabilities are highest around the central peak (meaning most of the observed variable values occur in that interval) and the probabilities for values further away from the peak (the mean value) decline equally in both directions. Both extremes have almost the same, albeit low, probability. In layman’s terms, this means that the average values are the most likely ones, while those that deviate a lot from that average are the least likely ones.

The normal distribution shows up a lot in the real world, with the usual examples of normal distribution being heights of people, blood pressure and errors in measurement. Some tests are even designed to be graded using the normal distribution (with around the same number of people failing the test and having the highest grade).

So… why does it show up here, in a scenario where variables should be random?

Well, the first thing to note is that while the bin the bean lands in is randomly determined, it isn’t truly random, as some bins have a higher probability to be hit than others. This is determined by the number of paths a bean can take to land in a certain bin, which I illustrated earlier: there is only one path to the leftmost or the rightmost bin, but there are many more paths to the central bins.

If we use n to denote the number of rows of pegs in a Galton board, the number of paths to the k-th bin on the bottom (counting k from zero) is given by the binomial coefficient n choose k, which equals n! / (k! * (n-k)!).

The values of the binomial coefficients are shown on the left in Pascal’s triangle and represent the numbers of paths a bean can take to land in a bin for a board with 8 bins and 7 rows of pegs.

However, this still doesn’t fully explain the phenomenon: these variables are still at least somewhat random – so why are they normally distributed?

There’s a very important theorem in mathematics called the central limit theorem which states that under certain (fairly common) conditions, the sum of many random variables (such as these!) will have an approximately normal distribution. This exact theorem is what Galton tried to demonstrate with his machine: the number of beans in a bin is random, but as the number of discrete events (dropped beans) increases, the function begins to resemble a normal distribution!

While the reasons for this are mathematically demanding, the simplified version is that when you have a certain expected (most probable) value and repeat the experiment enough times, most outcomes will converge around that value, while others will spread out evenly due to the large number of experiments.

And I get it, these mathematical results sound very boring: but they’re actually very important for our understanding of the world around us – giving sense to things that seem random, such as people’s heights or coin flips, making them more understandable and predictable. In the end, these theorems can be applied to the real world, making sense of the wilderness around us, which Sir Francis Galton describes himself:

I know of scarcely anything so apt to impress the imagination as the wonderful form of cosmic order expressed by the Law of Frequency of Error.

The law would have been personified by the Greeks and deified, if they had known of it. It reigns with serenity and in complete self-effacement, amidst the wildest confusion. The huger the mob, and the greater the apparent anarchy, the more perfect is its sway.

It is the supreme law of Unreason. Whenever a large sample of chaotic elements are taken in hand and marshalled in the order of their magnitude, an unsuspected and most beautiful form of regularity proves to have been latent all along.

Sir Francis Galton on the Central Limit Theorem

Can you think of some occurences of the natural distribution or an interesting application of this theorem? Try playing around with our simulation to see what happens when you drop a small number of beans vs. a large number of them for a better illustration of this theorem. If you have any questions and if you’ve found this to be interesting, please let us know in the comments below.

By Mario Borna Mjertan

Mario Borna Mjertan is a student of mathematics at the Department of Mathematics, Faculty of Science, University of Zagreb. He serves as Project Director for Znanstvenik u meni! and actively works on science popularisation projects such as ZUM, S3++ and other projects.

Leave a Reply

Your email address will not be published. Required fields are marked *