The Universe of Discourse
https://blog.plover.com
The Universe of Discourse (Mark Dominus Blog)enMore about the happy numeric coincidence
https://blog.plover.com/2019/01/02#power-digit-sum-2
<p>[ <a href="https://blog.plover.com/math/power-digit-sum.html">Previously</a> ]</p>
<p>Observing three small examples where the digital sum of <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%5ek%24"> was
equal to <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%24">, I said:</p>
<blockquote>
<p>I supposed that there were few other examples, probably none …
Still I hoped there might be one or two…</p>
</blockquote>
<p>but in fact there are a great many; for example the digital sum of
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24217%5e%7b22%7d%24"> is <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24217%24">.</p>
<p>Dave McKee asked what my intuition was. It was something like this.
Fix <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%24"> and consider the sequence <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%5e2%2c%20n%5e3%2c%20%e2%80%a6%24">. The elements
become increasingly sparse, and for their digital sum to equal <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%24">
requires increasingly improbable coincidences. For example, taking
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%3d3%24">, we would need to have <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24k%24"> such that $$3^k = 2·10^p + 1.$$
While I can't immediately rule out this possibility, it seems
extremely unlikely. This also resembles the <a href="https://en.wikipedia.org/wiki/Catalan%27s_conjecture">Catalan
conjecture</a>,
which is that the only nontrivial solution of $$ \left\lvert2^i -
3^j\right\rvert = 1$$ is <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24i%3d3%2c%20j%3d2%24">. The Catalan conjecture is
indeed true, but it was an open problem for 158 years.</p>
<p>I was quite mistaken, so what went wrong? First, there is one
nontrivial solution to the Catalan conjecture, and here we have not
one sequence of <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%5ek%24"> but an infinite family, each of which might
have an exceptional solution or two. And second, the case of <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%3d3%24">
is atypically bleak. For <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%243%5ek%24"> to have a digital sum of <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%243%24"> is a
tough order because there are very few sequences of digits whose sum is 3.
But the number of sequences of <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24d%24"> digits whose sum is <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%24"> grows
quite rapidly with <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%24">, and for small <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%24"> is very misleading.</p>
A happy numeric coincidence
https://blog.plover.com/2019/01/01#power-digit-sum
<p>A couple of days ago I was pleased to notice the following coincidence:</p>
<table align="center">
<tr><td><img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%249%5e2%20%3d%2081%24"><td>and <td align="right"><img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%248%20%2b%201%20%3d%209%24">
<tr><td><img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%248%5e3%20%3d%20512%24"><td>and <td align="right"><img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%245%20%2b%201%20%2b%202%20%3d%208%24">
<tr><td><img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%247%5e4%20%3d%202401%24"><td>and <td align="right"><img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%242%20%2b%204%20%2b%200%20%2b%201%20%3d%207%24">
</table>
<p>I supposed that there were few other examples, probably none, and that
at least I could prove that there were only a finite number of
examples. My expected proof of this didn't work, but I still supposed
that there would be no further examples. Still I hoped there might be one
or two, so I set the computer to look for them if there were.</p>
<p>My first run produced:</p>
<p>\begin{array}{rcr}
17^3 &=& 4\;913 \\
18^3 &=& 5\;832\\
22^4 &=& 234\;256\\
25^4 &=& 390\;625\\
26^3 &=& 17\;576\\
27^3 &=& 19\;683\\
28^4 &=& 614\;656\\
36^4 &=& 1\;679\;616\\
\end{array}</p>
<p>Well, that was a happy surprise.</p>
<p>Wait a minute, though:</p>
<p>\begin{array}{rcr}
18 ^{ 6 } &=& 34\;012\;224 \\
18 ^{ 7 } &=& 612\;220\;032 \\
27 ^{ 7 } &=& 10\;460\;353\;203 \\
28 ^{ 5 } &=& 17\;210\;368 \\
31 ^{ 7 } &=& 27\;512\;614\;111 \\
34 ^{ 7 } &=& 52\;523\;350\;144 \\
35 ^{ 5 } &=& 52\;521\;875 \\
36 ^{ 5 } &=& 60\;466\;176 \\
43 ^{ 7 } &=& 271\;818\;611\;107 \\
45 ^{ 6 } &=& 8\;303\;765\;625 \\
46 ^{ 5 } &=& 205\;962\;976 \\
46 ^{ 8 } &=& 20\;047\;612\;231\;936 \\
53 ^{ 7 } &=& 1\;174\;711\;139\;837 \\
54 ^{ 6 } &=& 24\;794\;911\;296 \\
54 ^{ 8 } &=& 72\;301\;961\;339\;136 \\
54 ^{ 9 } &=& 3\;904\;305\;912\;313\;344 \\
58 ^{ 7 } &=& 2\;207\;984\;167\;552 \\
63 ^{ 8 } &=& 248\;155\;780\;267\;521 \\
64 ^{ 6 } &=& 68\;719\;476\;736 \\
68 ^{ 7 } &=& 6\;722\;988\;818\;432 \\
71 ^{ 9 } &=& 45\;848\;500\;718\;449\;031 \\
81 ^{ 9 } &=& 150\;094\;635\;296\;999\;121 \\
82 ^{ 10 } &=& 13\;744\;803\;133\;596\;058\;624 \\
85 ^{ 10 } &=& 19\;687\;440\;434\;072\;265\;625 \\
94 ^{ 10 } &=& 53\;861\;511\;409\;489\;970\;176 \\
97 ^{ 10 } &=& 73\;742\;412\;689\;492\;826\;049 \\
106 ^{ 10 } &=& 179\;084\;769\;654\;285\;362\;176 \\
117 ^{ 10 } &=& 480\;682\;838\;924\;478\;847\;449 \\
\end{array}</p>
<p>Oh my. </p>
<p>\begin{array}{rcr}
20 ^{ 13 } &=& 81\;920 & · 10^{12} \\
40 ^{ 13 } &=& 671\;088\;640 & · 10^{12} \\
80 ^{ 17 } &=& 225\;179\;981\;368\;524\;800 & · 10^{15} \\ \hline
80 ^{ 19 } &=& 1\;441\;151\;880\;758\;558\;720 & · 10^{18} \\
86 ^{ 13 } &=& 14\;076\;019\;706\;120\;526\;112\;710\;656 \\
90 ^{ 19 } &=& 13\;508\;517\;176\;729\;920\;890 & · 10^{18} \\ \hline
90 ^{ 20 } &=& 1\;215\;766\;545\;905\;692\;880\;100 & · 10^{18} \\
90 ^{ 21 } &=& 109\;418\;989\;131\;512\;359\;209 & · 10^{21} \\
90 ^{ 22 } &=& 9\;847\;709\;021\;836\;112\;328\;810 & · 10^{21} \\ \hline
90 ^{ 28 } &=& 5\;233\;476\;330\;273\;605\;372\;135\;115\;210 & · 10^{27} \\
91 ^{ 14 } &=& 2\;670\;419\;511\;272\;061\;205\;254\;504\;361 \\
98 ^{ 11 } &=& 8\;007\;313\;507\;497\;959\;524\;352 \\ \hline
103 ^{ 13 } &=& 146\;853\;371\;345\;156\;431\;381\;127\;623 \\
104 ^{ 13 } &=& 166\;507\;350\;731\;038\;802\;170\;609\;664 \\
106 ^{ 13 } &=& 213\;292\;826\;014\;568\;334\;917\;410\;816 \\ \hline
107 ^{ 11 } &=& 21\;048\;519\;522\;998\;348\;950\;643 \\
107 ^{ 13 } &=& 240\;984\;500\;018\;808\;097\;135\;911\;707 \\
107 ^{ 15 } & = & 2\;759\;031\;540\;715\;333\;904\;109\;053\;133 & & \\
& & 443 & & \\ \hline
108 ^{ 11 } &=& 23\;316\;389\;970\;546\;096\;340\;992 \\
108 ^{ 12 } &=& 2\;518\;170\;116\;818\;978\;404\;827\;136 \\
118 ^{ 14 } &=& 101\;472\;439\;712\;019\;470\;540\;189\;876\;224 \\ \hline
126 ^{ 13 } &=& 2\;017\;516\;459\;574\;609\;153\;391\;845\;376 \\
127 ^{ 14 } &=& 283\;956\;682\;347\;124\;706\;942\;551\;243\;009 \\
133 ^{ 16 } & = & 9\;585\;753\;470\;490\;322\;141\;591\;520\;062 & & \\
& & 265\;281 & & \\ \hline
134 ^{ 13 } &=& 4\;491\;199\;828\;872\;408\;503\;792\;328\;704 \\
134 ^{ 15 } & = & 80\;643\;984\;127\;232\;967\;094\;095\;054\;209 & & \\
& & 024 & & \\
135 ^{ 13 } &=& 4\;946\;966\;739\;525\;117\;513\;427\;734\;375 \\ \hline
135 ^{ 14 } &=& 667\;840\;509\;835\;890\;864\;312\;744\;140\;625 \\
136 ^{ 15 } & = & 100\;712\;557\;719\;971\;285\;024\;106\;952\;523 & & \\
& & 776 & & \\
140 ^{ 25 } &=& 449\;987\;958\;058\;483\;731\;145\;152\;266\;240 & · 10^{24} \\ \hline
142 ^{ 16 } & = & 27\;328\;356\;228\;554\;426\;163\;172\;505\;624 & & \\
& & 313\;856 & & \\
143 ^{ 17 } & = & 4\;372\;327\;021\;734\;283\;642\;004\;853\;327 & & \\
& & 592\;915\;343 & & \\
152 ^{ 15 } & = & 534\;138\;422\;146\;939\;893\;094\;821\;310\;496 & & \\
& & 768 & & \\ \hline
154 ^{ 14 } & = & 4\;219\;782\;742\;781\;494\;680\;756\;610\;809 & & \\
& & 856 & & \\
154 ^{ 15 } & = & 649\;846\;542\;388\;350\;180\;836\;518\;064\;717 & & \\
& & 824 & & \\
155 ^{ 19 } & = & 413\;335\;079\;574\;020\;313\;162\;122\;296\;733 & & \\
& & 856\;201\;171\;875 & & \\ \hline
157 ^{ 19 } & = & 527\;343\;255\;303\;841\;790\;870\;720\;812\;082 & & \\
& & 050\;804\;460\;293 & & \\
160 ^{ 28 } & = & 51\;922\;968\;585\;348\;276\;285\;304\;963\;292 & & \\
& & 200\;960 & · 10^{27} & \\
163 ^{ 16 } & = & 248\;314\;265\;639\;726\;167\;358\;751\;235\;626 & & \\
& & 296\;641 & & \\ \hline
169 ^{ 16 } & = & 442\;779\;263\;776\;840\;698\;304\;313\;192\;148 & & \\
& & 785\;281 & & \\
169 ^{ 22 } & = & 10\;315\;908\;977\;942\;302\;627\;204\;470\;186 & & \\
& & 314\;316\;211\;062\;255\;002\;161 & & \\
170 ^{ 31 } & = & 1\;392\;889\;173\;388\;510\;144\;614\;180\;174 & & \\
& & 894\;677\;204\;330 & · 10^{30} & \\ \hline
170 ^{ 33 } & = & 40\;254\;497\;110\;927\;943\;179\;349\;807\;054 & & \\
& & 456\;171\;205\;137 & · 10^{33} & \\
171 ^{ 17 } & = & 91\;397\;407\;411\;741\;874\;683\;083\;843\;738 & & \\
& & 640\;173\;291 & & \\
171 ^{ 19 } & = & 2\;672\;551\;590\;126\;744\;157\;608\;054\;674 & & \\
& & 761\;577\;307\;202\;131 & & \\ \hline
172 ^{ 18 } & = & 17\;358\;494\;027\;033\;103\;736\;099\;033\;196 & & \\
& & 316\;709\;617\;664 & & \\
173 ^{ 19 } & = & 3\;333\;311\;951\;341\;729\;629\;204\;978\;703 & & \\
& & 084\;632\;004\;627\;637 & & \\
181 ^{ 18 } & = & 43\;472\;473\;122\;830\;653\;562\;489\;222\;659 & & \\
& & 449\;707\;872\;441 & & \\ \hline
181 ^{ 19 } & = & 7\;868\;517\;635\;232\;348\;294\;810\;549\;301 & & \\
& & 360\;397\;124\;911\;821 & & \\
181 ^{ 20 } & = & 1\;424\;201\;691\;977\;055\;041\;360\;709\;423 & & \\
& & 546\;231\;879\;609\;039\;601 & & \\
189 ^{ 19 } & = & 17\;896\;754\;443\;176\;031\;520\;198\;514\;559 & & \\
& & 819\;163\;143\;441\;509 & & \\ \hline
193 ^{ 22 } & = & 191\;540\;580\;003\;116\;921\;429\;323\;712\;183 & & \\
& & 642\;218\;614\;831\;262\;597\;249 & & \\
199 ^{ 21 } & = & 1\;887\;620\;149\;539\;230\;539\;058\;375\;534 & & \\
& & 310\;517\;606\;114\;631\;604\;199 & & \\
207 ^{ 20 } & = & 20\;864\;448\;472\;975\;628\;947\;226\;005\;981 & & \\
& & 267\;194\;447\;042\;584\;001 & & \\ \hline
211 ^{ 25 } & = & 12\;795\;621\;425\;112\;113\;141\;935\;148\;247 & & \\
& & 655\;082\;376\;252\;275\;523\;500\;373\;035\;251 & & \\
217 ^{ 22 } & = & 2\;524\;144\;100\;572\;738\;110\;818\;511\;483 & & \\
& & 976\;079\;134\;636\;146\;367\;057\;489 & & \\
221 ^{ 25 } & = & 40\;719\;913\;064\;560\;249\;818\;128\;041\;081 & & \\
& & 360\;346\;218\;088\;750\;603\;039\;104\;925\;501 & & \\ \hline
225 ^{ 22 } & = & 5\;597\;774\;487\;475\;881\;147\;025\;802\;420 & & \\
& & 102\;991\;163\;730\;621\;337\;890\;625 & & \\
234 ^{ 23 } & = & 3\;104\;307\;401\;943\;398\;225\;947\;002\;752 & & \\
& & 118\;451\;297\;846\;365\;869\;366\;575\;104 & & \\
236 ^{ 25 } & = & 210\;281\;019\;656\;164\;214\;863\;109\;519\;134 & & \\
& & 145\;127\;118\;463\;502\;897\;144\;582\;373\;376 & & \\ \hline
250 ^{ 40 } & = & 827\;180\;612\;553\;027\;674\;871\;408\;692\;069 & & \\
& & 962\;853\;565\;812\;110\;900\;878\;906\;250 & · 10^{39} & \\
265 ^{ 28 } & = & 70\;938\;903\;323\;020\;164\;041\;464\;952\;207 & & \\
& & 191\;804\;150\;246\;813\;586\;391\;508\;579\;254 & & \\
& & 150\;390\;625 & & \\
\end{array}</p>
<p>Holy cow.</p>
<p>I should have been able to foresee some of those, like <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%2420%5e%7b13%7d%20%3d%208192%c2%b710%5e%7b13%7d%24">,
which in hindsight is obvious. But seriously, <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24163%5e%7b16%7d%24">?</p>
<p>(It rather looks like <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24265%5e%7b28%7d%24"> might be the last one where <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%24">
is not a multiple of <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%2410%24">, however. Or maybe that is a misleading artifact of
the calculating system I am using? I'm not sure yet.)</p>
<p>Happy new year, all.</p>
<p>[ Addendum 20190102: Several readers have confirmed that there are many
examples past <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24265%5e%7b28%7d%24">. I am probably running into some mismatch between
the way the computer represents numbers and the way they actually
work. ]</p>
<p>[ Addendum 20190102: Dave McKee asked <a href="https://blog.plover.com/math/power-digit-sum-2.html">why I thought there would be few examples</a>. ]</p>
I figured out that context manager bug!
https://blog.plover.com/2018/12/05#greenlight-cm-2
<p><a href="https://blog.plover.com/prog/bug/greenlight-cm.html">A couple of days ago I described a strange
bug</a> in my “Greenlight” project
that was causing Git to fail unpredictably, saying:</p>
<pre><code> fatal: this operation must be run in a work tree
</code></pre>
<p>The problem seemed to go away when I changed</p>
<pre><code> with env_var("GIT_DIR", self.repo_dir):
with env_var("GIT_WORK_TREE", self.work_dir):
result = subprocess.run(command, ...)
</code></pre>
<p>to</p>
<pre><code> with env_var("GIT_DIR", self.repo_dir, "GIT_WORK_TREE", self.work_dir):
result = subprocess.run(command, ...)
</code></pre>
<p>but I didn't understand why. I said:</p>
<blockquote>
<p>This was so unexpected that I wondered if the real problem was
nondeterministic and if some of the debugging messages had somehow
perturbed it. But I removed everything but the context manager
change and ran another test, which succeeded. By then I was five
and half hours into the debugging and I didn't have any energy left
to actually understand what the problem had been. I still don't
know.</p>
</blockquote>
<p>The problem re-manifested again today, and this time I was able to
track it down and fix it. The context manager code I mentioned above
was not the issue.</p>
<p>That <code>subprocess.run</code> call is made inside a <code>git_util</code> object which,
as you can see in the tiny excerpt above, has a <code>self.work_dir</code>
attribute that tells it where to find the working tree. Just before
running a Git command, the <code>git_util</code> object installs <code>self.work_dir</code>
into the environment to tell Git where the working tree is.</p>
<p>The <code>git_util</code> object is originally manufactured by Greenlight itself,
which sets the <code>work_dir</code> attribute to a path that contains the
current process ID number. Just before the process exits, Greenlight
destroys the working tree. This way, concurrent processes never try
to use the same working tree, which would be a mess.</p>
<p>When Greenlight needs to operate on the repository, it uses its
<code>git_util</code> object directly. It also creates a <code>submission</code> object to
represent the submitted branch, and it installs the <code>git_util</code> object
into the submission object, so that the submission object can also
operate on the repository. For example, the submission object may ask
its <code>git_util</code> object if it needs to be rebased onto some other
branch, and if so to please do it. So:</p>
<ul>
<li>Greenlight has a <code>submission</code>.</li>
<li><code>submission.git</code> is the <code>git_util</code> object that deals with Git.</li>
<li><code>submission.git.work_dir</code> is the path to the per-process temporary working tree.</li>
</ul>
<p>Greenlight's main purpose is to track these submission objects, and it
has a database of them. To save time when writing the initial
implementation, instead of using a real database, I had Greenlight use
<a href="https://docs.python.org/3.6/library/pickle.html">Python's “pickle”
feature</a> to pickle
the list of submissions.</p>
<p>Someone would submit a branch, and Greenlight would pickle the
submission. The submission contained its <code>git_util</code> object, and that
got pickled along with the rest. Then Greenlight would exit and, just
before doing so, it would destroy its temporary working tree.</p>
<p>Then later, when someone else wanted to approve the submission for
publication, Greenlight would set up a different working tree with its
new process ID, and unpickle the submission. But the submission's
<code>git.work_dir</code> had been pickled with the <em>old</em> path, which no longer
existed.</p>
<p>The context manager was working just fine. It was setting
<code>GIT_WORK_TREE</code> to the <code>work_dir</code> value in the <code>git_util</code> object. But
the object was obsolete and its <code>work_dir</code> value pointed to a
directory that had been destroyed!</p>
<p>Adding to the confusion:</p>
<ol>
<li><p>Greenlight's own <code>git_util</code> object was always fresh and had the
right path in it, so Git commands run directly by Greenlight all
worked properly.</p></li>
<li><p>Any new <code>submission</code> objects created by Greenlight would have the
right path, so Git commands run by fresh submissions also worked
properly.</p></li>
<li><p>Greenlight doesn't always destroy the working tree when it exits.
If it exits abnormally, it leaves the working tree intact, for a
later autopsy. And the unpickled submission would work perfectly
if the working tree still existed, and it would be impossible to
reproduce the problem!</p></li>
</ol>
<p>Toward the end of the previous article, I said:</p>
<blockquote>
<p>I <em>suspect</em> I'm being sabotaged somewhere by Python's weird implicit
ideas of scope and variable duration, but I don't know. Yet.</p>
</blockquote>
<p>For the record, then: The issue was indeed one of variable duration.
But Python's weird implicit ideas were, in this instance, completely
blameless. Instead the issue was cause by a software component even
more complex and more poorly understood: “Dominus”.</p>
<p>This computer stuff is amazingly complicated. I don't know how anyone
gets anything done.</p>
Necklaces and bracelets
https://blog.plover.com/2018/12/02#necklaces-and-bracelets
<p>There are combinatorial objects called
<a href="https://en.wikipedia.org/wiki/Necklace_%28combinatorics%29">necklaces</a>
and
<a href="https://en.wikipedia.org/wiki/Bracelet_%28combinatorics%29">bracelets</a>
and I can never remember which is which.</p>
<p>Both are finite sequences of things (typically symbols) where the
start point is not important. So the bracelet <code>ABCDE</code> is considered
to be the same as the bracelets <code>BCDEA</code>, <code>CDEAB</code>, <code>DEABC</code>, and
<code>EABCD</code>.</p>
<p>One of the two <em>also</em> disregards the direction you go, so that
<code>ABCDE</code> is also considered the same as <code>EDCBA</code> (and so also <code>DCBAE</code>,
etc.). But which? I have to look it up every time.</p>
<p>I have finally thought of a mnemonic. In a necklace, the direction is
important, because to reverse an actual necklace you have to pull it
off over the wearer's head, turn it over, and put it back on. But in
a bracelet the direction is not important, because it could be on
either wrist, and a bracelet on the left wrist is the same as the
reversed bracelet on the right wrist.</p>
<p>Okay, silly, maybe, but I think it's going to work.</p>
Another day, another bug. No, four bugs.
https://blog.plover.com/2018/12/02#greenlight-cm
<p>I'm working on a large and wonderful project called “Greenlight”.
It's a Git branch merging service that implements the following
workflow:</p>
<ol>
<li>Submitter submits a branch to Greenlight (<code>greenlight submit my-topic-branch</code>)</li>
<li>Greenlight analyzes the branch to decide if it changes anything
that requires review and signoff</li>
<li>If so, it contacts the authorized reviewers, who then inform
Greenlight that they approve the changes (<code>greenlight approve 03a46dc1</code>)</li>
<li>Greenlight merges the branch to <code>master</code> and publishes the result
to the central repository</li>
</ol>
<p>Of course, there are many details elided here.</p>
<p>Multiple instances of Greenlight share a local repository, but to avoid
confusion each has its own working tree. In Git you can configure
these by setting <code>GIT_DIR</code> and <code>GIT_WORK_TREE</code> environment variables,
respectively. When Greenlight needs to run a Git command, it does so
like this:</p>
<pre><code> with env_var("GIT_DIR", self.repo_dir):
with env_var("GIT_WORK_TREE", self.work_dir):
result = subprocess.run(command, ...)
</code></pre>
<p>The <code>env_var</code> here is a Python context manager that saves the old
environment, sets the new environment variable, and then when the body
of the block is complete, it restores the environment to the way it
was. This worked in testing every time.</p>
<p>But the first time a beta tester ran the <code>approve</code> command, Greenlight
threw a fatal exception. It was trying to run <code>git checkout --quiet
--detach</code>, and this was failing, with Git saying</p>
<pre><code>fatal: this operation must be run in a work tree
</code></pre>
<p>Where was the <code>GIT_WORK_TREE</code> setting going? I still don't know. But
in the course of trying to track the problem down, I changed the code
above to:</p>
<pre><code> with env_var("GIT_DIR", self.repo_dir, "GIT_WORK_TREE", self.work_dir):
result = subprocess.run(command, ...)
</code></pre>
<p>and the problem, whatever it was, no longer manifested.</p>
<p>But this revealed a second bug: Greenlight no longer failed in the
approval phase. It went ahead and merged the branch, and then tried
to publish the merge with <code>git push origin ...</code>. But the push was
rejected.</p>
<p>This is because the <code>origin</code> repository had an <code>update</code> hook that ran
on every push, which performed the same review analysis that Greenlight
was performing; one of Greenlight's main purposes is to be a
replacement for this hook. To avoid tying up the main repository for
too long, this hook had a two-minute timeout, after which it would die
and reject the push. This had only happened very rarely in the past,
usually when someone was inadvertently trying to push a malformed
branch. For example, they might have rebased all of <code>master</code> onto
their topic branch. In this case, however, the branch really was
legitimately enormous; it contained over 2900 commits.</p>
<p>“Oh, right,” I said. “I forgot to add the exception to the hook that
tells it that it can immediately approve anything pushed by
Greenlight.” The hook can assume that if the push comes from
Greenlight, it has already been checked and authorized.</p>
<p>Pushes are happening via SSH, and Greenlight has its own SSH identity,
which is passed to the hook itself in the <code>GL_USERNAME</code> variable.
Modifying the hook was easy: I just added:</p>
<pre><code> if environ["GL_USERNAME"] == 'greenlight':
exit(0)
</code></pre>
<p>This didn't work. My first idea was that Greenlight's public SSH key
had not been installed in the <code>authorized_keys</code> file in the right
place. When I grepped for <code>greenlight</code> in the <code>authorized_keys</code> file,
there were no matches. The key was actually there, but in Gitlab the
<code>authorized_keys</code> file doesn't have actual usernames in it. It has
internal userids, which are then mapped to <code>GL_USERNAME</code> variables by
some other entity. So I chased that wild goose for a while.
Eventually I determined that the key <em>was</em> in the right place, but
that the name of the Greenlight identity on the receiving side was not
<code>greenlight</code> but <code>bot-greenlight</code>, which I had forgotten.</p>
<p>So I changed the exception to say:</p>
<pre><code> if environ["GL_USERNAME"] == 'bot-greenlight':
exit(0)
</code></pre>
<p>and it still didn't work. I eventually discovered that when
Greenlight did the push, the <code>GL_USERNAME</code> was actually set to <code>mjd</code>.</p>
<p>“Oh, right,” I said. “I forgot to have Greenlight use its own
SSH credentials in the <code>ssh</code> connection.”</p>
<p>The way you do this is to write a little wrapper program that obtains
the correct credentials and runs <code>ssh</code>, and then you set <code>GIT_SSH</code> to
point to the wrapper. It looks like this:</p>
<pre><code> #!/usr/bin/env bash
export -n SSH_CLIENT SSH_TTY SSH_AUTH_SOCK SSH_CONNECTION
exec /usr/bin/ssh -i $HOME/.ssh/identity "$@"
</code></pre>
<p>But wait, why hadn't I noticed this before? Because, apparently,
every single person who had alpha-tested Greenlight had had their own
credentials stored in <code>ssh-agent</code>, and every single one had had
agent-forwarding enabled, so that when Greenlight tried to use <code>ssh</code>
to connect to the Git repository, SSH duly forwarded their credentials
along and the pushes succeeded. Amazing.</p>
<p>With these changes, the publication went through. I committed the
changes to the SSH credential stuff, and some other unrelated changes,
and I looked at what was left to see what had actually fixed the
original bug. Every change but one was to add diagnostic messages and
logging. The fix for the original bug had been to replace the nested
context managers with a single context manager. This was so
unexpected that I wondered if the real problem was nondeterministic
and if some of the debugging messages had somehow perturbed it. But I
removed everything but the context manager change and ran another
test, which succeeded. By then I was five and half hours into the
debugging and I didn't have any energy left to actually understand
what the problem had been. I still don't know.</p>
<p>If you'd like to play along at home, the context manager looks like
this, and did not change during the debugging process:</p>
<pre><code> from contextlib import contextmanager
@contextmanager
def env_var(*args):
# Save old values of environment variables in `old`
# A saved value of `None` means that the variable was not there before
old = {}
for i in range(len(args)//2):
(key, value) = (args[2*i : 2*i+2])
old[key] = None
if key in os.environ:
old[key] = os.environ[str(key)]
if value is None: os.environ.pop(str(key), "dummy")
else:
os.environ[str(key)] = str(value)
yield
# Undo changes from versions saved in `old`
for (key, value) in old.items():
if value is None: os.environ.pop(str(key), "dummy")
else: os.environ[str(key)] = value
</code></pre>
<p>I <em>suspect</em> I'm being sabotaged somewhere by Python's weird implicit
ideas of scope and variable duration, but I don't know. Yet.</p>
<p>This computer stuff is amazingly complicated. I don't know how anyone
gets anything done.</p>
<p>[ Addendum 20181204: <a href="https://blog.plover.com/prog/bug/greenlight-cm-2.html">I figured it
out</a>. ]</p>
How many kinds of polygonal loops? (part 2)
https://blog.plover.com/2018/11/30#polygonal-loops-2
<p><a href="https://blog.plover.com/math/polygonal-loops.html">I recently asked about these</a>:</p>
<p><img class="center" src="https://pic.blog.plover.com/math/polygonal-loops-2/pentagons.svg" alt="
Four displays, each with five dark gray dots arranged at the vertices
of a regular pentagon. In each display the dots are connected with
purple lines, but each in a different order. If the dots were
numbered 0-1-2-3-4 in clockwise order, the four figures have purple
lines connecting them, respectively, in the orders
0-1-2-3-4-0, 0-1-3-2-4-0, 0-2-1-4-3-0, and 0-2-4-1-3-0. The first of
these is a plain pentagon, and the last is a five-pointed star. The
middle two are less symmetric." /></p>
<p>And I said I thought there were nine analogous figures with six
points.</p>
<p>Rahul Narain referred me to <a href="https://math.stackexchange.com/q/2986900/856">a recent discussion of almost this exact
question on Math
Stackexchange</a>. (Note
that the discussion there considers two figures different if they are
reflections of one another; I consider them the same.) The answer
turns out to be <a href="http://oeis.org/A000940">OEIS A000940</a>. I had said:</p>
<blockquote>
<p>… for <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24N%3d6%24">, I found it hard to enumerate. I think there are nine
shapes but I might have missed one, because I know I kept making
mistakes in the enumeration …</p>
</blockquote>
<p>I missed <em>three</em>. The nine I got were:</p>
<p><img class="center" src="https://pic.blog.plover.com/math/polygonal-loops-2/hexagons.svg" alt="This time
there are nine displays, each with six dots. The connections are,
respectively,
012345 (a hexagon), 015432, 032145 (two diamonds),
015234 (highly irregular), 014523 (three triangles that share a vertex
in the center), 013254, 023154, 031254, and 035142."/></p>
<p>And the three I missed are:</p>
<p><img class="center" src="https://pic.blog.plover.com/math/polygonal-loops-2/missing%20hexagons.svg" alt="Three
more hexagons, this time connected as follows:
014253, 013524, and 015342"/></p>
<p>I had tried to break them down by the arrangement of the outside ring
of edges, which can be described by a composition. The first two of these have type
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%241%2b1%2b1%2b1%2b2%24"> (which I missed completely; I thought there were none of
this type) and the other has type <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%241%2b2%2b1%2b2%24">, the same as the
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24015342%24"> one in the lower right of the previous diagram.</p>
<p>I had ended by saying:</p>
<blockquote>
<p>I would certainly not trust myself to hand-enumerate the
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24N%3d7%24"> shapes.</p>
</blockquote>
<p>Good call, Mr. Dominus! I considered filing this under <a
href="https://blog.plover.com/oops/">“oops”</a> but I decided that although I had
gotten the wrong answer, my confidence in it had been adequately low.
On one level it was a mistake, but on a higher and more important
level, I did better.</p>
<p>I am going to try the (Cauchy-Frobenius-)Burnside-(Redfield-)Pólya
lemma on it next and see if I can get the right answer.</p>
<p>Thanks again to Rahul Narain for bringing this to my attention.</p>
How many kinds of polygonal loops?
https://blog.plover.com/2018/11/29#polygonal-loops
<p>Take <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24N%24"> equally-spaced points on a circle. Now connect them in a
loop: each point should be connected to exactly two others, and each
point should be reachable from the others. How many geometrically
distinct shapes can be formed?</p>
<p>For example, when <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24N%3d5%24">, these four shapes can be formed:</p>
<p><img class="center" src="https://pic.blog.plover.com/math/polygonal-loops/pentagons.svg" alt="
Four displays, each with five dark gray dots arranged at the vertices
of a regular pentagon. In each display the dots are connected with
purple lines, but each in a different order. If the dots were
numbered 0-1-2-3-4 in clockwise order, the four figures have purple
lines connecting them, respectively, in the orders
0-1-2-3-4-0, 0-1-3-2-4-0, 0-2-1-4-3-0, and 0-2-4-1-3-0. The first of
these is a plain pentagon, and the last is a five-pointed star. The
middle two are less symmetric." /></p>
<p>(I phrased this like a geometry problenm, but it should be clear it's
actually a combinatorics problem. But it's much easier to express as
a geometry problem; to talk about the combinatorics I have to ask you
to consider a permutation <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> where <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%28i%c2%b11%29%e2%89%a0P%28i%29%c2%b11%24"> blah blah blah…)</p>
<p>For <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24N%3c5%24"> it's easy. When <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24N%3d3%24"> it is always a triangle. When <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24N%3d4%24"> there are
only two shapes: a square and a bow tie.</p>
<p>But for <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24N%3d6%24">, I found it hard to enumerate. I think there are nine
shapes but I might have missed one, because I know I kept making
mistakes in the enumeration, and I am not sure they are all corrected:</p>
<p><img class="center" src="https://pic.blog.plover.com/math/polygonal-loops/hexagons.svg" alt="This time
there are nine displays, each with six dots. The connections are,
respectively,
012345 (a hexagon), 015432, 032145 (two diamonds),
015234 (highly irregular), 014523 (three triangles that share a vertex
in the center), 013254, 023154, 031254, and 035142."/></p>
<p>It seems like it ought not to be hard to enumerate and count these,
but so far I haven't gotten a good handle on it. I produced the
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24N%3d6%24"> display above by considering the
<a href="https://en.wikipedia.org/wiki/Composition_%28combinatorics%29">compositions</a> of the number <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%246%24">:</p>
<table align="center" cellpadding="1" cellspacing="10">
<tr><th> Composition <th> How many<br> loops?
<tr><td align="right"> 6 <td align="right"> 1
<tr bgcolor="#e0e0e0"><td align="right"> 1+5 <td align="right"> —
<tr><td align="right"> 2+4 <td align="right"> 1
<tr><td align="right"> 3+3 <td align="right"> 1
<tr bgcolor="#e0e0e0"><td align="right"> 1+1+4 <td align="right"> —
<tr><td align="right"> 1+2+3 <td align="right"> 1
<tr><td align="right"> 2+2+2 <td align="right"> 2
<tr bgcolor="#e0e0e0"><td align="right"> 1+1+1+3 <td align="right"> —
<tr><td align="right"> 1+1+2+2 <td align="right"> 1
<tr><td align="right"> 1+2+1+1 <td align="right"> 1
<tr bgcolor="#e0e0e0"><td align="right"> 1+1+1+1+2 <td align="right"> —
<tr><td align="right"> 1+1+1+1+1+1 <td align="right"> 1
<tr bgcolor="#eeeeee"><td>Total<td align="right">9 (?)
</table>
<p>(Actually it's the compositions, modulo
<a href="https://en.wikipedia.org/wiki/Bracelet_%28combinatorics%29">bracelet</a> symmetries — that is,
modulo the action of the dihedral group.)</p>
<p>But this is fraught with opportunities for mistakes in both
directions. I would certainly not trust myself to hand-enumerate the
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24N%3d7%24"> shapes.</p>
<p>[ Addendum: For <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24N%3d6%24"> there are <em>12</em> figures, not 9. For <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24N%3d7%24">,
there are 39. <a href="https://blog.plover.com/math/polygonal-loops-2.html">Further
details</a>. ]</p>
60-degree angles on a lattice
https://blog.plover.com/2018/11/25#60-degree-angles
<p>A couple of years back I was thinking about <a href="https://blog.plover.com/math/law-of-cosines.html">how to draw a good
approximation to an equilateral triangle on a piece of graph
paper</a>. There are
no lattice points that are <em>exactly</em> the vertices of an equilateral
triangle, but you can come close, and one way to do it is to find
integers <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a%24"> and <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24b%24"> with <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5cfrac%20ba%5capprox%20%5csqrt%203%24">, and then
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clangle%200%2c%200%5crangle%2c%20%5clangle%202a%2c%200%5crangle%2c%24"> and <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clangle%20a%2c%0ab%5crangle%24"> are almost an equilateral triangle.</p>
<p>But today I came back to it for some reason and I wondered if it would
be possible to get an angle closer to 60°, or numbers that were simpler,
or both, by <em>not</em> making one of the sides of the
triangle perfectly horizontal as in that example.</p>
<p>So okay, we want to find <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%20%3d%20%5clangle%20a%2c%20b%5crangle%24"> and <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24Q%20%3d%20%5clangle%0ac%2cd%5crangle%24"> so that the angle <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5calpha%24"> between the rays
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5coverrightarrow%7bOP%7d%24"> and <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5coverrightarrow%7bOQ%7d%24"> is as close as
possible to <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5cfrac%5cpi%203%24">.</p>
<p>The first thing I thought of was that the dot product <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%5ccdot%20Q%20%3d%0a%7cP%7c%7cQ%7c%5ccos%5calpha%24">, and <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%5ccdot%20Q%24"> is super-easy to calculate, it's
just <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24ac%2bbd%24">. So we want $$\frac{ad+bc}{|P||Q|} = \cos\alpha \approx \frac12,$$ and
everything is simple, except that <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%7cP%7c%7cQ%7c%20%3d%0a%5csqrt%7ba%5e2%2bb%5e2%7d%5csqrt%7bc%5e2%2bd%5e2%7d%24">, which is not so great.</p>
<p>Then I tried something else, using high-school trigonometry.
Let <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5calpha_P%24"> and <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5calpha_Q%24"> be the angles that the rays make
with the <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24x%24">-axis. Then <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5calpha%20%3d%20%5calpha_Q%20%2d%20%5calpha_P%20%3d%20%5ctan%5e%7b%2d1%7d%0a%5cfrac%20dc%20%2d%20%5ctan%5e%7b%2d1%7d%20%5cfrac%20ba%24">, which we want close to <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5cfrac%5cpi3%24">.</p>
<p>Taking the tangent of both sides and applying the formula
$$\tan(q-p) = \frac{\tan q - \tan p}{1 + \tan q \tan p}$$
we get $$ \frac{\frac dc - \frac ba}{1 + \frac dc\frac ba} \approx \sqrt3.$$
Or simplifying a bit, the super-simple $$\frac{ad-bc}{ac+bd} \approx \sqrt3.$$</p>
<p>After I got there I realized that my dot product idea had <em>almost</em>
worked. To get rid of the troublesome <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%7cP%7c%7cQ%7c%24">
you should consider
the <em>cross</em> product also. Observe that the magnitude of <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%5ctimes%20Q%24">
is <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%7cP%7c%7cQ%7c%5csin%5calpha%24">, and is also
$$\begin{vmatrix}
a & b & 0 \\
c & d & 0 \\
1 & 1 & 1 \end{vmatrix} = ad - bc$$
so that <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5csin%5calpha%20%3d%20%5cfrac%7bad%2dbc%7d%7b%7cP%7c%7cQ%7c%7d%24">. Then if we divide, the
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%7cP%7c%7cQ%7c%24"> things cancel out nicely:
$$\tan\alpha = \frac{\sin\alpha}{\cos\alpha} = \frac{ad-bc}{ac+bd}$$
which we want to be as close as possible to <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5csqrt%203%24">.</p>
<p>Okay, that's fine. Now we need to find some integers <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a%2cb%2cc%2cd%24"> that
do what we want. The usual trick, “see what happens if <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a%3d0%24">”, is
already used up, since that's what the previous article was about.
So let's look under the next-closest lamppost, and let <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a%3d1%24">. Actually we'll
let <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24b%3d1%24"> instead to keep things more horizonal. Then, taking <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5cfrac74%24">
as our approximation for <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5csqrt3%24">, we want</p>
<p>$$\frac{ad-c}{ac+d} = \frac74$$</p>
<p>or equivalently $$\frac dc = \frac{7a+4}{4a-7}.$$</p>
<p>Now we just tabulate <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%247a%2b4%24"> and <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%244a%2d7%24"> looking for nice fractions:</p>
<table align='center' cellpadding=1 cellspacing=1>
<tr><th><img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a%24"><th><img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24d%20%3d%24"><br/><img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%247a%2b4%24"><th><img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24c%3d%24"><br/><img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%244a%2d7%24">
<tr> <td align="right">2<td align="right">18<td align="right">1
<tr bgcolor="pink"> <td align="right">3<td align="right">25<td align="right">5
<tr> <td align="right">4<td align="right">32<td align="right">9
<tr> <td align="right">5<td align="right">39<td align="right">13
<tr> <td align="right">6<td align="right">46<td align="right">17
<tr> <td align="right">7<td align="right">53<td align="right">21
<tr bgcolor="lightyellow"> <td align="right">8<td align="right">60<td align="right">25
<tr> <td align="right">9<td align="right">67<td align="right">29
<tr> <td align="right">10<td align="right">74<td align="right">33
<tr> <td align="right">11<td align="right">81<td align="right">37
<tr> <td align="right">12<td align="right">88<td align="right">41
<tr> <td align="right">13<td align="right">95<td align="right">45
<tr> <td align="right">14<td align="right">102<td align="right">49
<tr> <td align="right">15<td align="right">109<td align="right">53
<tr> <td align="right">16<td align="right">116<td align="right">57
<tr> <td align="right">17<td align="right">123<td align="right">61
<tr bgcolor="lightyellow"> <td align="right">18<td align="right">130<td align="right">65
<tr> <td align="right">19<td align="right">137<td align="right">69
<tr> <td align="right">20<td align="right">144<td align="right">73
</table>
<p>Each of these gives us a <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clangle%20c%2cd%5crangle%24"> point, but some are
much better than others. For example, in line 3, we have
take <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clangle%205%2c25%5crangle%24"> but we can use <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clangle%201%2c5%5crangle%24">
which gives the same <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5cfrac%20dc%24"> but is simpler.
We still get <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5cfrac%7bad%2dbc%7d%7bac%2bbd%7d%20%3d%20%5cfrac%2074%24"> as we want.</p>
<p>Doing this gives us the two points <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%3d%5clangle%203%2c1%5crangle%24"> and
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24Q%3d%5clangle%201%2c%205%5crangle%24">. The angle between <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5coverrightarrow%7bOP%7d%24">
and <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5coverrightarrow%7bOQ%7d%24"> is then <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%2460%2e255%c2%b0%24">. This is exactly the
same as in the approximately equilateral <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clangle%200%2c%200%5crangle%2c%0a%5clangle%208%2c%200%5crangle%2c%24"> and <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clangle%204%2c%207%5crangle%24"> triangle I
mentioned before, but the numbers could not possibly be easier to
remember. So the method is a success: I wanted simpler numbers or a
better approximation, and I got the same approximation with simpler
numbers.</p>
<blockquote>
<p>To draw a 60° angle on graph paper, mark <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%3d%5clangle%203%2c1%5crangle%24">
and <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24Q%3d%5clangle%201%2c%205%5crangle%24">, draw lines to them from the origin
with a straightedge, and there is your 60° angle, to better than a
half a percent.</p>
</blockquote>
<p><img src="https://pic.blog.plover.com/math/60-degree-angles/good-60.png" class="center"
alt="A graph of the lines 3y=x and y=5x, with the points
(3,1) and (1,5) marked, demonstrating that the angle between the
lines is very close to 60 degrees."
/></p>
<p>There are some other items in the table (for example row 18 gives
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%3d%5clangle%2018%2c1%5crangle%24"> and <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24Q%3d%5clangle%201%2c%202%5crangle%24">) but because
of the way we constructed the table, every row is going to give us the
same angle of <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%2460%2e225%c2%b0%24">, because we approximated
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5csqrt3%5capprox%5cfrac74%24"> and <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%2460%2e225%c2%b0%20%3d%20%5ctan%5e%7b%2d1%7d%5cfrac74%24">. And the
chance of finding numbers better than <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clangle%203%2c1%5crangle%24"> and
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clangle%201%2c%205%5crangle%24"> seems slim. So now let's see if we can
get the angle closer to exactly <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%2460%c2%b0%24"> by using a better
approximation to <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5csqrt3%24"> than <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5cfrac%2074%24">.</p>
<p>The next convergents to <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5csqrt%203%24"> are <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5cfrac%7b19%7d%7b11%7d%24"> and
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5cfrac%7b26%7d%7b15%7d%24">. I tried the same procedure for <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5cfrac%7b19%7d%7b11%7d%24">
and it was a bust. But <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5cfrac%7b26%7d%7b15%7d%24"> hit the jackpot: <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a%3d4%24">
gives us <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%2415a%2d26%20%3d%2034%24"> and <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%2426a%2d15%3d119%24">, both of which are
multiples of 17. So the points are <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%3d%5clangle%204%2c1%5crangle%24"> and
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24Q%3d%5clangle%202%2c%207%5crangle%24">, and this time the angle between the rays is
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5ctan%5e%7b%2d1%7d%5cfrac%7b26%7d%7b15%7d%20%3d%2060%2e018%c2%b0%24">. This is as accurate as anyone
drawing on graph paper could possibly need; on a circle with a
one-mile radius it is an error of 20 inches.</p>
<p><img src="https://pic.blog.plover.com/math/60-degree-angles/better-60.png" class="center"
alt="A very similar plot, this time with the lines 4y=x and 7y=2x"
/></p>
<p>Of course, the triangles you get are no longer equilateral, not even close. That
first one has sides of <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5csqrt%7b10%7d%2c%20%5csqrt%7b20%7d%2c%20%24"> and <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5csqrt%7b26%7d%24">,
and the second one has sides of <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5csqrt%7b17%7d%2c%20%5csqrt%7b40%7d%2c%20%24"> and
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5csqrt%7b53%7d%24">. But! The slopes of the lines are so simple, it's easy to
construct equilateral triangles with a straightedge and a bit of easy measuring.
Let's do it on the <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%2460%2e018%c2%b0%24"> angle and see how it looks.</p>
<p><img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5coverrightarrow%7bOP%7d%24"> has slope <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5cfrac14%24">, so the perpendicular to it
has slope <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%2d4%24">, which means that you can draw the perpendicular by
placing the straightedge between <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> and some point <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%2bx%5clangle%20%2d1%2c%0a4%5crangle%24">, say <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clangle%202%2c%209%5crangle%24"> as in the picture. The straightedge should have slope
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%2d4%24">, which is very easy to arrange: just imagine the little squares
grouped into stacks of four, and have the straightedge go through
opposite corners of each stack. The line won't necessarily intersect
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5coverrightarrow%7bOQ%7d%24"> anywhere great, but it doesn't need to,
because we can just mark the intersection, wherever it is:</p>
<p><img src="https://pic.blog.plover.com/math/60-degree-angles/triangle-1.png" class="center"
alt="Same as the previous plot, but now there is another line y-1=-4(x-4)
drawn through (4, 1) and its intersection with the other line, near
(2¼, 8)."
/></p>
<p>Let's call that intersection <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24A%24"> for “apex”.</p>
<p>The point opposite to <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24O%24"> on the other side of <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%24"> is even easier;
it's just <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%27%3d2P%20%3d%5clangle%208%2c%202%5crangle%24">. And the segment <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24P%27A%24"> is the
third side of our equilateral triangle:</p>
<p><img src="https://pic.blog.plover.com/math/60-degree-angles/triangle-2.png" class="center"
alt="The previous diagram, with the third side of the equilateral triangle drawn in."
/></p>
<p>This triangle is geometrically similar to a triangle with vertices
at
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clangle%200%2c%200%5crangle%2c%0a%5clangle%2030%2c%200%5crangle%2c%24"> and <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5clangle%2015%2c%2026%5crangle%24">, and the angles
are just close to 60°, but it is <em>much</em> smaller.</p>
<p>Woot!</p>
I love the dodecahedron
https://blog.plover.com/2018/11/19#dodecahedral-3-coloring
<p>I think I forgot to mention that I was looking recently at hamiltonian
cycles on a dodecahedron. The dodecahedron has 30 edges and 20
vertices, so a hamiltonian path contains 20 edges and omits 10. It
turns out that it is possible to color the edges of the dodecahedron
in three colors so that:</p>
<ul>
<li>Every vertex is incident to one edge of each color</li>
<li>The edges of any two of the three colors form a hamiltonian cycle</li>
</ul>
<p><img class="center" border=0
src="https://pic.blog.plover.com/math/dodecahedral-3-coloring/dodecahedron%20-%20vertex%20-%20hamiltonian cycles.svg"
alt="Dear visually impaired people: I try to provide clear
descriptions of illustrations, but here I was stumped about what I
could say that would be helpful that I had not already said. I would
be grateful for your advice and suggestions." /></p>
<p>Marvelous!</p>
<p>(In this presentation, I have taken one of the vertices and sent it
away to infinity. The three edges with arrowheads are all attached to
that vertex, off at infinity, and the three faces incident to it
have been stretched out to cover the rest of the plane.)</p>
<p>Every face has five edges and there are only three colors, so the
colors can't be distributed evenly around a face. Each face
is surrounded by two edges of one color, two of a second color, and
only one of the last color. This naturally divides the 12 faces into
three classes, depending on which color is assigned to only one edge
of that face.</p>
<p><img class="center" border=0
src="https://pic.blog.plover.com/math/dodecahedral-3-coloring/dodecahedron%20-%20vertex%20-%203-coloring.svg" alt="This is
the same picture as before, but each of the 12 regions of the plane
has been annotated with a large colored circle, the same as the color
of which the region has only one boundary edge." /></p>
<p>Each class contains two pairs of two adjacent
pentagons, and each adjacent pair is adjacent to the four pairs in the
other classes but not to the other pair in its own class.</p>
<p>Each pair shares a single edge, which we might call its “hinge”, shown
here as dotted lines. Each pair
has 8 vertices, of which two are on its hinge, four are adjacent to
the hinge, and two are not near of the hinge. These last two vertices
are always part of the hinges of the pairs of a different class.</p>
<p>I could think about this for a long time, and probably will. There is
plenty more to be seen, but I think there is something else I was
supposed to be doing today, let me think…. Oh yes! My “job”! So I will
leave you to go on from here on your own.</p>
<p>[ Addendum 20181203: David Eppstein has written a much longer and more
detailed article about <a href="https://11011110.github.io/blog/2018/12/02/triply-hamiltonian-edge.html">triply-Hamiltonian edge
colorings</a>,
using this example as a jumping-off point. ]</p>
How do you make a stella octangula?
https://blog.plover.com/2018/11/17#stella-octangula
<p>Yesterday Katara asked me out of nowhere “When you make a stella
octangula, do you build it up from an octahedron or a tetrahedron?”
<a href="https://en.wikipedia.org/wiki/stella_octangula">Stella octangula</a> was her favorite polyhedron
eight years ago.</p>
<p>“Uh,” I said. “Both?”</p>
<p>Then she had to make one to see what I meant. You can start with a
regular
octahedron:</p>
<p><a href="https://pic.blog.plover.com/math/stella-octangula/1.jpg"><img class="center" border=0
src="https://pic.blog.plover.com/math/stella-octangula/1-th.jpg" alt="a regular octahedron made of six steel
ball bearings and twelve blue and green magnetic struts" /></a></p>
<p>Then you erect spikes onto four of the octahedron's faces; this
produces a regular tetrahedron:</p>
<p><a href="https://pic.blog.plover.com/math/stella-octangula/2.jpg"><img class="center" border=0
src="https://pic.blog.plover.com/math/stella-octangula/2-th.jpg" alt="A very similar octahedron, this time
with an orange tripod attached to four of its eight faces, forming an
orange tetrahedron with a blue and green octahedron embedded in it" /></a></p>
<p>Then you erect spikes onto the other four of the octahedron's faces.
Now you have a stella octangula.</p>
<p><a href="https://pic.blog.plover.com/math/stella-octangula/3.jpg"><img class="center" border=0
src="https://pic.blog.plover.com/math/stella-octangula/3-th.jpg" alt="The octahedron from before, but with
red tripods attached to its other four faces, making eight tripods in
all. The final result looks like interpenetrating red and orange
tetrahedra, with the original octahedron in their intersection" /></a></p>
<p>So yeah, both. Or instead of starting with a unit octahedron and
erecting eight spikes of size 1, you can start with a unit tetrahedron
and erect four spikes of size ½. It's both at once.</p>
Counting paths through polyhedra
https://blog.plover.com/2018/11/14#polyhedral-paths
<p>A while back <a href="https://math.stackexchange.com/q/2577433/25554">someone asked on math stack exchange how many paths
there were of length <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24N%24"> from one vertex of a dodecahedron to the
opposite vertex</a>. The
vertices are distance 5 apart, so for <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24N%3c5%24"> the answer is zero, but
the paths need not be simple, so the number grows rapidly with <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24N%24">;
there are 58 million paths of length 19.</p>
<p>This is the kind of thing that the computer answers easily, so that's
where I started, and unfortunately that's also where I finished,
saying:</p>
<blockquote>
<p>I'm still working out a combinatorial method of calculating the
answer, and I may not be successful.</p>
</blockquote>
<p>Another user reminded me of this and I took another whack at it. I
couldn't remember what my idea had been last year, but my idea this
time around was to think of the dodecahedron as the Cayley graph for a
group, and then the paths are expressions that multiply out to a
particular group element.</p>
<p>I started by looking at a tetrahedron instead of at a dodecahedron, to
see how it would work out. Here's a tetrahedron.</p>
<p><img class="center" src="https://pic.blog.plover.com/math/polyhedral-paths/tetrahedron - labeled.svg"/></p>
<p>Let's say we're counting paths from the center vertex to one of the
others, say the one at the top. (Tetrahedra don't have opposite
vertices, but that's not an important part of the problem.) A path is
just a list of edges, and each edge is labeled with a letter <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a%24">,
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24b%24">, or <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24c%24">. Since each vertex has exactly one edge with each
label, every sequence of <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a%24">'s, <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24b%24">'s, and <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24c%24">'s represents a
distinct path from the center to somewhere else, although not
necessarily to the place we want to go. Which of these paths end at
the bottom vertex?</p>
<p>The edge labeling I chose here lets us play a wonderful trick.
First, since any edge has the same label at both ends, the path <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24x%24">
always ends at the same place as <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24xaa%24">, because the first <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a%24"> goes
somewhere else and then the second <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a%24"> comes back again, and
similarly <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24xbb%24"> and <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24xcc%24"> also go to the same place. So if we
have a path that ends where we want, we can insert any number of pairs
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24aa%2c%20bb%2c%20%24"> or <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24cc%24"> and the new path will end at the same place.</p>
<p>But there's an even better trick available. For any starting point,
and any letters <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24x%24"> and <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24y%24">,
the path <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24xy%24"> always ends at the same place as <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24yx%24">. For example,
if we start at the middle and follow edge <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24b%24">, then <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24c%24">, we end at
the lower left; similarly if we follow edge <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24c%24"> and then <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24b%24">
we end at the same place, although by a different path.</p>
<p>Now suppose we want to find all the paths of length 7 from the middle
to the top. Such a path is a sequence of a's, b's, and c's of length
7. Every such sequence specifies a different path out of the middle
vertex, but how can we recognize which sequences end at the top
vertex?</p>
<p>Since <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24xy%24"> always goes to the same place as <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24yx%24">, the order of the
seven letters doesn't matter.
A complicated-seeming path like <code>abacbcb</code> must go to the same place
as <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24aabbbcc%24">, the same path with the letters in alphabetical order.
And since <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24xx%24"> always goes back to
where it came from, the path <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24aabbbcc%24"> does to the same place as <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24b%24"></p>
<p>Since the paths we want are those that go to the same place as the
trivial path <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24c%24">, we want paths that have an even number of <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a%24">s
and <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24b%24">s and an odd number of <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24c%24">s. Any path fitting that
description will go to same place as <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24c%24">, which is the top vertex.
It's easy to enumerate such paths:</p>
<table align="center" cellspacing="1" cellpadding=1>
<tr><th>Prototypical<br> path<th>How many?
<tr><td>ccccccc<td align=right>1
<tr><td>cccccaa<td align=right>21
<tr><td>cccccbb<td align=right>21
<tr><td>cccaaaa<td align=right>35
<tr><td>cccaabb<td align=right>210
<tr><td>cccbbbb<td align=right>35
<tr><td>caaaaaa<td align=right>7
<tr><td>caaaabb<td align=right>105
<tr><td>caabbbb<td align=right>105
<tr><td>cbbbbbb<td align=right>7
<tr><td><font size="+1">Total</font><td align=right><font size="+1">547</font>
</table>
<p>Here something like “cccbbbb” stands for all the paths that have three
c's and four b's, in some order; there are <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5cfrac%7b7%21%7d%7b4%213%21%7d%20%3d%2035%24">
possible orders, so 35 paths of this type. If we wanted to consider
paths of arbitrary length, we could use <a href="https://en.wikipedia.org/wiki/Burnside%2527s_lemma">Burnside's
lemma</a>, but I consider the tetrahedron to
have been sufficiently well solved by the observations above (we
counted 547 paths by hand in under 60 seconds) and I don't want to
belabor the point.</p>
<p>Okay! Easy-peasy!</p>
<p>Now let's try cubes:</p>
<p><img class="center" src="https://pic.blog.plover.com/math/polyhedral-paths/cube - face - labeled - highlighted.svg"/></p>
<p>Here we'll consider paths between two antipodal vertices in the upper
right and the lower left, which I've colored much darker gray than the
other six vertices.</p>
<p>The same magic happens as in the tetrahedron. No matter where we
start, and no matter what <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24x%24"> and <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24y%24"> are, the path <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24xy%24"> always
gets us to the same place as <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24yx%24">. So again, if some complicated
path gets us where we want to go, we can permute its components into
any order and get a different path of the same langth to the same
place. For example, starting from the upper left, <code>bcba</code>, <code>abcb</code>, and
<code>abbc</code> all go to the same place.</p>
<p>And again, because <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24xx%24"> always make a trip along one edge and then
back along the same edge, it never goes anywhere. So the three paths
in the previous paragraph also go to the same place as <code>ac</code> and <code>ca</code>
and also <code>aa bcba bb aa aa aa aa bb cc cc cc bb</code>.</p>
<p>We want to count paths from one dark vertex to the other. Obviously
<code>abc</code> is one such, and so too must be <code>bac</code>, <code>cba</code>, <code>acb</code>, and so
forth. There are six paths of length 3.</p>
<p>To get paths of length 5, we must insert a pair of matching letters
into one of the paths of length 3. Without loss of generality we can
assume that we are inserting <code>aa</code>. There are 20 possible orders for
<code>aaabc</code>, and three choices about which pair to insert, for a total of
60 paths.</p>
<p>To get paths of length 7, we must insert two pairs. If the two pairs
are the same, there are <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5cfrac%7b7%21%7d%7b5%21%7d%20%3d%2042%24"> possible orders and 3
choices about which letters to insert, for a total of 126. If the two
pairs are different, there are <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5cfrac%7b7%21%7d%7b3%213%21%7d%20%3d%20140%24"> possible
orders and again 3 choices about which pairs to insert, for a total of
420, and a grand total of <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24420%2b126%20%3d%20546%24"> paths of length 7.
Counting the paths of length 9 is almost as easy. For the general
case, again we could use Burnside's lemma, or at this point <a href="https://oeis.org/search?q=6%2C60%2C546&language=english&go=Search">we could
look up the unusual sequence <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%246%2c%2060%2c%20546%24"> in
OEIS</a>
and find that the number of paths of length <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%242n%2b1%24"> is already known to be
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5cfrac34%289%5en%2d1%29%24">.</p>
<p>So far this technique has worked undeservedly well. The original
problem wanted to use it to study paths on a dodecahedron. Where,
unfortunately, the magic property <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24xy%3dyx%24"> doesn't hold. It is
possible to label the edges of the dodecahedron so that every sequence
of labels determines a unique path:</p>
<p><img class="center" src="https://pic.blog.plover.com/math/polyhedral-paths/dodecahedron - face - hamiltonian cycles - labeled.svg"/></p>
<p>but there's nothing like <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24xy%3dyx%24">. Well, nothing <em>exactly</em> like it.
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24xy%3dyx%24"> is equivalent to <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%28xy%29%5e2%3d1%24">, and here instead we have
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%28xy%29%5e%7b10%7d%3d1%24">. I'm not sure that helps. I will probably need
another idea.</p>
<p>The method fails similarly for the octahedron — which is good, because
I can use the octahedron as a test platform to try to figure out a new
idea. On an octahedron we need to use four kinds of labels because
each vertex has four edges emerging from it:</p>
<p><img class="center" src="https://pic.blog.plover.com/math/polyhedral-paths/octahedron - face - labeled.svg"/></p>
<p>Here again we don't have <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%28xy%29%5e2%3d1%24"> but we <em>do</em> have <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%28xy%29%5e3%20%3d%0a1%24">. So it's possible that if I figure out a good way to enumerate
paths on the octahedron I may be able to adapt the technique to the
dodecahedron. But the octahedron will be <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24%5cfrac%7b10%7d3%24"> times easier.</p>
<p>Viewed as groups, by the way, these path groups are all examples of
Coxeter groups. I'm not sure this is actually a useful observation,
but I've been wanting to learn about Coxeter groups for a long time
and this might be a good enough excuse.</p>
A puzzle about representing numbers as a sum of 3-smooth numbers
https://blog.plover.com/2018/11/13#pow23tab
<p>I think this would be fun for a suitably-minded bright kid of maybe
12–15 years old.</p>
<p>Consider the following table of numbers of the form <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%242%5ei3%5ej%24">:</p>
<table align=center cellspacing="1em" cellpadding="6em">
<tr><td align='right'>1 <td align='right'>3 <td align='right'>9 <td align='right'>27 <td align='right'>81 <td align='right'>243
<tr><td align='right'>2 <td align='right'>6 <td align='right'>18 <td align='right'>54 <td align='right'>162 <td align='right'>…
<tr><td align='right'>4 <td align='right'>12 <td align='right'>36 <td align='right'>108 <td align='right'>… <td align='right'>…
<tr><td align='right'>8 <td align='right'>24 <td align='right'>72 <td align='right'>216 <td align='right'>… <td align='right'>…
<tr><td align='right'>16 <td align='right'>48 <td align='right'>144 <td align='right'>… <td align='right'>… <td align='right'>…
<tr><td align='right'>32 <td align='right'>96 <td align='right'>… <td align='right'>… <td align='right'>… <td align='right'>…
<tr><td align='right'>64 <td align='right'>192 <td align='right'>… <td align='right'>… <td align='right'>… <td align='right'>…
<tr><td align='right'>128 <td align='right'>… <td align='right'>… <td align='right'>… <td align='right'>… <td align='right'>…
</table>
<p>Given a number <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%24">, is is possible to represent <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%24"> as a sum of
entries from the table, with the following constraints:</p>
<ul>
<li>No more than one entry from any column</li>
<li>An entry may only be used if it is in a strictly higher row than any
entry to its left.</li>
</ul>
<p>For example, one may not represent <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%2423%20%3d%202%20%2b%2012%20%2b%209%24">, because the
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%2412%24"> is in a lower row than the <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%242%24"> to its left.</p>
<table align=center cellspacing="1em" cellpadding="6em">
<tr><td align='right'>1 <td align='right'>3 <td align='right'><b
style="color: darkblue">9</b> <td align='right'>27
<tr><td align='right'><b style="color: darkblue">2</b> <td align='right'>6 <td align='right'>18 <td align='right'>54
<tr><td align='right'>4 <td align='right'><b style="color: maroon">12</b> <td align='right'>36 <td align='right'>108
</table>
<p>But <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%2423%20%3d%208%20%2b%206%0a%2b%209%24"> is acceptable, because 6 is higher than 8, and 9 is higher than 6.</p>
<table align=center cellspacing="1em" cellpadding="6em">
<tr><td align='right'>1 <td align='right'>3 <td align='right'><b
style="color: darkblue">9</b> <td align='right'>27
<tr><td align='right'>2 <td align='right'><b style="color: darkblue">6</> <td align='right'>18 <td align='right'>54
<tr><td align='right'>4 <td align='right'>12 <td align='right'>36 <td align='right'>108
<tr><td align='right'><b style="color: darkblue">8</b> <td align='right'>24 <td align='right'>72 <td align='right'>216
</table>
<p>Or, put another way: can we represent any number <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24n%24"> in the form
$$n = \sum_i 2^{a_i}3^{b_i}$$ where the
<img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24a_i%24"> are strictly decreasing and the <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%24b_i%24"> are strictly increasing?</p>
<h4>Spoiler:</h4>
<pre><code><div class="spoiler">
maxpow3 1 = 1
maxpow3 2 = 1
maxpow3 n = 3 * maxpow3 (n `div` 3)
rep :: Integer -> [Integer]
rep 0 = []
rep n = if even n then map (* 2) (rep (n `div` 2))
else (rep (n - mp3)) ++ [mp3] where mp3 = maxpow3 n
</div></pre>
<p></code></p>
<p>Sadly, the representation is not unique. For example, <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%248%2b3%20%3d%202%2b9%24">,
and <img src="https://chart.apis.google.com/chart?chf=bg,s,00000000&cht=tx&chl=%2432%2b24%2b9%20%3d%2032%2b6%2b27%20%3d%208%2b12%3d18%2b27%24">.</p>