The hoard of clutter within someone's memories

Some of it is useful

Any AI version of Marie Kondo should just give up!

So, in the beginning of mankind, there was a decision to be made. And no-one could agree. And then someone thought that the gods of those very early people could somehow guide them. This first priest of those first gods looked around and then found a flat rock. The priest then marked both sides with different markings and proclaimed to the others that the gods could communicate by affecting the outcome of how the rock landed when flipped into the air. The rock was flipped, all watched, and the rock landed in the dust. The first priest announced that 'The gods have spoken!' and the result was there for all to see. And the first steps of progress, good and bad, were made by that first tribe.

Admitted, the above description may be a touch overdramatic but such oracles have existed for as long as humanity. The I Ching is still used by many now for such purposes. But many aspects of modern maths and computing still have this dependence of two different desrete states. Heads or tails, yes or no, 1 or 0 are all the basis of so many things that permeate the modern world. A computer should be able to emulate that, right? Well.......no, not that well but we can get close.

Even the smaller modern version of flipping a coin in the real world is not perfectly random. There exists inherent bias based on how the coin is set on the hand before the flip, how hard it is flipped and how the catch is made. A true random result for a large number of coin flips would show close to 50% for one side and 50% the other. In real life the ratio is closer to 51:49. However, for most purposes, we don't need to perfectly emulate life. We just need to get close enough.

So if a computer can't replicate a simple action with perfect accuracy, then why do it? Well, what a computer can do is emulate such actions much faster. Doing 100 coin flips takes up a lot of time, 1000 or 10000 much more so. And nobody wants the job of flipping any object that many times. I suppose the youth of today would just ask ChatGPT but one's own program is quite easy to do. And the program still works on any old PC or laptop even if CloudFlare or AWS goes down. So it's always worth knowing how to do something like this.

On a computer, there are already in-built pseudo-random number generators designed to produce a range of integers or floats etc. As it is desired to only have two outcomes, the easiest way for design to to check if the result is odd or even as this splits any range of integers into two parts. An odd or even number will decide whether the result is 'heads' or 'tails'.

So, with such justification, let's begin.

Bash examples

There are two ways to obtain a random variable in Bash, $RANDOM and $SRANDOM. The difference is that $RANDOM produces a 16-bit integer and thus has a lower range of integers. $SRANDOM produces 32-bit integers. Both ranges are large enough for this exercise. To test this out, open a terminal and type the following:

echo $RANDOM

The result should be a random integer produced on the screen. Do this for a few times to get an idea of the range of numbers that can be produced and then repeat the exercise replacing $RANDOM with $SRANDOM. The latter should produce quite a few numbers that are much larger.

Now you are ready to write the first Bash script in a text editor. Open a text editor and type the following, saving the file as Rand1.sh. Or use a different name of your choosing as long as it end with'.sh'.

#! /usr/bin/env bash
VALUE=$RANDOM
if ((VALUE%2==0)); then
    echo "Heads!"
else
    echo "Tails!"
fi

Run the code in the terminal a few times and the result will be successive 'Heads!' or 'Tails!' declarations based on the result being odd or even. This is a quick explanation of the code:

  • The first line is the standard line to declare the use of the Bash environment
  • The second line assignes a value to the VALUE variable from $RANDOM
  • The next section is an if statement that starts with an if condition and ends with fi
  • The ((VALUE%2==0)) tests if the random number VALUE modulus 2 is equal to zero, making VALUE even
  • If VALUE is even, then the result will print out 'Heads!' to the screen
  • The else statement will print out 'Tails!' to the screen because the result is not even

And that's it! Use chmod +x to make the file an executable and it is ready to go. Then in the text editor change $RANDOM to $SRANDOM and save it with a different file name, such as Rand2.sh. Two different Bash scripts showing heads or tails. Now the next trick is to place the result into a text file rather than out to the screen. This is done by amending the code as follows:

#! /usr/bin/env bash
VALUE=$RANDOM
if ((VALUE%2==0)); then
    echo "Heads!">output.txt
