<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
<title type="text">Hyperbolicity</title>
<generator uri="https://github.com/jekyll/jekyll">Jekyll</generator>
<link rel="self" type="application/atom+xml" href="http://bbischof.com/feed.xml" />
<link rel="alternate" type="text/html" href="http://bbischof.com" />
<updated>2021-03-10T15:44:52+00:00</updated>
<id>http://bbischof.com/</id>
<author>
  <name>Bryan Bischof</name>
  <uri>http://bbischof.com/</uri>
  <email>bryan.bischof@gmail.com</email>
</author>


<entry>
  <title type="html"><![CDATA[Simple smoothing of demand with shelf life]]></title>
  <link rel="alternate" type="text/html" href="http://bbischof.com/blog/a_simple_smoothing_of_demand_with_shelf_life/" />
  <id>http://bbischof.com/blog/a_simple_smoothing_of_demand_with_shelf_life</id>
  <published>2018-10-10T04:00:01+00:00</published>
  <updated>2018-10-10T04:00:01+00:00</updated>
  <author>
    <name>Bryan Bischof</name>
    <uri>http://bbischof.com</uri>
    <email>bryan.bischof@gmail.com</email>
  </author>
  <content type="html">
    &lt;p&gt;A very simple discrete algorithm for smoothing out impulses to a target constant value&lt;/p&gt;

&lt;!-- ^Spoiler Text^ --&gt;

&lt;h1 id=&quot;demand-smoothing&quot;&gt;Demand smoothing&lt;/h1&gt;

&lt;p&gt;Let’s assume you use a lot of toilet paper at your home. Some number of rolls per week(integer rolls). If you buy new packages of toilet paper once a month, let’s figure out a simple algorithm to keep your bathroom well-stocked.&lt;/p&gt;

&lt;h2 id=&quot;roll-up-weekly-data&quot;&gt;Roll up weekly data&lt;/h2&gt;

&lt;p&gt;Each week, we have our usage, but since we’re only buying once every month we need to consider the sum over the weeks inside. Consider M-S weeks, then the months have the following number of Sundays:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;[4,4,4,5,4,4,5,4,5,4,4,5]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We’ll return to this later.&lt;/p&gt;

&lt;h2 id=&quot;available-rolls&quot;&gt;Available rolls&lt;/h2&gt;

&lt;p&gt;We dont want to run out, period. As not-a-risk taker, and someone who occasionally throws parties, I want at least &lt;em&gt;twice as much&lt;/em&gt; TP around as I normally need. Let’s then say whatever my biggest usage per week is, times two, will be my target &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;t&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;minimizing-error&quot;&gt;Minimizing Error&lt;/h2&gt;

&lt;p&gt;Because we have a target for available rolls, our goal throughout the month, is to have our order keep us as close to that value as possible.&lt;/p&gt;

&lt;p&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt;, \(1 ≤ i ≤ 5\) the numbered weeks in the month, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;u_i&lt;/code&gt; the corresponding TP usages. Also assume that before you buy some more TP, you have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;o&lt;/code&gt; the “on shelf” TP from the month before. We’ll be calculating our TP purchase &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We wish to minimize&lt;/p&gt;

&lt;p&gt;\[\mathop{\arg\,\min}\limits_x\left(\sum_i\left(\mid x+o-\sum^i_j u_j -t \mid\right)\right)\]&lt;/p&gt;

&lt;p&gt;This feels like something that should be somewhat easy to minimize, and to a certain extent it is. It relies on a little lemma though:&lt;/p&gt;

&lt;h3 id=&quot;little-lemma&quot;&gt;Little Lemma&lt;/h3&gt;

&lt;p&gt;For a set of numbers &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;S&lt;/code&gt;, and a value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Y&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;\[\mathop{\arg\,\min}\limits_{s \in S}\left(\sum_i\left(\mid S - Y \mid\right)\right) = median\left(S\right)\]&lt;/p&gt;

&lt;p&gt;So let \(Y= x+o-t\), and consider instead, the partial sums \(U_i = \sum^i_j u_j\), then&lt;/p&gt;

&lt;p&gt;\[\mathop{\arg\,\min}\limits_x\left(\sum_i\left(\mid x+o-\sum^i_j u_j -t \mid\right)\right) = \mathop{\arg\,\min}\limits_{U_i}\left(\sum_i\left(\mid U_i - Y \mid\right)\right) = median\left(U_i\right)\]&lt;/p&gt;

&lt;h2 id=&quot;ap-ply-ing-our-algorithm&quot;&gt;Ap-PLY-ing our algorithm&lt;/h2&gt;

&lt;p&gt;To compute a year’s worth of TP purchases, we need now apply the previous. Let’s start by assuming our TP consumption is exactly last years(broken into months):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;weekly_usage = [
  [4,3,2,4,],
  [3,3,2,4,],
  [3,5,3,2,],
  [4,5,3,3,2,],
  [4,3,3,2,],
  [6,4,3,3,],
  [2,7,4,3,3,],
  [4,2,4,3,],
  [3,6,2,4,3,],
  [3,2,11,2,],
  [4,3,7,3,],
  [2,4,3,3,5,],
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we need to send each of these little lists into the median calculator:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;partial_sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;take_median_or_upper_bound_of_partial_sums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;list_of_ints&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;partial_sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;list_of_ints&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:],&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;list_of_ints&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;list_of_ints&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;list_of_ints&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And then we can just run through our weekly usage in blocks of months:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;monthly_purchases&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start_of_month_availability&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;incoming_availability&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;month&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;weekly_usage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;necessary&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;take_median_or_upper_bound_of_partial_sums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;month&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;start_of_month_availability&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;monthly_purchases&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;necessary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;start_of_month_availability&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;necessary&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start_of_month_availability&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;month&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;a-gotcha&quot;&gt;A gotcha&lt;/h3&gt;

&lt;p&gt;If you dont start exactly when you’re buying, every week that passes before you buy needs to be subtracted from the start_of_month_availability to start with:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;start_of_month_availability&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;incoming_availability&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;used_before_first_order&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;example&quot;&gt;Example&lt;/h2&gt;

&lt;p&gt;As an example, with the data above, you can compute the purchase amounts. In this case let’s assume the incoming_availability is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;12&lt;/code&gt; and our target is twice the biggest week’s usage: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;22&lt;/code&gt;, it looks like this:&lt;/p&gt;

&lt;figure&gt;
    &lt;img src=&quot;/images/demand_graph.png&quot; alt=&quot;Graph of ongoing availability of TP&quot; /&gt;
    &lt;figcaption&gt;Available TP vs. our Target&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;purchase: 19
current available: 31
current available: 27
current available: 24
current available: 22
purchase: 12
current available: 30
current available: 27
current available: 24
current available: 22
purchase: 15
current available: 33
current available: 30
current available: 25
current available: 22
purchase: 14
current available: 34
current available: 30
current available: 25
current available: 22
current available: 19
purchase: 15
current available: 32
current available: 28
current available: 25
current available: 22
purchase: 15
current available: 35
current available: 29
current available: 25
current available: 22
purchase: 16
current available: 35
current available: 33
current available: 26
current available: 22
current available: 19
purchase: 16
current available: 32
current available: 28
current available: 26
current available: 22
purchase: 14
current available: 33
current available: 30
current available: 24
current available: 22
current available: 18
purchase: 23
current available: 38
current available: 35
current available: 33
current available: 22
purchase: 16
current available: 36
current available: 32
current available: 29
current available: 22
purchase: 12
current available: 31
current available: 29
current available: 25
current available: 22
current available: 19
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

    &lt;p&gt;&lt;a href=&quot;http://bbischof.com/blog/a_simple_smoothing_of_demand_with_shelf_life/&quot;&gt;Simple smoothing of demand with shelf life&lt;/a&gt; was originally published by Bryan Bischof at &lt;a href=&quot;http://bbischof.com&quot;&gt;Hyperbolicity&lt;/a&gt; on October 10, 2018.&lt;/p&gt;
  </content>
</entry>


