# Hacking Pi with PowerShell

Friday, 15 March 2013

A Facebook friend recently posted a cool picture from the Pi chain that California Institute of Technology created on Pi Day, 2013:

After seeing that, you might wonder – “Where in Pi is that?” And, “What number does each colour represent?”

PowerShell can help here – its support for regular expressions let you find all kinds of stuff in text. But where do you find the text of Pi? Bing, of course. After copy + pasting the first 100,000 digits of Pi from into a text file, you now have some text to work with.

If you want to see some of the things you can do with Regular Expressions, check out this quick reference in the PowerShell Cookbook: http://www.powershellcookbook.com/recipe/qAxK/appendix-b-regular-expression-reference.

If you assume that the chain links are 4 inches wide, 100,000 digits will go for almost 7 miles. It’s doubtful that they made a chain longer than that, so using 100,000 digits is pretty safe.

PS C:\Users\Lee> $page = iwr http://www.geom.uiuc.edu/~huberty/math5337/groupe/digits.html

PS C:\Users\Lee> $null = "$page" -match ‘(\d|\.|\n){5,}’

PS C:\Users\Lee> $digits = $matches[0] -replace "\s",""

PS C:\Users\Lee> -join $digits[0..100]

3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067

Now, since we know that each colour represents a different number, and those colours appear in a certain pattern, we can look in $digits for that pattern.

What we see – 15 colours:

Yellow, Yellow, Blue, (Orange?) Green, Blue, Yellow, (Red?), Purple, Purple, Orange, Pink, Red, Yellow, Yellow

Now, here’s the regular expression to match 15 different characters (15 dots):

$digits –match “…………….”

It does, of course (I hear Pi goes on for a while), so let’s get more specific.

Regular expressions let you group characters by surrounding them in parenthesis:

$digits –match “(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)”

And also give them names. Let’s name the first group:

$digits –match “(?<Yellow>.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)”

And rather than using the “dot” to match a specific character, you can refer to a previous group – by either name or number. Here’s the chunk that names the first character “Yellow”, and then says that the second character must be the same as the first:

$regex = "(?<Yellow>.)(\k<Yellow>)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)"

$digits | Select-String $regex -AllMatches | % { $_.Matches.Value } | Select -First 1

33832795028841

This is how we’ll “crack the code” – find patterns where the digits are the same at the same place the colours are the same. Since most of the colours aren’t repeated, they don’t help us much and we can ignore them for now. Let’s expand our example:

$regex = "(?<Yellow>.)(\k<Yellow>)" +

"(?<Blue>.)(?<Orangey>.)(<?Green>.)(\k<Blue>)(\k<Yellow>)" +

"(?<Pinkish>.)(?<Purple>.)(\k<Purple>)(?<Orange>.)(?<Pink>.)" +

"(?<Red>.)(\k<Yellow>)(\k<Yellow>)"

$digits | Select-String $regex -AllMatches | % { $_.Matches.Value } | sortPS >

Hrrm. No results.

Let’s relax some constraints. Maybe some colours we thought matched really didn’t? With my man eyes to the rescue, those blues look subtly different.

$regex = "(?<Yellow>.)(\k<Yellow>)" +

"(?<Blue>.)(?<Orangey>.)(<?Green>.)(?<Blue2>.)(\k<Yellow>)" +

"(?<Pinkish>.)(?<Purple>.)(\k<Purple>)(?<Orange>.)(?<Pink>.)" +

"(?<Red>.)(\k<Yellow>)(\k<Yellow>)"

$digits | Select-String $regex -AllMatches | % { $_.Matches.Value } | sort

PS >

Grr! No results again.

Maybe the yellows are different? There are three groups. The first group of two is certainly the same colour. The last group of two is certainly the same colour. But maybe those groups are different yellows. Lets see – call the other ones Yellow2 and Yellow3:

$regex = "(?<Yellow>.)(\k<Yellow>)" +

"(?<Blue>.)(?<Orangey>.)(<?Green>.)(?<Blue2>.)(?<Yellow2>.)" +

