The Nature of Code

Exercises from the book The Nature of Code by Daniel Shiffman. The animations are constructed using the p5.js library (reference documents for p5). At the moment, all the HTML, CSS, and JavaScript is hand-rolled. The page is deployed to S3 via the AWS command line tool invoked from a Makefile, and served by CloudFront. S3 and CloudFront are configured with Terraform.

Chapter 0 - Randomness

The first chapter Randomness introduces the concept of random numbers with simple examples such as random walks.

Exercise 0.1: a random walker tending down and right

Create a random walker that has a greater tendency to move down and to the right. (The solution follows in the next section.)

Steps for the random walk were biased towards the right at 26%, down at 26%, up and left at 24% each. Just this slight bias results in a clear trend, can be seen by letting the animation run for a few minutes.

The step size is 1 pixel, and the walker wraps around the region defined by the canvas (cream colored panel above).

Exercise 0.2: drawing Aces

What is the probability of drawing two aces in a row from a deck of 52 cards, if you reshuffle your first draw back into the deck before making your second draw? What would that probability be if you didn’t reshuffle after your first draw?

This is very straightforward undergraduate probability.

  1. With replacement. First draw: \(\frac{4}{52}\); second draw: \(\frac{4}{52}\). Probability of drawing two aces in a row: $$\frac{4}{52} \times \frac{4}{52} = \frac{16}{2704} = \frac{1}{169}$$
  2. Without replacement, First draw: \(\frac{4}{52}\); second draw: \(\frac{3}{51}\). Probability of drawing two aces in a row: $$\frac{4}{52} \times \frac{3}{51} = \frac{12}{2652} = \frac{1}{221}$$

Again, nothing new here, but a fun way to add a bit of MathJax.

Exercise 0.3: random walker with 4 choices

Create a random walker with dynamic probabilities. For example, can you give it a 50 percent chance of moving in the direction of the mouse? Remember, you can use mouseX and mouseY to get the current mouse position in p5.js!

There is some sublety to this exercise with respect to how "50%" is interpreted. Because the canvas tracks the position in floating point numbers and anti-aliases on rendering, we approximate the probabilities be defining two separate stepping functions. The first function will step in one of the 4 cardinal directions with probability 0.5, the second will step along a vector towards the current cursor position.

Technically, there is some overlap in probabilities when the cursor is perfectly aligned along the cardinal directions. This slightly increases the probability of stepping in that direction.

Another question: should the mouse coordinates be confined to the canvas, or be anywhere on the page?

The walker below will step along the cursor position vector with probability 0.1. The 50% probability is boring and sends the walker straight to the cursor. If it reaches the cursor it will halt and not restart.

Right now, the walker wraps around the canvas. More could be done, for example, restarting the walker after it reaches the cursor.

Exercise 0.4: paint spatters

Direct link.
Consider a simulation of paint splatter drawn as a collection of colored dots. Most of the paint clusters around a central position, but some dots splatter out toward the edges. Can you use a normal distribution of random numbers to generate the positions of the dots? Can you also use a normal distribution of random numbers to generate a color palette? Try creating a slider to adjust the standard deviation.

This is several questions in one. We'll spatter some paint first.

By definition, a Gaussian, or normal distribution is the continuous probability distribution $$ f(x \,|\, \mu, \sigma) = \frac{1}{\sigma\sqrt{2\pi}} e^{-\frac{1}{2}\left(\frac{(x-\mu)}{\sigma}\right)^2} $$ where \(\mu\) is the mean and \(\sigma\) is the standard deviation. With mean \(\mu = 0\) and and standard deviation \(\sigma = 1\), the distribution is the standard normal distribution. P5.js conveniently provides the function randomGaussian() to generate normally distributed random numbers.In the plot below, we set \(\mu = 0\) and \(\sigma = 3\) to produce interesting patterns.

Color controls TBD.

Exercise 0.5: Gaussian random walk

Direct link.
A Gaussian random walk is defined as one in which the step size (how far the object moves in a given direction) is generated with a normal distribution. Implement this variation of the Walker class.

In the plot below, we set \(\mu = 0\) and \(\sigma = 3\) to produce interesting patterns. Two walkers are defined, one in green, the other in blue.

A fun extension would be providing controls to adjust the mean and standard deviation. Values are wrapped around all edges so that the walker always stays within a region bounded by the canvas.

Exercise 0.6: qualified random values

Direct link.
Use a custom probability distribution to vary the size of the random walker’s steps. The step size can be determined by influencing the range of values picked with a qualifying random value. Can you map the probability to a quadratic function by making the likelihood that a value is picked equal to the value squared?

Setting a "probability to a quadratic function" seems vague to me. The difficulty is with respect to "equal to the value squared". With floating point numbers, getting equality is difficult. Drawing a bar chart with this condition (not shown) accepted values less than a square of a random number uniformly distributed between 0 and 1. We'll do the same here and set the step range to the returned square value.

Values are wrapped around all edges so that the walker always stays within a region bounded by the canvas. It might be interesting to plot the step sizes as well.

Here's an implementation of a bar graph with quadratic selection:

Exercise 0.7: Perlin noise

Direct link.
In the Perlin noise random walker, the result of the noise() function is mapped directly to the walker’s position. Create a random walker, but map the result of the noise() function to the walker’s step size instead.

Perlin noise provides a way to generate smpoth random values. The walker below demonstrates the effect. The general idea is that the next value depends on the current value in some way. The result is that the walker has much longer "streaks" moving in a single direction.

This was straightforward, and leveraged the example code provided by the book. Using discs instead of points results in an interesting vusual effect. The built-in noise() function constrained the values to the region, so there is no need to wrap positions

Just for fun, here is a smooth time series using noise:

This sort of function is useful for application load testing. It's smoother than random values, more random than a sine wave, and is more plausible then either for simulating user traffic to a web application.

Exercise 0.8 parameterizing noise details

Play with color, noiseDetail(), and the rate at which xoff and yoff are incremented to achieve different visual effects.

Exercises 0.8 and 0.9 are combined in the example below.

This Pixel arrays at Coding Train video was really helpful in understanding how the rendering works.

Some controls for Perlin generation would be interesting.

Exercise 0.10 render 2D noise as elevations

Use the noise values as the elevations of a landscape.

We'll replicate the example from the book.

This exercise was substantially more involved than any of the previous, requiring P5 concepts for rendering strips and WebGL, then integrating Perlin noise for elevations. It's also good to remember that rotations are not commutative.


And that is a wrap for Chapter 0 of Nature of Code. You may also be interested in Chapter 1: Vectors


dool.in