<entry>
  <title type="html"><![CDATA[The route to the top 100]]></title>
  <link rel="alternate" type="text/html" href="http://bbischof.com/articles/the-route-to-the-top-100/" />
  <id>http://bbischof.com/articles/the-route-to-the-top-100</id>
  <published>2018-01-01T04:00:01+00:00</published>
  <updated>2018-01-01T04:00:01+00:00</updated>
  <author>
    <name>Bryan Bischof</name>
    <uri>http://bbischof.com</uri>
    <email>bryan.bischof@gmail.com</email>
  </author>
  <content type="html">
    &lt;p&gt;The shortest¹ cycling route that climbs the top 100 climbs in the continental US.&lt;/p&gt;

&lt;!-- ^Spoiler Text^ --&gt;

&lt;h1 id=&quot;the-idea&quot;&gt;The idea&lt;/h1&gt;

&lt;p&gt;A while back, Randal Olson posted a blog post about the &lt;a href=&quot;http://www.randalolson.com/2015/03/08/computing-the-optimal-road-trip-across-the-u-s/&quot;&gt;optimal road trip across the US&lt;/a&gt;. The parameters of his project were to design a car trip that touched all the states, and he used landmarks in each state to make it more interesting.&lt;/p&gt;

&lt;p&gt;Two things really stood out about this to me:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;he open-sourced his notebook that wrapped up some of more annoying API/wrapper stuff and the genetic algorithm&lt;/li&gt;
  &lt;li&gt;he noted that the API accepted a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bike routes&lt;/code&gt; flag!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I was inspired! In addition to a mathy, I’m a serious lover of cycling. My project, was essentially:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Combine the dataset of &lt;a href=&quot;https://www.pjammcycling.com/&quot;&gt;Top 100 road cycling climbs&lt;/a&gt; with Randal Olson’s project to achieve the minimal bike route that includes all these climbs&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Top 100 road climbs is a nice project by &lt;strong&gt;pjammcycling&lt;/strong&gt; that rank the hardest climbs in the US(as defined by Fiets index).&lt;/p&gt;

&lt;p&gt;Note: &lt;em&gt;I wanted this to be a cycling route, no usage of boats allowed. So Hawaii was out. Unfortunately—and somewhat surprisingly, Hawaii has 7 of the top 100 road climbs in the US. Luckily, the list provided 107 climbs, so…&lt;/em&gt;&lt;/p&gt;

&lt;figure&gt;
    &lt;img src=&quot;/images/freebie.gif&quot; alt=&quot;that was a freebie&quot; /&gt;
&lt;/figure&gt;

&lt;h2 id=&quot;a-little-about-the-math&quot;&gt;A little about the math&lt;/h2&gt;

&lt;p&gt;More details are in Randy’s post, but I’ll provide a super short explanation of the idea.&lt;/p&gt;

&lt;p&gt;This is the famous &lt;a href=&quot;https://www.wikiwand.com/en/Travelling_salesman_problem&quot;&gt;Traveling Salesman Problem&lt;/a&gt; which finds the order that minimizes the distance to visit a collection of sites.&lt;/p&gt;

&lt;p&gt;In our case, the starts of the climbs are the sites. We use Google Maps API to find cycling routes between each pair of sites(that’s 10000 measurements).&lt;/p&gt;

&lt;p&gt;Once you have all the pairwise distance it would require &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n!&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;10000!&lt;/code&gt;(this is over &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;35000&lt;/code&gt; digits) different orderings you’d have to try. We use something called a genetic algorithm which picks a random order, changes some and checks if it improves or worsens. After many many iterations it comes to a good, but not necessarily perfect solution¹.&lt;/p&gt;

&lt;h2 id=&quot;some-challenges&quot;&gt;Some challenges&lt;/h2&gt;

&lt;p&gt;Initially, I was going to grab the list of locations names from &lt;strong&gt;pjamm&lt;/strong&gt;, run them through his notebook, and let it crunch. But I was wary that things weren’t going to be easy, because the names of the locations weren’t very accurate.&lt;/p&gt;

&lt;p&gt;My first round yielded a route that the Google Maps visualization API couldn’t plot because many of the locations it couldn’t find anything for. I switched to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(lat, long)&lt;/code&gt; after a few small modifications to his notebook. This worked much better at getting me close to the initial points for each of the climbs.&lt;/p&gt;

&lt;p&gt;Again, the visualization code died on this route. This time, it was a mixture of some bad waypoints, and a few other things:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;the route was longer than the maximum alloted&lt;/li&gt;
  &lt;li&gt;some locations were on roads that are not bike friendly so Google maps disliked this&lt;/li&gt;
  &lt;li&gt;some locations were connected by seasonal roads, so Google maps disliked this &lt;em&gt;(this issue returns later)&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;google-maps-visualizations&quot;&gt;Google Maps visualizations&lt;/h2&gt;

&lt;p&gt;I managed to do some small adjustments and finally get an image for this stage of the visualization, knowing that there was much more to do. I also broke the route up into ten pieces, anticipating the difficulties due to scale.&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;/images/google-maps-image-routepart-01.png&quot; alt=&quot;part 1&quot; /&gt;
  &lt;figcaption&gt;The long first route.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class=&quot;third&quot;&gt;
  &lt;img src=&quot;/images/google-maps-image-routepart-02.png&quot; alt=&quot;part 2&quot; /&gt;
  &lt;img src=&quot;/images/google-maps-image-routepart-03.png&quot; alt=&quot;part 3&quot; /&gt;
  &lt;img src=&quot;/images/google-maps-image-routepart-04.png&quot; alt=&quot;part 4&quot; /&gt;
  &lt;figcaption&gt;Plots of route starts via Google Maps.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure class=&quot;half&quot;&gt;
  &lt;img src=&quot;/images/google-maps-image-routepart-05.png&quot; alt=&quot;part 5&quot; /&gt;
  &lt;img src=&quot;/images/google-maps-image-routepart-06.png&quot; alt=&quot;part 6&quot; /&gt;
&lt;/figure&gt;

&lt;figure class=&quot;half&quot;&gt;
  &lt;img src=&quot;/images/google-maps-image-routepart-07.png&quot; alt=&quot;part 7&quot; /&gt;
  &lt;img src=&quot;/images/google-maps-image-routepart-08.png&quot; alt=&quot;part 8&quot; /&gt;
&lt;/figure&gt;

&lt;figure&gt;
  &lt;img src=&quot;/images/google-maps-image-routepart-09.png&quot; alt=&quot;part 9&quot; /&gt;
&lt;/figure&gt;

&lt;figure&gt;
  &lt;img src=&quot;/images/google-maps-image-routepart-10.png&quot; alt=&quot;part 10&quot; /&gt;
  &lt;figcaption&gt;The last ten.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id=&quot;transitioning-to-an-actual-cycling-route&quot;&gt;Transitioning to an actual cycling route&lt;/h2&gt;

&lt;p&gt;I always wanted this to turn into a cycling route in the end, and the numerous issues with the Google maps visualization made clear that things wouldn’t go smoothly. About this time I came to some scary realizations:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;the data that I had didn’t include the actual climbs, they were simply latitude and longitude of the starting location&lt;/li&gt;
  &lt;li&gt;I didn’t have the Strava segments associated to each of these climbs&lt;/li&gt;
  &lt;li&gt;I couldn’t find a route builder that accepted lists of coordinates to build a route, and Strava doesn’t allow adding waypoints later, or searching by lat/long in their route builder.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point, I took a major step back. The relatively naive approach I was taking had come to an end. I then started working on building more of a decent dataset.&lt;/p&gt;

&lt;h2 id=&quot;the-dataset&quot;&gt;The dataset&lt;/h2&gt;

&lt;p&gt;Until this moment I’d been able to simply copy the table off the front page &lt;em&gt;(Note that the website has changed a bit recently)&lt;/em&gt; , and with some text-editor dexterity, turn it into something that looked like a data set. Now, I knew I needed to do a few things:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;scrape the dataset and make sure it was clean and more easily referenced&lt;/li&gt;
  &lt;li&gt;download the Strava segments for each climb and add the segment number to my dataset&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These were relatively straightforward, here’s how I grabbed the segments:&lt;/p&gt;