"(?<Pinkish>.)(?<Purple>.)(\k<Purple>)(?<Orange>.)(?<Pink>.)" +

"(?<Red>.)(?<Yellow3>.)(\k<Yellow3>)"

$digits | Select-String $regex -AllMatches | % { $_.Matches.Value } | sortPS >

Hmm. This doesn’t seem to be working out so well.

**Brain flash**. Oh wait, this is just a picture. What if it was taken from the other side? The colours would be reversed. Maybe we’re looking at the digits of Pi in the wrong order?

Let’s rewrite the regex since we might actually be looking at:

Yellow, Yellow, Red, Pink, Orange, Purple, Purple, (Red?), Yellow, Blue, (Orange?) Green, Blue, Yellow,Yellow

$regex = "(?<Yellow3>.)(\k<Yellow3>)" +

"(?<Red>.)(?<Pink>.)(?<Orange>.)(?<Purple>.)(\k<Purple>)" +

"(?<Pinkish>.)(?<Yellow2>.)(?<Blue2>.)(?<Green>.)(?<Orangey>.)" +

"(?<Blue>.)(?<Yellow>.)(\k<Yellow>)"

$digits | Select-String $regex -AllMatches | % { $_.Matches.Value } | sort000139962344455

004489917210022

006079992795411

006447771837022

006734420647477

006758838043211

008368842671022

009318804549333

112821107094422(…)

Bingo!

That’s a lot of options, so let’s add back in some things that we are more sure of – specifically, those yellows:

$regex = "(?<Yellow3>.)(\k<Yellow3>)" +

"(?<Red>.)(?<Pink>.)(?<Orange>.)(?<Purple>.)(\k<Purple>)" +

"(?<Pinkish>.)(?<Yellow3>.)(?<Blue2>.)(?<Green>.)(?<Orangey>.)" +

"(?<Blue>.)(?<Yellow2>.)(\k<Yellow2>)"

$digits | Select-String $regex -AllMatches | % { $_.Matches.Value } | sort000139962344455

004489917210022

006079992795411

006447771837022

006734420647477

006758838043211

008368842671022

009318804549333

112821107094422

113829928776911(…)

But that first yellow has a zero. Maybe that’s a hint?

$regex = "(?<Yellow3>0)(\k<Yellow3>)" +

"(?<Red>.)(?<Pink>.)(?<Orange>.)(?<Purple>.)(\k<Purple>)" +

"(?<Pinkish>.)(?<Yellow3>.)(?<Blue2>.)(?<Green>.)(?<Orangey>.)" +

"(?<Blue>.)(?<Yellow2>.)(\k<Yellow2>)"

$digits | Select-String $regex -AllMatches | % { $_.Matches.Value } | sort000139962344455

004489917210022

006079992795411

006447771837022

006734420647477

006758838043211

008368842671022

009318804549333

Not very many, so we’re getting closer. Let’s take a look at the patterns and rule out the ones that don’t make sense:

000139962344455 # No, triple start digit

004489917210022 # No, second digits doubled

006079992795411 # No, has another zero ("Yellow") on the fourth digit

006447771837022 # No, has another doubling right after the red

006734420647477 # No, has colour four of colour #4, four of colour #7

006758838043211 # No, 8 means purple, and has another purple in the middle

008368842671022 # No, has another zero ("Yellow") where we thought Blue was

009318804549333 # No, has a tripled final colour

Well, evidently none of them make sense. This is truly confusing. Maybe the numbers happen after 100,000 digits of Pi?

Taking a different approach, it turns out that the original California Institute of Technology page shows a few pictures where there are numbers drawn on the links. Could we use those for a key?

Let’s try this again from the start. The pictures tell us:

0 = Yellow

1 = Pink

2 = Goldenrod

3 = Green

4 = ?

5 = Light Blue

6 = Orange

7 = Purple

8 = ?

9 = Dark Blue

Wait. There’s a *Goldenrod*?