else
    echo "Tails!">output.txt
fi

The > redirects the output, in this case to a file. If the file does not exist, it is created. If the file does exist, its current contents are wiped and the output is written to the file. If you don't want to erase the current data in the file, then you can append data to that file by using the >> operator, which is what will be done in the next part.

Multiple coin flips using for loops

The current result only produces a single output. The whole advantage of computers is to produce multiple outputs in short time. The easiest way is to add some code that states something like 'repeat this operation for a specific number of times'. This can be done using a for loop.

#! /usr/bin/env bash
VALUE=$RANDOM
if ((VALUE%2==0)); then
    echo "Heads!">output.txt
else
    echo "Tails!">output.txt
fi

for i in $(seq 1 999);
do
VALUE=$RANDOM
if ((VALUE%2==0)); then
    echo "Heads!">>output.txt
else
    echo "Tails!">>output.txt
fi
done

The for loop starts with a for statement. In this case, the variable i is given a value from 1 to 999. This is followed by some code surrounded by do and done. This states that the code between these points should be executed by the number of times defined in the for statement. The code between do and done is almost the same code as used before (use copy and paste, don't type everything out again). The only difference is the use of the >> operator to append the output to a file rather than erasing the current contents. The result is a file containing the result of 1000 coin flips. Easy!

Using C

The great thing about doing something in Bash, is that there is no need to compile the code. Just making it executable using the command chmod +x somefilename.h, where somefilename is replaced with what you named your file, is all that is required. Bash is great when it can be used but there are times that Bash will not do. Bash is designed for administration and certain functions, like mathematical operations, are limited to the basics. Also, Bash is an interpreted language and code going through an interpreter is going to be slower than code compiled on the machine. Thus there are going to be times where other types of code is necessary. So let's try an example using C.

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main()
{
uint32_t x=arc4random();
if(x%2==0)
    printf("Heads!\n");
else
    printf("Tails!\n");
return 0;
}

This example uses the arc4random() to generate a random 32-bit integer. This program requires 3 header files, the first one is standard for any programs requiring input or output. The other two are required for arc4random() and its output of a integer guaranteed to be 32 bits in size (uint32_t).

Save the file as coinout.c, or something else if you want as long as it ends with .c. There is no need to create an object file when compiling this small program, if using gcc, compile it with the following:

gcc coinout.c -o cointoss

A file called cointoss should be produced. If you are already in the directory, just type cointoss and the result will either be 'Heads!' or 'Tails!'.

It is possible to create a C program that writes to a file but it is easier to write a Bash script that executes this C program. Bash is a great way to quickly emulates commands types in the terminal. In a text editor, create the following file called multicointoss.sh in the same directory as your cointoss program:

#! /usr/bin/env bash
./cointoss>output.txt
for i in $(seq 1 999);
do
    ./ct1>>output.txt
done

The above result executes the cointoss program 1000 times with the output going to a text file. The next question is, how do they compare?

I ran all of these examples three times with 1000 outputs and compared their average deviation from a 50:50 output. Thus a 1% deviation from this point would result in a 51:49 ratio between the two outcomes. Here are the results:

  • Bash with $RANDOM: 1.1%
  • Bash with $$RANDOM: 2.07%
  • C program: 1.77%

Just as important though, is the single example with maximum deviation. Here are the results of that:

  • Bash with $RANDOM: 2.3%
  • Bash with $$RANDOM: 3.6%
  • C program: 3.6%

So the Bash script with the 16-bit integer has the smallest maximum and average deviation from the 50:50 mark.

Given that in real life the result would be close to 51:49, all of these programs are OK for simple rough-and-ready results but the key seems to be in this instance that simpler is better. Having a smaller range of smaller numbers seems to be beneficial.

About

This is where I place the very basic notes on programming from those starting at the very beginning using Linux or similar operating systems. It's set up to be understood by everyone. If you have an opinion as to how this page is done, then you are already and intermediate or advanced programmer and I don't care!