&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;1, &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; enum_outputstrings.txt
curl &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://www.pjammcycling.com/1.--mauna-kea---test2.html&quot;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;www.Strava | &lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'BEGIN {FS=&quot;src=&quot;} {for(i=2;i&amp;lt;=NF;i++)print $i}'&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;cut&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; 1 | &lt;span class=&quot;nb&quot;&gt;tr&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\'\&quot;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'s/\/embed$//'&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; enum_outputstrings.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I was feeling good about this and started the next step—which I’ll explain in a minute—before I realized a &lt;em&gt;huge&lt;/em&gt; problem with this.&lt;/p&gt;

&lt;p&gt;If you look closely at how I’m extracting the above, I’m using a few tricks about the order that I download them, to infer the number in the ranking, and then searching that page for where I see the string &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;www.Strava&lt;/code&gt;. Why is this a problem? Because &lt;strong&gt;pjammcycling&lt;/strong&gt; has changed the order without updating the urls… Also, my original code wasn’t clever enough to predict pages with multiple Strava links.&lt;/p&gt;

&lt;p&gt;Both of these meant that this data extract was quite seriously erroneous. This wouldn’t have been particularly awful, had I been using a more sophisticated method for this data extraction. The subtlety really ended up being the killer. I ended up not really updating the shell script, and instead just manually adjusted things, or used some text-editor shenanigans.&lt;/p&gt;

&lt;p&gt;This was the first part of the problem that pushed the timeline way back.&lt;/p&gt;

&lt;h2 id=&quot;plotting-the-route&quot;&gt;Plotting the route&lt;/h2&gt;

&lt;p&gt;I still hadn’t found a solution to either of my plotting problems. So, I thought to myself:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“I’ll buckle down and input all these lat/long by hand”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Luckily, I had the foresight to split them into ten-climb groups. It took about an hour, but I build the original ten routes, by copy-pasting lat/long pairs into &lt;a href=&quot;https://ridewithgps.com&quot;&gt;ridewithGPS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A note about &lt;strong&gt;ridewithGPS&lt;/strong&gt;: I think that I’d more naturally use Strava to build the route, because all of the climbs have the effort data, but &lt;strong&gt;ridewithGPS’&lt;/strong&gt; route tool is hands-down easier to use, and allows for addition of waypoints, splitting, combining, etc. &lt;em&gt;I’m not confident this project would be possible with Strava’s route tool, but doable with &lt;strong&gt;ridewithGPS’&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So now I have ten long routes that connect the starting points of each climb, but I’m a long way from the actual goal. This came after some manual adjustment here and there, where the points were problematic as I previously mentioned.&lt;/p&gt;

&lt;h3 id=&quot;a-brief-aside-about-loops&quot;&gt;A brief aside about loops&lt;/h3&gt;

&lt;p&gt;The final product is not a loop. This is completely intended. The output of the algorithm is a loop. I didn’t really like that, so I decided I would break it. Because I was breaking it, I could choose which pair of points didn’t need connection. Keeping in line with the original goal of the project, I removed the &lt;em&gt;longest distance connection&lt;/em&gt; between any two consecutive points in the optimized path.&lt;/p&gt;

&lt;p&gt;This turned out to be the connection from northwest Wyoming to upstate New York. I arbitrarily decided on the orientation of the route, which mean that upstate New York was the start, and that it would finish miles from the Wyoming/Montana border.&lt;/p&gt;

&lt;h2 id=&quot;drag-on&quot;&gt;Drag on&lt;/h2&gt;

&lt;p&gt;I had a moment of realization as I was finishing up the manual route building of the ten original segments where I thought&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“I’m going to have to drag the path to make all the hill climbs part of this route—that’s going to suck”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It did.&lt;/p&gt;

&lt;p&gt;I used a timer during this project and this part of the project took approximately 8 hrs. This involved:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;downloading a &lt;a href=&quot;https://github.com/cdzombak/OpenList&quot;&gt;chrome extension&lt;/a&gt; that can open lists of urls as tabs&lt;/li&gt;
  &lt;li&gt;using my dataset of Strava segments to visually detail what the routes look like&lt;/li&gt;
  &lt;li&gt;dragging a point just after the starting waypoint to the top of the climb&lt;/li&gt;
  &lt;li&gt;adjusting points in-between to make sure they followed the &lt;em&gt;exact&lt;/em&gt; path as the specified segment&lt;/li&gt;
  &lt;li&gt;fixing some data issues again &lt;em&gt;(yes, there were more at this point, c.f. below)&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;adjusting the route between ends of climbs and starts of next to optimize both: enjoyability of ride, and minimal distance taking into consideration the different location&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This last point was important to me. The genetic algorithm provides a pretty good global solution, but since I was effectively doubling the number of waypoints, and the algorithm never saw the new ones, there was only this human option.&lt;/p&gt;

&lt;p&gt;This process was very challenging, and I had to spread this over a few weeks. In some cases, the route builder seemed &lt;em&gt;insistant&lt;/em&gt; on not following the route I wanted and occasionally would require six or more extra points to force it. Not to mention the incredible frustration of summer roads. The astute reader may realize that we’ve been talking about mountains here, which in some cases, get snowy. In places like Colorado and some in the Sierras, the climb is on a summer road that I for the life of me, could not get &lt;strong&gt;ridewithGPS&lt;/strong&gt; to plot on. However, again we see the flexibility of their tool: you can freehand.&lt;/p&gt;

&lt;p&gt;So yes, dear reader, a few of the climbs are freehanded(poorly I might add).&lt;/p&gt;

&lt;h3 id=&quot;more-data-issues&quot;&gt;More data issues&lt;/h3&gt;

&lt;p&gt;How could there be any data issues left by now? &lt;em&gt;…Sigh…&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In one case, I had apparently deleted a digit in the dataset accidentally. In two cases, the Strava segment listed was no longer listed on Strava. And more! These little issues eat up time and make an already exhausting task feel impossible. Nevertheless, I persisted.&lt;/p&gt;

&lt;h4 id=&quot;explicit-changes-to-the-dataset&quot;&gt;Explicit changes to the dataset&lt;/h4&gt;

&lt;p&gt;Here is a short list of &lt;em&gt;data changes&lt;/em&gt; that I made:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;A few climbs had double Strava segments&lt;/li&gt;
  &lt;li&gt;Three climbs had bad coords for the starts: 44, 61, 62&lt;/li&gt;
  &lt;li&gt;A few had no Strava segment listed, so I went and found some using the &lt;a href=&quot;https://www.Strava.com/segments/explore&quot;&gt;segment explorer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Hwy 21-245-180-198 California&lt;/em&gt;, doesn’t have a Strava route, but there’s a &lt;a href=&quot;https://www.strava.com/segments/14594861&quot;&gt;longer one&lt;/a&gt; that can be used&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Tollhouse Rd&lt;/em&gt; had the wrong route number, it’s actually &lt;a href=&quot;https://www.strava.com/segments/9887218&quot;&gt;9887218&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;The &lt;em&gt;Gibraltar Rd&lt;/em&gt; &lt;a href=&quot;https://www.strava.com/segments/7961219&quot;&gt;segment&lt;/a&gt; has been flagged, so I used the &lt;em&gt;Gibraltar TT&lt;/em&gt; &lt;a href=&quot;https://www.strava.com/segments/634846&quot;&gt;segment&lt;/a&gt;(shorter), but on the top 100 route, it still does the longer version&lt;/li&gt;
  &lt;li&gt;Fixed the &lt;em&gt;Lone Pine to Table Mountain&lt;/em&gt; &lt;a href=&quot;https://www.strava.com/segments/3812372&quot;&gt;segment&lt;/a&gt; to a better one&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;one-for-all&quot;&gt;One for all&lt;/h2&gt;

