welcome to college football saturday

For the past five years Jon Bois has tweeted “welcome to college football saturday” during college football saturdays.

This tradition ended last week, here are some graphs to commemorate it


Figure 1: When Jon tweets


Figure 2: How the public responds

This was done using tweepy to scrape the last 3.2k tweets from Jon


Where in the Square?

Another week, another riddler. This week’s was a puzzle I’d submitted:


You are given an empty 4-by-4 square and one marker. You can color in the individual squares or leave them untouched. After you color as many or as few squares as you’d like, I will secretly cut out a 2-by-2 piece of it and then show it to you without rotating it. You then have to tell me where it was (e.g., “top middle” or “bottom right,” etc.) in the original 4-by-4 square.

Can you design a square for which you’ll always know where the piece came from?


For this I brute forced the problem and checked every possible square — turns out there are 6188 correct answers. Here are 150 of them:


And here is the code:

from matplotlib import pyplot as plt
from matplotlib.colors import ListedColormap
import numpy as np

def render_square(sq):

def render_squares(total_sqs):

    rows = 10
    cols = 15
    newcmp = ListedColormap(['#F29A8B','#30333A'])
    fig, axes = plt.subplots(nrows=rows, ncols=cols, sharex=True, sharey=True)

    for x in range(cols):
        for y in range(rows):
            axes[y,x].matshow(total_sqs[x*cols + y],cmap=newcmp)

    fig.subplots_adjust(left=0, right=1, top=1, bottom=0, wspace=0.1, hspace=0.1)

def check_if_locatable(source):
    squares = set()










    if len(squares) == 9: return True

def check_all_squares():
    total_sq = 0
    total_sqs = []
    sq_size = 4
    sq_cells = sq_size**2
    bin_max = 2**sq_cells
    for i in range(bin_max):
        sq = []
        sq_vals = str(bin(i)[2:]).zfill(sq_cells)
        for row in range(sq_size):
            row_val = sq_vals[row*sq_size:(row+1)*sq_size]
            row_val_list = list(row_val)
            for i in range(sq_size): row_val_list[i] = int(row_val_list[i])


        if check_if_locatable(sq):
            total_sq += 1



Pen Plotting

Recently I’ve been into pen plotters – they hit the sweet spot of several venn diagrams: blending hardware & software, engineering & art, and randomness & structure. Basically they are at the convergence of things I enjoy

The process started with a blog post by Tobias Toft, found here. It was broken down in a way I could understand and immediately wanted to get more into.


A recent work

From there I got the hardware: I was able to find my own plotter — an HP 7550A in factory packaging from 1985. Finding cabling was a bit of trial and error but soon I had it talking to the computer


The HP7550A Plotter

The software aspect was trickier. After a year of futzing around someone who made things I liked recommended a video lecture series by Matt DesLauriers, found here. This made the seemingly impossible task look very possible — which made it worth the 40$ cost to me.

After that it was off to the races – I started with different pens, paper, frames and more.


This lets me use standard pens with the HP Plotter



I ended up making an instagram for these works — check it out here

Rock Climbing Tracker

Once upon a time, on youtube I saw a video showing off software like this:


I think its super cool. But the high cost (100 dollars a day) and fact that uses a 2D camera left me wanting to make my own.


With that, here is a demo of what I’ve made. Details after the video


  • Uses Kinect V2.0 Camera
  • Running on a Dell XPS Ultrabook thats ~2 years old
  • Standard lighting



Highlighting Holds:

This is where it highlights the holds, showing in the first few seconds of the video. It uses a grid every five pixels and will stop selecting if the color changes drastically

Tracking People:

This is the wireframe overlayed on me. This is done by Microsoft’s software

Detecting Human -> Hold Collisions:

This is done by tracking the human hand and checking it against the distance (one threshold) and depth (another threshold). If each are met, the hold is marked as “reached” and the color is changed.


Will upload software later — it needs to be refactored / cleaned up

Uploaded here. It still needs to be refactored / cleaned up

Do pitchers throw different pitches to batters that they’ve face more often?

In competitive events the more experience you have against a particular opponent means the more information they have about how you play and vis versa. As this knowledge increases certain tools become more and less valuable.

For example, consider facing a knuckleball pitcher in baseball. Knowing they will throw knuckleballs a majority of the time and not being as familiar with their release motion means sneaking a fastball in can really catch you off guard. Then, as you learn how these pitches look the unexpected fastball becomes more predictable and, therefore, less valuable.