This might help. Let’s do this match against the left-to-right version:

Yellow, Yellow, Blue, (Orange?) Green, Blue, Yellow, (Red?), Purple, Purple, Orange, Pink, Red, Yellow, Yellow

We can now substitute some numbers into the regex. Yellow and Goldenrod are pretty close, so let’s use Regex Alteration (a|b) to let it select either. The light blue is pretty clear, so let’s call that out specifically:

$regex = "(0|2)(0|2)5..5…….(0|2)(0|2)"

$digits | Select-String $regex -AllMatches | % { $_.Matches.Value } | sort225695968815920

Wow! It seems like we have a match!

Godenrod, Goldenrod, Light Blue, Orange, Dark Blue, Blue, Dark Blue, …

But there are two problems:

- It implies that either 9 is Green, or that the picture showing Green is actually Dark Blue
- It says that the colour before the second blue is the same as the colour after it. That’s not the case.

Maybe they messed up assigning colours? If you follow the colour chart through further, there are almost a dozen more mistakes. Let’s go back to the big brain flash, and reverse the regex.

$regex = "………5..5(0|2)(0|2)"

$digits | Select-String $regex -AllMatches | % { $_.Matches.Value } | sort005476022525520

008169980536520

020695124539500

036407573587502

048466277504500

068006422512520

090988702550520

101024365553522(…)

Tons of matches again. Let’s get more specific with those yellows:

$regex = "(0|2)(0|2)……(0|2)5..5(0|2)(0|2)"

$digits | Select-String $regex -AllMatches | % { $_.Matches.Value } | sort005476022525520

008169980536520

Much better. Apply the process of elimination again:

005476022525520 ## Says that the red is colour 5, but also that orange and light blue are too.

008169980536520 ## Seems legit

One was way off, the other one seemed legit. If we apply our colour key, we get:

Yellow, Yellow, ?, Pink, Orange, Dark Blue, Dark Blue, Red, Yellow, Light Blue, Green, Orange, Light Blue, Goldenrod, Yellow

That seems very reasonable. The unknown colour (8) is evidently red. The two that we thought were purple were either actually dark blue, or the assembly person made a mistake. “Pinkish” was red in the sunlight. The last two yellows were actually not two yellows – they were one Goldenrod, and then one Yellow. Or the person putting them together made a mistake.

- Now, we can get smart. How far along were they on the chain?

$digits.IndexOf("008169980536520")

12309

Going back to our 4-inch estimate (3 of those in a foot), that’s 4103 feet:

PS > 12309/3

4103

Nearly a mile in, or perhaps near the end of the chain (which was evidently about 15,000 links).

## What went wrong in the pattern-based regex?

If you take a look at the final regex we played with, we assumed that the last two were the same colour:

$regex = "(?<Yellow3>0)(\k<Yellow3>)" +

"(?<Red>.)(?<Pink>.)(?<Orange>.)(?<Purple>.)(\k<Purple>)" +

"(?<Pinkish>.)(?<Yellow3>.)(?<Blue2>.)(?<Green>.)(?<Orangey>.)" +

"(?<Blue>.)(?<Yellow2>.)(\k<Yellow2>)"

$digits | Select-String $regex -AllMatches | % { $_.Matches.Value } | sort

If we assume that “Orangey” is actually “Orange”, and say that the final two digits are either Yellow or Goldenrod, then we get the proper result after the process of elimination:

$regex = "(?<Yellow3>0)(\k<Yellow3>)" +

"(?<Red>.)(?<Pink>.)(?<Orange>.)(?<Purple>.)(\k<Purple>)" +

"(?<Pinkish>.)(?<Yellow3>.)(?<Blue2>.)(?<Green>.)(\k<Orange>)" +

"(?<Blue>.)(?<Yellow2>.)(\k<Yellow2>|\k<Yellow3>)"

$digits | Select-String $regex -AllMatches | % { $_.Matches.Value } | sort001502298330798

008169980536520

009743300884990

## Why do I care?

Why not spend some time messing around in Pi?