&lt;p&gt;Now I had ten routes (&lt;a href=&quot;https://ridewithgps.com/routes/26535896&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;https://ridewithgps.com/routes/26535908&quot;&gt;2&lt;/a&gt;, &lt;a href=&quot;https://ridewithgps.com/routes/26535916&quot;&gt;3&lt;/a&gt;, &lt;a href=&quot;https://ridewithgps.com/routes/26535920&quot;&gt;4&lt;/a&gt;, &lt;a href=&quot;https://ridewithgps.com/routes/26535926&quot;&gt;5&lt;/a&gt;, &lt;a href=&quot;https://ridewithgps.com/routes/26535934&quot;&gt;6&lt;/a&gt;, &lt;a href=&quot;https://ridewithgps.com/routes/26535938&quot;&gt;7&lt;/a&gt;, &lt;a href=&quot;https://ridewithgps.com/routes/26535948&quot;&gt;8&lt;/a&gt;, &lt;a href=&quot;https://ridewithgps.com/routes/26535957&quot;&gt;9&lt;/a&gt;, &lt;a href=&quot;https://ridewithgps.com/routes/26535964&quot;&gt;10&lt;/a&gt;), all with ten climbs each. Again, &lt;strong&gt;ridewithGPS&lt;/strong&gt; to the rescue; combining was relatively painless. Although, I’ll admit that it’s a little hard on the browser to have close to 300 waypoints stretched over 14000 miles of route, unsurprisingly.&lt;/p&gt;

&lt;p&gt;💯💯💯 &lt;strong&gt;&lt;a href=&quot;https://ridewithgps.com/routes/26633832&quot;&gt;So I guess, it’s time to show it to you!!!&lt;/a&gt;?&lt;/strong&gt; 💯💯💯&lt;/p&gt;

&lt;p&gt;^^^^^^ Click to explore the interactive route on &lt;strong&gt;ridewithGPS&lt;/strong&gt; ^^^^^^&lt;/p&gt;

&lt;figure&gt;
    &lt;img src=&quot;/images/fullRouteRunthrough.gif&quot; alt=&quot;that was a freebie&quot; /&gt;
&lt;/figure&gt;

&lt;h2 id=&quot;by-the-numbers&quot;&gt;By the numbers&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;100 climbs in the Continental US&lt;/li&gt;
  &lt;li&gt;17 states&lt;/li&gt;
  &lt;li&gt;14235 miles&lt;/li&gt;
  &lt;li&gt;965210 ft of elevation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;some-technical-notes&quot;&gt;Some technical notes&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;a href=&quot;https://github.com/BBischof/top100ClimbsRoute/blob/master/RoutesData.csv&quot;&gt;dataset&lt;/a&gt; was extracted originally in November, 2017. I wont likely be updating the routes.&lt;/li&gt;
  &lt;li&gt;The actual route doesn’t change as the ranking list changes, but, obviously, it will be effected if totally new routes are added.&lt;/li&gt;
  &lt;li&gt;Bear Camp was not in the dataset when the original dataset was built, hence it’s not included. &lt;a href=&quot;https://www.pjammcycling.com/oregon---bear-camp.html&quot;&gt;Here&lt;/a&gt; is the route. It should be in &lt;a href=&quot;https://ridewithgps.com/routes/26535916&quot;&gt;this section&lt;/a&gt; of the route, before you climb &lt;a href=&quot;https://www.pjammcycling.com/91.--mt.-ashland--or.html&quot;&gt;Mt. Ashland&lt;/a&gt; the Strava route for the new Bear Camp is &lt;a href=&quot;https://www.strava.com/segments/7625827&quot;&gt;here&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;As of just yesterday, the &lt;strong&gt;pjammcycling&lt;/strong&gt; website has changed dramatically. Additionally, they’ve expanded to worldwide now 😏.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;next-steps&quot;&gt;Next Steps&lt;/h2&gt;

&lt;p&gt;First, I want to mention an accidental offshoot of this project: &lt;em&gt;maximal sub-routes&lt;/em&gt;. By this I mean, “what are some sections of this route which maximize the elevation/mileage trade-off?” These are things that you could consider turning into crazy Gran-Fondos like the &lt;a href=&quot;http://www.caltriplecrown.com/&quot;&gt;California Triple Crown series&lt;/a&gt; which are hard-as-nails double centuries. There are some obvious ones in this data-set, and some manual inspection can find some cute little things like Mile 310-510 in the &lt;a href=&quot;https://ridewithgps.com/routes/26535920&quot;&gt;4th route&lt;/a&gt; which contains almost 30k climbing on six of the top 100 climbs! &lt;em&gt;(&lt;a href=&quot;http://www.highrouleur.cc/&quot;&gt;HRS I’m looking at you here!&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;figure&gt;
    &lt;img src=&quot;/images/SierrasHardDoubleCentury.png&quot; alt=&quot;a toughie&quot; /&gt;
&lt;/figure&gt;

&lt;p&gt;I’ll be following this post up with some fun dives into snippets like the above.&lt;/p&gt;

&lt;p&gt;Finally, I want to mention that this project, believe it or not, is part one. To keep the mystery alive, I’ll only mention that part two is to compute the &lt;em&gt;Best of the Top 100&lt;/em&gt;, and more generally a &lt;strong&gt;StraVaELO…&lt;/strong&gt;&lt;/p&gt;


    &lt;p&gt;&lt;a href=&quot;http://bbischof.com/articles/the-route-to-the-top-100/&quot;&gt;The route to the top 100&lt;/a&gt; was originally published by Bryan Bischof at &lt;a href=&quot;http://bbischof.com&quot;&gt;Hyperbolicity&lt;/a&gt; on January 01, 2018.&lt;/p&gt;
  </content>
</entry>


<entry>
  <title type="html"><![CDATA[Contiguous letter sequences]]></title>
  <link rel="alternate" type="text/html" href="http://bbischof.com/blog/contiguous_letter_sequences/" />
  <id>http://bbischof.com/blog/contiguous_letter_sequences</id>
  <published>2017-09-10T04:00:01+00:00</published>
  <updated>2017-09-10T04:00:01+00:00</updated>
  <author>
    <name>Bryan Bischof</name>
    <uri>http://bbischof.com</uri>
    <email>bryan.bischof@gmail.com</email>
  </author>
  <content type="html">
    &lt;p&gt;What’s the shortest word that contains ‘ABCDE’ and so on…&lt;/p&gt;

&lt;!-- ^Spoiler Text^ --&gt;
&lt;h2 id=&quot;contiguous-letter-sequences&quot;&gt;Contiguous letter sequences&lt;/h2&gt;

&lt;p&gt;Haggard Hawks—one of my favorite Twitter accounts, and the subject of a different &lt;a href=&quot;https://medium.com/100000-arrows/haggard-scrabble-twitter-bot-2d2b53307c4c&quot;&gt;project&lt;/a&gt; once before—tweeted out this &lt;a href=&quot;https://twitter.com/HaggardHawks/status/903472505280618496&quot;&gt;fun fact&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;GOLDFINCHES contains the letters CDEFGHI.
JASMINELIKE contains the letters IJKLMN.
PROPINQUITIES contains the letters OPQRST.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Which got the ol’ thinker thinkin’.&lt;/p&gt;

&lt;p&gt;The code for this is relatively straightforward, so I wont belabor it, but I will admit I had to think a bit about what exactly I wanted to do. I came up with&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;For each subsequence of the alphabet, what is the shortest word in my dictionary(we'll come back to this) that contains all letters in this subsequence?
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A few points:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;I wanted the shortest word as a way to make the solutions more unique, and more “purely” about the letters.&lt;/li&gt;
  &lt;li&gt;I wanted to consider all subsequences because I predicted it would make for a better visualization and decomposition of the alphabet than random splittings of letters.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;the-coding-part&quot;&gt;The coding part&lt;/h3&gt;

&lt;p&gt;The most challenging of the coding component was an organized and reasonably efficient way to run through all words in the dictionary and all subsequences. Since the dictionary is long in comparison to the number of subsequences—&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(n^2 + n) / 2)-n=325&lt;/code&gt; because I ignore single letters—I knew that I’d want to scroll through the dictionary and check which of the subsequences were there. Thus I made a dict, with keys all the subsequences and values as empty lists, and then checked if the alphabetized-uniqued version of the word contained the subsequence. If so, I added it to the dictionary in length order. This worked and wasn’t too slow, even for 300k words.&lt;/p&gt;

&lt;p&gt;If I were really flexing, I’d have made the subsequences into a trie, and traversed that to reduce the number of checks, but it didn’t seem worth it since the run-time was so small already.&lt;/p&gt;

&lt;h2 id=&quot;visualization&quot;&gt;Visualization&lt;/h2&gt;

&lt;p&gt;After running through the above, I knew in my mind that I wanted some matrix presentation of the data, but for the life of me couldn’t make sense of how to do it. I kept thinking that the rows and columns would be letters contained in the sequence, but this actually becomes sort of a tensor(3-dimensional matrix), in that there is a matrix of containment for every pair of letters. After far too long I realized that starting letter and ending letter uniquely identify the subsequence, and realized what I wanted.&lt;/p&gt;

&lt;p&gt;I used Tableau to simplify generating the graphics, which for this simple of a project, was plenty.&lt;/p&gt;

&lt;figure&gt;
    &lt;img src=&quot;/images/consec_words_matrix_double_small.jpg&quot; alt=&quot;consec_words_matrix_double&quot; /&gt;
    &lt;figcaption&gt;Two matrices for two differently sized dictionaries&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;In the above you’ll notice two matrices because I used two separate word lists. Originally, I just used the unix wordlist, but I immediately noticed I didn’t find &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JASMINELIKE&lt;/code&gt; in my analysis, or even another word that contained &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IJKLMN&lt;/code&gt;. This bothered me, so I looked around for a longer wordlist similar to the unix one. I found &lt;a href=&quot;https://github.com/dwyl/english-words&quot;&gt;this one&lt;/a&gt;. I liked how similar the wordlists were, and this one is about 50% larger. You’ll notice that the larger dictionary does, in-fact, have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jasminelike&lt;/code&gt;, and adds some other good words on the outskirts of this matrix.&lt;/p&gt;

&lt;p&gt;I liked that the big stair steps in the matrices show where certain letters have a lot less words.&lt;/p&gt;

&lt;h3 id=&quot;efficiency&quot;&gt;Efficiency&lt;/h3&gt;

&lt;p&gt;Because I was thinking about how short the words were in terms of their subsequence, I decided to compute &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;efficiency&lt;/code&gt; of the words. Hueristically, this meant &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;how many letters beyond the subsequence were necessary to create the word&lt;/code&gt;. We expect that as the subsequence grows in length, the efficiency will also decrease, and that was true.&lt;/p&gt;

&lt;figure&gt;
    &lt;img src=&quot;/images/consec_words_efficiency_small.jpg&quot; alt=&quot;consec_words_efficiency&quot; /&gt;
    &lt;figcaption&gt;Efficiency matrix for large dictionary&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;To compute this I used the following formula:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(
  1-([Containing Word Len]-[number of consecs])/[Containing Word Len]
)*[number of consecs]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Which is the percentage of the number of unnecissary letters multiplied by the number of consecutive letters. The reason for skewing by consecutive letters is to accomidate that it’s harder and harder to make a word as the number of letters increase.&lt;/p&gt;

&lt;h3 id=&quot;some-analysis&quot;&gt;Some analysis&lt;/h3&gt;

&lt;p&gt;If I wanted to recreate the original tweet with the shortest possible words:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;LIGHTFACED is a shorter word for CDEFGHI
JASMINELIKE is the shortest for IJKLMN
PAROQUETS is shorter for OPQRSTU
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If I wanted the shortest total letters to express the alphabet:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;AB,CD,FE,HG,JI,KL,MN,PO,QR,ST,VU,XW,YEZ
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Which isn’t very interesting, so I switched to shortest number of words and minimizing letters within that:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;BOLDFACE,HIGHJACK,PLASMOQUIN,LIVERWURST,XYZ
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note that this required a bit more coding, to find the optimal sequence.&lt;/p&gt;


    &lt;p&gt;&lt;a href=&quot;http://bbischof.com/blog/contiguous_letter_sequences/&quot;&gt;Contiguous letter sequences&lt;/a&gt; was originally published by Bryan Bischof at &lt;a href=&quot;http://bbischof.com&quot;&gt;Hyperbolicity&lt;/a&gt; on September 10, 2017.&lt;/p&gt;
  </content>
</entry>


<entry>
  <title type="html"><![CDATA[Puzzles]]></title>
  <link rel="alternate" type="text/html" href="http://bbischof.com/blog/puzzles/" />
  <id>http://bbischof.com/blog/puzzles</id>
  <published>2017-05-19T04:00:01+00:00</published>
  <updated>2017-05-19T04:00:01+00:00</updated>
  <author>
    <name>Bryan Bischof</name>
    <uri>http://bbischof.com</uri>
    <email>bryan.bischof@gmail.com</email>
  </author>
  <content type="html">
    &lt;p&gt;A place for my continued toying with puzzles. 538 puzzles, WACan’t, and others.&lt;/p&gt;

&lt;!-- ^Spoiler Text^ --&gt;
&lt;h2 id=&quot;finnegans-quaternions&quot;&gt;Finnegan’s Quaternions&lt;/h2&gt;

&lt;p&gt;The ever distracting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Wolfram Alpha Can't&lt;/code&gt; Twitter account, ensnared me a few days ago with this &lt;a href=&quot;https://twitter.com/wacnt/status/864631759954161666&quot;&gt;tweet&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Which asked for all the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt;s, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;j&lt;/code&gt;s, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;k&lt;/code&gt;s from Finnegan’s wake, to be taken in order to be a quaternionic product. The problem wasn’t the most fascinating, but just silly enough.&lt;/p&gt;

&lt;p&gt;Here’s a &lt;a href=&quot;https://gist.github.com/BBischof/560352b5da927758487df8882512a845&quot;&gt;gist&lt;/a&gt; of my solution. I definitely think that the multiplication function could be more elegant, but c’est la vie. I &lt;em&gt;was&lt;/em&gt; happy that I thought to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reduce&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;billiards-racks&quot;&gt;Billiards racks&lt;/h2&gt;

&lt;p&gt;Another distracting Twitter account is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;solve my maths&lt;/code&gt;, who retweeted this &lt;a href=&quot;https://twitter.com/aap03102/status/859645194806996992&quot;&gt;little puppy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This problem was a little meatier. It asks if you can rearrange the pool balls in a billiards rack such that each ball is the difference of the two balls below it(excluding the bottom row). I liked how this problem immediately starts suggesting some data structures.&lt;/p&gt;

&lt;p&gt;My mental model for how to construct a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rack&lt;/code&gt; was to start in the lower-left corner, and add a ball to the bottom row at a time, and stop when it becomes impossible. Then, running through all the ball orderings, will return only the racks that make it all the way.&lt;/p&gt;

&lt;p&gt;So I started with a row object, and then a rack object. The rows have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;append&lt;/code&gt;, and the racks have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_ball&lt;/code&gt;. The rack needs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fill_last&lt;/code&gt; because it didn’t cleanly fit into the paradigm of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_ball&lt;/code&gt;; also added a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;print_rack&lt;/code&gt; function for obvious reasons.&lt;/p&gt;

&lt;p&gt;The logic is straightforward, and starts with two balls:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;leftmost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secondleftmost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rack_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;leftmost&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secondleftmost&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;leftmost&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;secondleftmost&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;leftmost&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secondleftmost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;operation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;operation&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rack_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rack_size&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rows&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rack_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;leftmost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;secondleftmost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remaining_balls&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rack_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rack_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remaining_balls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;leftmost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remaining_balls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;secondleftmost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fill_last&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ValueError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Incorrect Starting Configuration&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fill_last()&lt;/code&gt; is doing the work of moving up a row, and adding the necessary ball in the third position. You’ll see that this function will get called every time a ball is added to the rack, but only for the topmost ball necessary—the top of whatever triangle exists.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fill_last&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;current_last_length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rack_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;diff&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;operation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;diff&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remaining_balls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current_last_length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;diff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remaining_balls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;diff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ValueError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Impossible Rack&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So now, we just keep adding balls to the bottom row, and then filling out the rows above, and finishing off with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fill_last()&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add_ball&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remaining_balls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remaining_balls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;diff&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;operation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;diff&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remaining_balls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;diff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remaining_balls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;diff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ValueError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Impossible Rack&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fill_last&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remaining_balls&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ValueError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Impossible Rack&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is all well and good, and does yield a solution for the original problem if you iterate through all the possibilities, but I wanted to see the evolution of these solutions, i.e. as you add balls, how many racks are floating around. First, this code does the iteration:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;solve_puzzle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;puzzle_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;puzzle_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;puzzle_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ValueError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Change your puzzle size&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;rack_list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;number_of_balls&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;puzzle_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;puzzle_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;number_of_balls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;number_of_balls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;rack_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;puzzle_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ValueError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And then I got a wild hair and wrote this atrocity:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;new_rack&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;some_racks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;compute_subracks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_rack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;some_racks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ball&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_rack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remaining_balls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;sub_rack&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deepcopy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_rack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;sub_rack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_ball&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ball&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;some_racks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sub_rack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ValueError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;some_racks&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;print_rack_tree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root_rack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;puzzle_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;possibility_counts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compute_subracks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root_rack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;possibility_counts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;puzzle_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compute_subracks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;possibility_counts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;puzzle_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compute_subracks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;possibility_counts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
                        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;puzzle_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                            &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compute_subracks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
                                &lt;span class=&quot;n&quot;&gt;possibility_counts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
                                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;puzzle_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                                    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compute_subracks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
                                        &lt;span class=&quot;n&quot;&gt;possibility_counts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
                                        &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print_rack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
                                &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                                    &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print_rack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
                        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                            &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print_rack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print_rack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print_rack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;possibility_counts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;which, OMG, I &lt;em&gt;cannot, for the life of me,&lt;/em&gt; refactor to be recursive. I have tried like three times and keep messing it up. It &lt;em&gt;clearly&lt;/em&gt; should be recursive, but it’s above my pay-grade.&lt;/p&gt;

&lt;p&gt;So now, a little word on these counts:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;global_counts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rack_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;global_counts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;counts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;print_rack_tree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;puzzle_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;counts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;global_counts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;counts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;global_counts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Which is going to yield the sequence leading up to a solution. Without further ado:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solve_puzzle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;returns&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;row 4:         [5]
row 3:       [4, 9]
row 2:     [7, 11, 2]
row 1:   [8, 1, 12, 10]
row 0: [6, 14, 15, 3, 13]
Remaining: []
row 4:         [5]
row 3:       [9, 4]
row 2:     [2, 11, 7]
row 1:   [10, 12, 1, 8]
row 0: [13, 3, 15, 14, 6]
Remaining: []
{2: 196, 3: 1574, 4: 1734, 5: 2}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I know whatcha thinking, I was thinking it too. What about the racks for larger numbers(the astute reader will have noticed how often I left these functions to take &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt;). Let’s look at 6:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{2: 400, 3: 5516, 4: 25994, 5: 3182, 6: 0}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;No solution! Damn! But 3182 racks get to the level 5 before they fail at 6. Take note that the number of balls is larger, so there are more degrees of freedom here. Here are the first four it spits out, it’d be curious to see if there is some common structure, but there are a lot to look at.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;row 4:         [4]
row 3:       [5, 9]
row 2:     [7, 12, 3]
row 1:   [13, 6, 18, 15]
row 0: [1, 14, 20, 2, 17]
Remaining: [8, 10, 11, 16, 19, 21]
row 4:         [5]
row 3:       [4, 9]
row 2:     [7, 11, 2]
row 1:   [13, 6, 17, 15]
row 0: [1, 14, 20, 3, 18]
Remaining: [8, 10, 12, 16, 19, 21]
row 4:         [4]
row 3:       [5, 9]
row 2:     [6, 11, 2]
row 1:   [13, 7, 18, 16]
row 0: [1, 14, 21, 3, 19]
Remaining: [8, 10, 12, 15, 17, 20]
row 4:         [6]
row 3:       [2, 8]
row 2:     [9, 11, 3]
row 1:   [14, 5, 16, 13]
row 0: [1, 15, 20, 4, 17]
Remaining: [7, 10, 12, 18, 19, 21]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Seven is similarly dissapointing, and so I’m just guessing that 5 is the upper bound for a solution(I’m going to try to prove this at some point, but I’m a bit lazy and uninspired).&lt;/p&gt;

&lt;p&gt;Ok, so what about 4?&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;row 3:       [3]
row 2:     [4, 7]
row 1:   [5, 9, 2]
row 0: [6, 1, 10, 8]
Remaining: []
row 3:       [3]
row 2:     [5, 2]
row 1:   [4, 9, 7]
row 0: [6, 10, 1, 8]
Remaining: []
row 3:       [3]
row 2:     [2, 5]
row 1:   [7, 9, 4]
row 0: [8, 1, 10, 6]
Remaining: []
row 3:       [4]
row 2:     [2, 6]
row 1:   [5, 7, 1]
row 0: [8, 3, 10, 9]
Remaining: []
row 3:       [3]
row 2:     [7, 4]
row 1:   [2, 9, 5]
row 0: [8, 10, 1, 6]
Remaining: []
row 3:       [4]
row 2:     [5, 1]
row 1:   [2, 7, 6]
row 0: [8, 10, 3, 9]
Remaining: []
row 3:       [4]
row 2:     [1, 5]
row 1:   [6, 7, 2]
row 0: [9, 3, 10, 8]
Remaining: []
row 3:       [4]
row 2:     [6, 2]
row 1:   [1, 7, 5]
row 0: [9, 10, 3, 8]
Remaining: []
{2: 80, 3: 262, 4: 8}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And 3(for completeness)?&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;row 2:     [3]
row 1:   [5, 2]
row 0: [1, 6, 4]
Remaining: []
row 2:     [3]
row 1:   [4, 1]
row 0: [2, 6, 5]
Remaining: []
row 2:     [2]
row 1:   [3, 5]
row 0: [4, 1, 6]
Remaining: []
row 2:     [3]
row 1:   [2, 5]
row 0: [4, 6, 1]
Remaining: []
row 2:     [1]
row 1:   [3, 4]
row 0: [5, 2, 6]
Remaining: []
row 2:     [3]
row 1:   [1, 4]
row 0: [5, 6, 2]
Remaining: []
row 2:     [2]
row 1:   [5, 3]
row 0: [6, 1, 4]
Remaining: []
row 2:     [1]
row 1:   [4, 3]
row 0: [6, 2, 5]
Remaining: []
{2: 24, 3: 8}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You may think at this point “Can we stop talking about this?”, or you may think “what about if it was add instead of difference?”&lt;/p&gt;

&lt;p&gt;Nope. Not even a little. With enough balls for a rack of size 6, there are only 7 additive 4-racks! Wild!&lt;/p&gt;

&lt;p&gt;All of the above discussion and code in this &lt;a href=&quot;https://gist.github.com/BBischof/d3968457dda2a9deb6cc7c710c27dd35&quot;&gt;gist&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;letter-place-frequencies&quot;&gt;Letter-place frequencies&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://twitter.com/wacnt/status/847961924813848576&quot;&gt;This one&lt;/a&gt; also originated from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Wolfram Alpha Can't&lt;/code&gt;, and asks about the most common letter, by place, by length of word.&lt;/p&gt;

&lt;p&gt;I just love this question so much. The solution doesn’t take much work, just a little bashy loop:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;i &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;1 15&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
    for &lt;/span&gt;j &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;1 &lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /usr/share/dict/words | &lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;length(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;) == &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; { print tolower(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;) }&quot;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;sort&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;uniq&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$j&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'{print tolower(substr($0,j,1))}'&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;sort&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;uniq&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'{print $2, $1}'&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-nk2&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-1&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'{print $1}'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;tr&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; &quot;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;tr&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'[:space:]'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;done
    &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;which has the added fun of making “words” out of the answers.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ao
aae
saae
saaee
sariee
saraiee
sareliee
sereeliee
pereoiaiie
pereooatiie
pnreoooatiie
pnteooiiatiis
pnteoooiianiss
pneeooooiianiss
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I got really excited and wanted to look at a slightly more dramatic presentation, so I made &lt;a href=&quot;https://twitter.com/BEBischof/status/848016168254406656&quot;&gt;this&lt;/a&gt; which I think is way cool! Check out those patterns!!!&lt;/p&gt;

&lt;h2 id=&quot;the-538-multiplication-problem&quot;&gt;The 538-multiplication problem&lt;/h2&gt;

&lt;p&gt;This is one of the &lt;a href=&quot;https://twitter.com/ollie/status/850356577446055936&quot;&gt;538 Puzzlers&lt;/a&gt;, and while I like the official solutions, I also kinda like my work on it:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;10k sims:
random_placement: 2321,
mean_method: 1083,
thresh: (4, 4, 3, 1072),
cond_thresh: (4, 4, 3, 1072),
perfect: (4, 4, 3, 875)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And some cool &lt;a href=&quot;https://twitter.com/BEBischof/status/852372470707269632&quot;&gt;pics&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;end-matter&quot;&gt;End matter&lt;/h2&gt;

&lt;p&gt;All for now, but there will always be more. Let me know if you find a puzzle that I might like, or you have some input on the above.&lt;/p&gt;

    &lt;p&gt;&lt;a href=&quot;http://bbischof.com/blog/puzzles/&quot;&gt;Puzzles&lt;/a&gt; was originally published by Bryan Bischof at &lt;a href=&quot;http://bbischof.com&quot;&gt;Hyperbolicity&lt;/a&gt; on May 19, 2017.&lt;/p&gt;
  </content>
</entry>


<entry>
  <title type="html"><![CDATA[Random Partition]]></title>
  <link rel="alternate" type="text/html" href="http://bbischof.com/blog/random-partitions/" />
  <id>http://bbischof.com/blog/random-partitions</id>
  <published>2017-05-14T12:08:50+00:00</published>
  <updated>2017-05-14T12:08:50+00:00</updated>
  <author>
    <name>Bryan Bischof</name>
    <uri>http://bbischof.com</uri>
    <email>bryan.bischof@gmail.com</email>
  </author>
  <content type="html">
    &lt;p&gt;I’ve been curious about generating a random partition of an integer.&lt;/p&gt;

&lt;h2 id=&quot;rancom&quot;&gt;RanCom&lt;/h2&gt;

&lt;p&gt;I have been thinking a lot about this somewhat randomly. In particular, I’ve been trying to think of how to select things randomly in various incarnations. This one wasn’t obvious other than the naive solution of&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Generate all partitions&lt;/li&gt;
  &lt;li&gt;Select one at random&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After some Google, I found &lt;a href=&quot;http://stackoverflow.com/questions/2161406/how-do-i-generate-a-uniform-random-integer-partition&quot;&gt;this&lt;/a&gt;, which after a little thinking I was able to understand. The answer I used comes from this &lt;a href=&quot;https://www.math.upenn.edu/~wilf/website/CombinatorialAlgorithms.pdf&quot;&gt;book&lt;/a&gt;—which I am now dangerously interested in reading. It becomes:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;random&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;rancom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sample&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:])]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Notice that this is for arbitrary &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;k&lt;/code&gt;, but in our case, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;k=n&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Nice and fast. I think it’d be fun to look at the balls-and-boxes algorithm that leads to this solution.&lt;/p&gt;

&lt;p&gt;There’s also the fun question of what is an average partition for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;avg_part&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iterations&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iterations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rancom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reverse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;[2, 0]
[2, 1, 0]
[3, 1, 0, 0]
[3, 1, 1, 0, 0]
[3, 2, 1, 0, 0, 0]
[3, 2, 1, 1, 0, 0, 0]
[3, 2, 1, 1, 0, 0, 0, 0]
[4, 2, 1, 1, 1, 0, 0, 0, 0]
[4, 2, 2, 1, 1, 0, 0, 0, 0, 0]
[4, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0]
[4, 3, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0]
[4, 3, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0]
[4, 3, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]
[4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]
[4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]
[4, 3, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]
[5, 3, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[5, 3, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[5, 3, 3, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[5, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[5, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[5, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[5, 4, 3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;&lt;a href=&quot;http://bbischof.com/blog/random-partitions/&quot;&gt;Random Partition&lt;/a&gt; was originally published by Bryan Bischof at &lt;a href=&quot;http://bbischof.com&quot;&gt;Hyperbolicity&lt;/a&gt; on May 14, 2017.&lt;/p&gt;
  </content>
</entry>


<entry>
  <title type="html"><![CDATA[A Horsey Race]]></title>
  <link rel="alternate" type="text/html" href="http://bbischof.com/blog/a-horsey-race/" />
  <id>http://bbischof.com/blog/a-horsey-race</id>
  <published>2017-05-06T12:08:50+00:00</published>
  <updated>2017-05-06T12:08:50+00:00</updated>
  <author>
    <name>Bryan Bischof</name>
    <uri>http://bbischof.com</uri>
    <email>bryan.bischof@gmail.com</email>
  </author>
  <content type="html">
    &lt;p&gt;I’ve been playing with some puzzles lately(slightly egged on by &lt;a href=&quot;https://whatsyourpvalue.wordpress.com/&quot;&gt;Jeff&lt;/a&gt;).&lt;/p&gt;

&lt;h2 id=&quot;some-recent-puzzles&quot;&gt;Some recent puzzles&lt;/h2&gt;

&lt;p&gt;I’ve thought about some of the recent puzzles, even automating some and making some fun &lt;a href=&quot;https://twitter.com/BEBischof/status/852372470707269632&quot;&gt;visualizations&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also spent a little time writing some puzzles myself, and some out of left field &lt;a href=&quot;https://twitter.com/BEBischof/status/848016168254406656&quot;&gt;questions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;However, for the most recent 538 puzzle, they suggested making an animation, so I thought I’d spent a few hours making a d3 vis for fun. Here’s the &lt;a href=&quot;https://fivethirtyeight.com/features/who-will-win-the-lucky-derby/&quot;&gt;puzzle.&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;horseys&quot;&gt;Horseys&lt;/h2&gt;

&lt;p&gt;The setup is relatively straightforward; using the list of probabilities, generate 20 sequences of steps, continuing to sum them until one exceeds 200. Here’s the little function—keep in mind that I don’t know Javascript:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;function run_race(race_length){
  horsey_probabilities = [.52,.54,.56,.58,.60,.62,.64,.66,.68,.70,.72,.74,.76,.78,.80,.82,.84,.86,.88,.90].reverse()
  horsey_paths = [[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]
  winning_position = 0
  while (winning_position &amp;lt; race_length) {
    new_steps = horsey_probabilities.map(function(d){return rand_step(d)})
    horsey_paths.map(function (list, idx) {
      return list.push(new_steps[idx]);});
    winning_position = Math.max.apply(Math, horsey_paths.map(function(d){return d.reduce((a, b) =&amp;gt; a + b, 0)}))
//   console.log(winning_position);
  }
  return horsey_paths
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The ‘hardest’ part was that I wanted to display the data as a bump chart of who was winning the race at each step. So I had to compute the ‘position’ at each step. Consider the following problem:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Given a square matrix of numbers of integers, a list of rows, convert the integers to the columnar rank of each entry.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For example:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[
  [1,2,3],
  [3,2,1],
  [5,1,0],
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;becomes&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[
  [1,1,3],
  [2,3,2],
  [3,1,1],
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’s a little strange, but mostly involves changing the direction of the lists, and then computing the ranks; even in Python gave me pause:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;a = [5,2,4,3,0]
[z[1] for z in
 sorted([(y[0],j+1) for j,y in
         enumerate(sorted([(i+1,x) for i,x in
                           enumerate(a)
                          ], key=lambda x: x[1]))
        ], key=lambda x: x[0])
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;So you can imagine it was a little awkard in JS, but here ya go:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;function matrix_transpose(matrix){
  return matrix[0].map(function(col, i) {
    return matrix.map(function(row) {
        return row[i];
    });
});
}

function convert_list_to_ranks(list_of_sums){
  output = list_of_sums.map(function (i,idx){return ([idx+1, i]);})
    .sort(function(a,b) {return b[1] - a[1];})
    .map(function (p,idy){return ([p[0], idy+1])})
    .sort(function(a,b) {return a[0] - b[0];})
    .map(function (x){return x[1]})
  return output
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Without further ado, here’s the &lt;a href=&quot;https://bl.ocks.org/BBischof/576cf84b61c3f04f1021a0159fc5a2d1&quot;&gt;vis&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;&lt;a href=&quot;http://bbischof.com/blog/a-horsey-race/&quot;&gt;A Horsey Race&lt;/a&gt; was originally published by Bryan Bischof at &lt;a href=&quot;http://bbischof.com&quot;&gt;Hyperbolicity&lt;/a&gt; on May 06, 2017.&lt;/p&gt;
  </content>
</entry>


<entry>
  <title type="html"><![CDATA[Joining Blue Bottle]]></title>
  <link rel="alternate" type="text/html" href="http://bbischof.com/blog/joining-blue-bottle/" />
  <id>http://bbischof.com/blog/joining-blue-bottle</id>
  <published>2016-07-30T12:08:50+00:00</published>
  <updated>2016-07-30T12:08:50+00:00</updated>
  <author>
    <name>Bryan Bischof</name>
    <uri>http://bbischof.com</uri>
    <email>bryan.bischof@gmail.com</email>
  </author>
  <content type="html">
    &lt;p&gt;After several months of extremely casual job-searching, something clicked. And in some sense, that which clicked, was that &lt;em&gt;confirmation-bias-makes-destiny’s-work-easy&lt;/em&gt; job.&lt;/p&gt;

&lt;h2 id=&quot;the-lead-up&quot;&gt;The lead-up&lt;/h2&gt;

&lt;p&gt;I found this opportunity on one of the job forums. I was cruising and looking for anything that jumped out. I was &lt;em&gt;really&lt;/em&gt; taken aback when I saw that Blue Bottle(BB) was hiring a data engineer. As most know, I’m really interested in coffee. I’ve been interested in the domain for more than five years now, and in that time, I’ve really gone out of my way to understand the industry as an outsider.&lt;/p&gt;

&lt;p&gt;While I know a lot of people are “into” coffee, I think that this undersells my passion. I’ve genuinely wanted to work with coffee data for some time, but unfortunately, I haven’t really found any datasets that got me charged. Last year, I tried to contact &lt;a href=&quot;https://www.cropster.com/&quot;&gt;Cropster&lt;/a&gt;, but I struggled to find a reasonable vector. Some other things I’ve thought about is collecting data on my own coffee consumption, but obviously this isn’t exactly huge. (I &lt;em&gt;do&lt;/em&gt; intend on building some visualizations of my coffee drinking throughout the past couple years, as per my coffee bags.)&lt;/p&gt;

&lt;p&gt;I shot off a cover letter to BB and was a little hesitant. My biggest concern was truly that the job seemed very focused on ETL and maybe not enough ML/Eng.&lt;/p&gt;

&lt;h2 id=&quot;in-comminique&quot;&gt;In comminique&lt;/h2&gt;

&lt;p&gt;They got back to me, we had the standard phone calls(the one with their digital lead was especially fun), and I got invited on site last monday. Due to a string of less-than-thrilling on-sites this year(I’m planning a write-up of those), I was quite nervous.&lt;/p&gt;

&lt;p&gt;To skip ahead a bit, I told my friend Jeff monday night that “if I don’t get this job, I don’t know anything about getting jobs.”&lt;/p&gt;

&lt;p&gt;The reason for the above statement was that I essentially killed my interviews. I felt confident in my answers, extremely personable that day, exuding excitement, and genuinely like I had skills to contribute. I got a little side-tracked in one interview, but otherwise I really felt on.&lt;/p&gt;

&lt;p&gt;The next day I got an offer. And in-fact, signed it the same day.&lt;/p&gt;

&lt;h2 id=&quot;future-perfect&quot;&gt;Future perfect&lt;/h2&gt;

&lt;p&gt;I really can’t speak highly enough about the opportunity to be doing data-engineering and data-science for a coffee company. I feel like a dream has come true(sorry, I know this is corny).&lt;/p&gt;

&lt;p&gt;While this means I’m leaving IBM a little earlier than I would have liked, I think it’s a good time for that anyhow. Despite there being a lot left to learn there, I think the move will dramatically benefit my mental health. One of the best things about Blue Bottle: &lt;em&gt;it’s still in the East Bay!!!&lt;/em&gt;&lt;/p&gt;

    &lt;p&gt;&lt;a href=&quot;http://bbischof.com/blog/joining-blue-bottle/&quot;&gt;Joining Blue Bottle&lt;/a&gt; was originally published by Bryan Bischof at &lt;a href=&quot;http://bbischof.com&quot;&gt;Hyperbolicity&lt;/a&gt; on July 30, 2016.&lt;/p&gt;
  </content>
</entry>


<entry>
  <title type="html"><![CDATA[Code for America App]]></title>
  <link rel="alternate" type="text/html" href="http://bbischof.com/blog/code-for-america-app/" />
  <id>http://bbischof.com/blog/code-for-america-app</id>
  <published>2016-07-23T12:08:50+00:00</published>
  <updated>2016-07-23T12:08:50+00:00</updated>
  <author>
    <name>Bryan Bischof</name>
    <uri>http://bbischof.com</uri>
    <email>bryan.bischof@gmail.com</email>
  </author>
  <content type="html">
    &lt;p&gt;The notion of Code for America is very attractive to me. In particular, the allure of working directly with a local government, is one of the ideal jobs I could ask for. While there would be some huge sacrifices to taking this position(not developing certain skills, forfeiting access to certain computational infrastructures, and of course, the money aspect), I am still interested. So I decided to apply.&lt;/p&gt;

&lt;h2 id=&quot;data-challenge&quot;&gt;Data Challenge&lt;/h2&gt;

&lt;p&gt;The coding challenge was very very easy:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Given the following `csv`, compute the number of violations by type, and the first and last violation in each set.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And they provide a little data file with columns:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;violation_id,inspection_id,violation_category,violation_date,violation_date_closed,violation_type
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;so the actual problem just requires a groupby, count, and min/max. However, the challenge asks specifically for you to &lt;em&gt;present&lt;/em&gt; this output. Whence I decided to just use js/D3 for the whole challenge.&lt;/p&gt;

&lt;p&gt;I had to remember how to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nest()&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;d3.nest().key(function(d) {return d.violation_type}).entries(data)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and then I did the fun thing of deciding how to draw this data. The data sets were so small, and so limited in time-scale, but I like the idea of something histogram-y. Since the number of total points was tiny, and one-dimensional, I remembered that beeswarms could be usable. So I went with that.&lt;/p&gt;

&lt;p&gt;Here’s the live &lt;a href=&quot;http://bl.ocks.org/BBischof/a9e166f26ea11e01d838273e34a043b6&quot;&gt;version&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;an-alternative&quot;&gt;An Alternative&lt;/h2&gt;

&lt;p&gt;The reality is, while the beeswarm is fun and kinda cool, I have to admit that it might just be better to use a calendar visualization. Because it’s all a single year I can use the exploded version of the calendar that takes up a bit more space and really highlights the delineation between the months.&lt;/p&gt;

&lt;p&gt;Here’s the live &lt;a href=&quot;http://bl.ocks.org/BBischof/7607b90705281634c6da741c34d9ba7c&quot;&gt;version&lt;/a&gt;.&lt;/p&gt;


    &lt;p&gt;&lt;a href=&quot;http://bbischof.com/blog/code-for-america-app/&quot;&gt;Code for America App&lt;/a&gt; was originally published by Bryan Bischof at &lt;a href=&quot;http://bbischof.com&quot;&gt;Hyperbolicity&lt;/a&gt; on July 23, 2016.&lt;/p&gt;
  </content>
</entry>

</feed>