Does the data support this theory?

Sort of – it depends on the pitchers. Here are the pitches thrown to players based on how many pitches total they threw to that batter for pitchers that had notable results:

R.A. Dickey_figure.png

R.A. Dickey seems to reduce the number of fastballs and increase knucklers if hes faced you often


Chris Sale seems to replace four seam fastballs with two seems fastballs with repeat visits


Jake Arrieta uses more sinkers and sliders and less fourseamers and curves

To get this data I took information from PITCHf/x from Brooks Baseball and then used pandas in python to form the graphs. Here is the source code to check out other players

Do you have any insight as to why some pitches scale better? Let me know in the comments below

A Circular Conundrum

Another week, another riddler. This weeks:

From Keith Wynroe, a concise circular conundrum:

If N points are generated at random places on the perimeter of a circle, what is the probability that you can pick a diameter such that all of those points are on only one side of the newly halved circle?

What a cool problem. First, I wanted to restate the problem so it could be evaluated more easily. I came up with finding the maximum difference in angle between two points. If this value is greater than 180 deg then you can draw a diameter in there that would satisfy this criteria.

Now how do we figure out how often this criteria is met? First, lets assume that one point is always at 0 (we can achieve this by rotating our circle). The same point is also at 360 degrees. Then there are N-1 points that will be located on the rest of our circle

For N=3 this would look like:



This is what it may look like after the points are placed. However, before points B & C are placed we have


If we place B & C and both are 180 deg or further from A1 then our layout would pass the test (shown in yellow). This is our first condition for creating a passing circle. For this experiment lets say we don’t and we place B between 0 and 180 degrees and instead get something like this:


Now, if we placing C and its greater than 180 degrees larger than B or less than B it would pass the test (shown in yellow). This is our second condition. Lets again say we don’t place it there and get something like this:


This brings us to our final condition, if all points are 180 deg or greater from A2. In this case they are, so our circle passes the test.

Reviewing: our conditions are

1: All points are 180 deg away from A1.

Probability (1/2)^(N-1)

2: All points are 180 deg away from B.

Probability (1/2)^(N-1)

3: All points are 180 deg away from A2.

Probability (1/2)^(N-1)

Because these are independent we can sum them and get the chance of success as 75 for N = 3. Generalizing, we get:


The only thing that changes with an increased number of points is that there are more “Condition 2″s for each additional point – which gives you the N value on

A FiveThirtyEight Spelling Bee

Another week, another riddler. This weeks:


From Steven Pratt, ordinal bee probability:

You are competing in a spelling bee alongside nine other contestants. You can each spell words perfectly from a certain portion of the dictionary but will misspell any word not in that portion of the book. Specifically, you have 99 percent of the dictionary down cold, and your opponents have 98 percent, 97 percent, 96 percent, and so on down to 90 percent memorized. The bee’s rules are simple: The contestants take turns spelling in some fixed order, which then restarts with the first surviving speller at the end of a round. Miss a word and you’re out, and the last speller standing wins. The bee words are chosen randomly from the dictionary.

First, say the contestants go in decreasing order of their knowledge, so that you go first. What are your chances of winning the spelling bee? Second, say the contestants go in increasing order of knowledge, so that you go last. What are your chances of winning now?


Unfortunately I had to just brute for this one. Due to the nature of the problem I couldn’t think of a good way to put this into any sort of an equation. Here are the results:



import random
import matplotlib.pyplot as plt
import matplotlib.patches as patches

def play_round(player):
    return random.randint(0,99) > player

def play_game():
    players = [1 for i in range(1,11)]
    players_left = sum(players)

    player_up = 0
    while players_left > 1:
        if players[player_up]:
            if not play_round(player_up):
                players[player_up] = 0
        player_up = (player_up + 1) % len(players)
        players_left = sum(players)
    return players.index(1)

#Run cycles

winners = [0 for i in range(1,11)]
for cycles in range(100000):
    winner = play_game()
    winners[winner] += 1
    if (cycles%10000 == 0): print(winners)

## Configure for plotting

percents = [float(winners[i])/cycles for i in range(len(winners))]
players_for_plotting = [99-i for i in range(10)]

fig = plt.figure()
ax1 = fig.add_subplot(111)

ax1.scatter(players_for_plotting,old_percents, color='purple',label ='best player first')
plt.ylabel('% wins')
plt.title('538 Spelling Bee Expected Results')
plt.legend(loc = 1)