<?xml version="1.0" encoding="UTF-16"?>
<!--This file generated by build script at ./Build.hs in solutions repository-->
<rss version="2.0">
  <channel>
    <title>Justin Le's Advent of Code 2020 Reflections</title>
    <description>Reflections for my Advent of Code solutions as I try to solve them all in fun ways using Haskell!</description>
    <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md</link>
    <copyright>Copyright 2020 Justin Le</copyright>
    <language>en-us</language>
    <lastBuildDate>Wed,  1 Dec 2021 18:34:59 EST</lastBuildDate>
    <managingEditor>justin@jle.im</managingEditor>
    <pubDate>Wed,  1 Dec 2021 18:34:59 EST</pubDate>
    <webMaster>justin@jle.im</webMaster>
    <generator>Shake + Template</generator>
    <item>
      <title>Day 25</title>
      <description>&lt;h2 id=&quot;day-25&quot;&gt;Day 25&lt;/h2&gt;
&lt;!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day25.md`.  If you want to edit this, edit
that file instead!
--&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://adventofcode.com/2020/day/25&quot;&gt;Prompt&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day25.hs&quot;&gt;Code&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://mstksg.github.io/advent-of-code-2020/src/AOC.Challenge.Day25.html&quot;&gt;Rendered&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day25.md&quot;&gt;Standalone Reflection Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Merry Christmas everyone, it’s December 25th :D&lt;/p&gt;
&lt;p&gt;The Christmas Problem is usually supposed to be a quick and concise one, since Eric wants people to spend the holiday with their family. This one is a bit obscured in the jargon, but once you sort through it, the solution ends up being pretty tidy :)&lt;/p&gt;
&lt;p&gt;In the end you are exponentiating the number 7 by a given number of times (the loop count) to get the number you see. So you’re solving &lt;code&gt;7^x = &amp;lt;your number&amp;gt;&lt;/code&gt;…so that’s basically a logarithm!&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;&lt;a href=&quot;https://hackage.haskell.org/package/arithmoi&quot;&gt;arithmoi&lt;/a&gt;&lt;/em&gt; library (which I previously used in problems like Day 13) offers a nice discrete logarithm function, so that’s really all we need to use:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Magic&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;20201227&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;magicGroup ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;CyclicGroup&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Integer&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Magic&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; magicGroup &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; cyclicGroup&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;primBase ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;PrimitiveRoot&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Magic&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; primBase &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; isPrimitiveRoot magicGroup &lt;span class=&quot;dv&quot;&gt;7&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-8&quot;&gt;&lt;a href=&quot;#cb1-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-9&quot;&gt;&lt;a href=&quot;#cb1-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;findSecret ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Mod&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Magic&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Natural&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-10&quot;&gt;&lt;a href=&quot;#cb1-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;findSecret &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;fmap&lt;/span&gt; (discreteLogarithm magicGroup primBase)&lt;/span&gt;
&lt;span id=&quot;cb1-11&quot;&gt;&lt;a href=&quot;#cb1-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;           &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; isMultElement&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And so our final solution is just (after converting the input numbers to the &lt;code&gt;Mod Magic&lt;/code&gt; data type)…&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;day25 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Mod&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Magic&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Mod&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Magic&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Integer&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;day52 x y &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    secret &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; findSecret x&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; getVal &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; y &lt;span class=&quot;op&quot;&gt;^%&lt;/span&gt; secret         &lt;span class=&quot;co&quot;&gt;-- exponentiate by the loop count&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Merry Christmas to everyone, and happy New Years too. Thank you for reading these reflections, and I hope they have been helpful in some way :) Special thanks to Eric Wastl too for such a great event as always. Until next year!&lt;/p&gt;
&lt;h3 id=&quot;day-25-benchmarks&quot;&gt;Day 25 Benchmarks&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; Day 25a
benchmarking...
time                 1.997 ms   (1.971 ms .. 2.023 ms)
                     0.998 R²   (0.997 R² .. 0.999 R²)
mean                 2.042 ms   (2.019 ms .. 2.066 ms)
std dev              73.99 μs   (63.56 μs .. 100.2 μs)
variance introduced by outliers: 22% (moderately inflated)

* parsing and formatting times excluded&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md#day-25</link>
      <pubDate>Fri, 25 Dec 2020 01:00:00 EST</pubDate>
    </item>

    <item>
      <title>Day 24</title>
      <description>&lt;h2 id=&quot;day-24&quot;&gt;Day 24&lt;/h2&gt;
&lt;!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day24.md`.  If you want to edit this, edit
that file instead!
--&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://adventofcode.com/2020/day/24&quot;&gt;Prompt&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day24.hs&quot;&gt;Code&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://mstksg.github.io/advent-of-code-2020/src/AOC.Challenge.Day24.html&quot;&gt;Rendered&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day24.md&quot;&gt;Standalone Reflection Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Day 24 brings us our third cellular automata puzzle of the year! :D The other ones were &lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day11.md&quot;&gt;Day 11&lt;/a&gt; and &lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day17.md&quot;&gt;Day 17&lt;/a&gt;. In fact, I was able to mostly copy and paste my stepper code for Day 17 :)&lt;/p&gt;
&lt;p&gt;The main twist here is that we’d have to use hexy stepping and hexy neighbors. My initial solve used the &lt;em&gt;&lt;a href=&quot;https://hackage.haskell.org/package/grid&quot;&gt;grid&lt;/a&gt;&lt;/em&gt; library to get the hexy steps neighbors, but I did go back and &lt;a href=&quot;https://github.com/mhwombat/grid/wiki/Implementation%3A-Hexagonal-tiles&quot;&gt;implement the tiling myself&lt;/a&gt; because it wasn’t too bad :)&lt;/p&gt;
&lt;p&gt;For part 1, it can be nice to have some intermediate data types&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;HexDirection&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;West&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                  &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Northwest&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                  &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Northeast&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                  &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;East&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                  &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Southeast&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                  &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Southwest&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-8&quot;&gt;&lt;a href=&quot;#cb1-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;toDirs ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;HexDirection&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb1-9&quot;&gt;&lt;a href=&quot;#cb1-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;toDirs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-10&quot;&gt;&lt;a href=&quot;#cb1-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; []&lt;/span&gt;
&lt;span id=&quot;cb1-11&quot;&gt;&lt;a href=&quot;#cb1-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ch&quot;&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;ds &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;West&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; toDirs ds&lt;/span&gt;
&lt;span id=&quot;cb1-12&quot;&gt;&lt;a href=&quot;#cb1-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ch&quot;&gt;&amp;#39;e&amp;#39;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;ds &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;East&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; toDirs ds&lt;/span&gt;
&lt;span id=&quot;cb1-13&quot;&gt;&lt;a href=&quot;#cb1-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ch&quot;&gt;&amp;#39;n&amp;#39;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;&amp;#39;e&amp;#39;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;ds &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Northeast&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; toDirs ds&lt;/span&gt;
&lt;span id=&quot;cb1-14&quot;&gt;&lt;a href=&quot;#cb1-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ch&quot;&gt;&amp;#39;n&amp;#39;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;ds &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Northwest&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; toDirs ds&lt;/span&gt;
&lt;span id=&quot;cb1-15&quot;&gt;&lt;a href=&quot;#cb1-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ch&quot;&gt;&amp;#39;s&amp;#39;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;&amp;#39;e&amp;#39;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;ds &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Southeast&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; toDirs ds&lt;/span&gt;
&lt;span id=&quot;cb1-16&quot;&gt;&lt;a href=&quot;#cb1-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ch&quot;&gt;&amp;#39;s&amp;#39;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;ds &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Southwest&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; toDirs ds&lt;/span&gt;
&lt;span id=&quot;cb1-17&quot;&gt;&lt;a href=&quot;#cb1-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    _ &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-18&quot;&gt;&lt;a href=&quot;#cb1-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-19&quot;&gt;&lt;a href=&quot;#cb1-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;hexOffset ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;HexDirection&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-20&quot;&gt;&lt;a href=&quot;#cb1-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;hexOffset &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-21&quot;&gt;&lt;a href=&quot;#cb1-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;West&lt;/span&gt;      &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;)  &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-22&quot;&gt;&lt;a href=&quot;#cb1-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;Northwest&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;)  &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-23&quot;&gt;&lt;a href=&quot;#cb1-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;Northeast&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt;   &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;   &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-24&quot;&gt;&lt;a href=&quot;#cb1-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;East&lt;/span&gt;      &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt;   &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;   &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-25&quot;&gt;&lt;a href=&quot;#cb1-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;Southeast&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt;   &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb1-26&quot;&gt;&lt;a href=&quot;#cb1-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;Southwest&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt;   &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So we can parse into a list of &lt;code&gt;[HexDirection]&lt;/code&gt; paths, and then we can get our starting points by xoring all of the final points:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Data.Bits&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;initialize ::&lt;/span&gt; [[&lt;span class=&quot;dt&quot;&gt;HexDirection&lt;/span&gt;]] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;initialize &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; M.keysSet &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; M.filter &lt;span class=&quot;fu&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; M.fromListWith xor&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;           &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;map&lt;/span&gt; (\steps &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;fu&quot;&gt;sum&lt;/span&gt; (&lt;span class=&quot;fu&quot;&gt;map&lt;/span&gt; hexOffset steps), &lt;span class=&quot;dt&quot;&gt;True&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And this gives us the set of all active points, which we can use to answer part one. But now, on to the simulation!&lt;/p&gt;
&lt;p&gt;First, we can expand the neighbors of a given point in our hexy coords:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;neighbors ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;neighbors (&lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; x y) &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; S.fromDistinctAscList&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [ &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; (x&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;) y&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; (x&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;) (y&lt;span class=&quot;op&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; x     (y&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; x     (y&lt;span class=&quot;op&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; (x&lt;span class=&quot;op&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;) (y&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb3-8&quot;&gt;&lt;a href=&quot;#cb3-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; (x&lt;span class=&quot;op&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;) y&lt;/span&gt;
&lt;span id=&quot;cb3-9&quot;&gt;&lt;a href=&quot;#cb3-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And our step function looks more or less the same as day 17:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;step ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;step ps &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; stayAlive &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt; comeAlive&lt;/span&gt;
&lt;span id=&quot;cb4-3&quot;&gt;&lt;a href=&quot;#cb4-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-4&quot;&gt;&lt;a href=&quot;#cb4-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    neighborCounts ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-5&quot;&gt;&lt;a href=&quot;#cb4-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    neighborCounts &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; M.unionsWith (&lt;span class=&quot;op&quot;&gt;+&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb4-6&quot;&gt;&lt;a href=&quot;#cb4-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      [ M.fromSet (&lt;span class=&quot;fu&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;) (neighbors p)&lt;/span&gt;
&lt;span id=&quot;cb4-7&quot;&gt;&lt;a href=&quot;#cb4-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; p &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; S.toList ps&lt;/span&gt;
&lt;span id=&quot;cb4-8&quot;&gt;&lt;a href=&quot;#cb4-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      ]&lt;/span&gt;
&lt;span id=&quot;cb4-9&quot;&gt;&lt;a href=&quot;#cb4-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    stayAlive &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; M.keysSet &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; M.filter (\n &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; n &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;||&lt;/span&gt; n &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-10&quot;&gt;&lt;a href=&quot;#cb4-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                  neighborCounts &lt;span class=&quot;ot&quot;&gt;`M.restrictKeys`&lt;/span&gt; ps&lt;/span&gt;
&lt;span id=&quot;cb4-11&quot;&gt;&lt;a href=&quot;#cb4-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    comeAlive &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; M.keysSet &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; M.filter (&lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-12&quot;&gt;&lt;a href=&quot;#cb4-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                  neighborCounts &lt;span class=&quot;ot&quot;&gt;`M.withoutKeys`&lt;/span&gt;  ps&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;First we collect a &lt;code&gt;Map Point Int&lt;/code&gt; of each point to how many live neighbors it has. Then the &lt;em&gt;live&lt;/em&gt; points (&lt;code&gt;neighborCounts `M.restrictKeys` ps&lt;/code&gt;) are filtered for only the ones with 1 or 2 live neighbors, and the &lt;em&gt;dead&lt;/em&gt; points (&lt;code&gt;neighborCounts `M.withoutKeys` ps&lt;/code&gt;) are filtered for only the ones with 2 live neighbors. And the resulting new set of live points is &lt;code&gt;stayAlive &amp;lt;&amp;gt; comeAlive&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part1 ::&lt;/span&gt; [[&lt;span class=&quot;dt&quot;&gt;HexDirection&lt;/span&gt;]] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part1 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; S.size &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; initialize&lt;/span&gt;
&lt;span id=&quot;cb5-3&quot;&gt;&lt;a href=&quot;#cb5-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-4&quot;&gt;&lt;a href=&quot;#cb5-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part2 ::&lt;/span&gt; [[&lt;span class=&quot;dt&quot;&gt;HexDirection&lt;/span&gt;]] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-5&quot;&gt;&lt;a href=&quot;#cb5-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2 paths &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; S.size (&lt;span class=&quot;fu&quot;&gt;iterate&lt;/span&gt; step pts &lt;span class=&quot;op&quot;&gt;!!!&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;100&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb5-6&quot;&gt;&lt;a href=&quot;#cb5-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-7&quot;&gt;&lt;a href=&quot;#cb5-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    pts &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; initialize paths&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;day-24-benchmarks&quot;&gt;Day 24 Benchmarks&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; Day 24a
benchmarking...
time                 2.597 ms   (2.551 ms .. 2.639 ms)
                     0.996 R²   (0.993 R² .. 0.998 R²)
mean                 2.579 ms   (2.545 ms .. 2.614 ms)
std dev              111.4 μs   (82.30 μs .. 141.5 μs)
variance introduced by outliers: 28% (moderately inflated)

&amp;gt;&amp;gt; Day 24b
benchmarking...
time                 272.1 ms   (247.2 ms .. 296.5 ms)
                     0.996 R²   (0.996 R² .. 1.000 R²)
mean                 273.7 ms   (264.8 ms .. 286.5 ms)
std dev              13.87 ms   (1.266 ms .. 18.02 ms)
variance introduced by outliers: 16% (moderately inflated)&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md#day-24</link>
      <pubDate>Thu, 24 Dec 2020 01:00:00 EST</pubDate>
    </item>

    <item>
      <title>Day 23</title>
      <description>&lt;h2 id=&quot;day-23&quot;&gt;Day 23&lt;/h2&gt;
&lt;!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day23.md`.  If you want to edit this, edit
that file instead!
--&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://adventofcode.com/2020/day/23&quot;&gt;Prompt&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day23.hs&quot;&gt;Code&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://mstksg.github.io/advent-of-code-2020/src/AOC.Challenge.Day23.html&quot;&gt;Rendered&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day23.md&quot;&gt;Standalone Reflection Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Day 23 – this one definitely stumped me a while, and it was the first one to take me more than 24 hours!&lt;/p&gt;
&lt;p&gt;Part 1 was straightforward enough with the circular &lt;a href=&quot;https://hackage.haskell.org/package/pointedlist&quot;&gt;Pointed List&lt;/a&gt;, and was pretty fun indeed. But the main problem with extrapolating this to part 2 was the crucial “slow part”: finding the index of the “preceding” cup. Using a circular pointed list makes it very fast to do things like take 3 cups and insert 3 cups where you want them, but the tough thing is finding &lt;em&gt;where&lt;/em&gt; you want to re-insert them: if you pick up cup #3, then where is cup #2? My circular pointed list (and my later mutable vector based one, among other attempts) all suffered from that same problem: re-arranging the cups is fast, but I couldn’t figure out a way to know where to place them without doing a full linear search. And this was tractable for 10 cups, but pretty much impossible for 1 million cups – especially since the location of the ‘preceding cup’ soon became very far from the current cup (it goes to the full 500k pretty quickly!)&lt;/p&gt;
&lt;p&gt;In frustration, I implemented a mutable circularly linked list library…but found the same problem: I could easily take and insert, but no easy way to find out where the preceding cup was without doing an item-by-item traversal.&lt;/p&gt;
&lt;p&gt;The breakthrough finally came when I thought about attaching a pointer to the preceding cup’s cell to each linked list cell — a “backdoor” pointer that skips across the circularly linked list. This should be doable because the structure of “preceding cup” is fixed – it won’t ever change, and so this pointer should also be fixed as well as you shuffle everything over it. I had the visual imagery of “pulling” the three taken cups up back “through” the backdoor pointer, and everything seemed very efficient, since the main inefficiency (finding the preceding cup) was fixed.&lt;/p&gt;
&lt;p&gt;Unfortunately I am not skilled enough in pointer manipulation and other imperative programming intricacies to be able to implement this in a nice way. So I stepped back and thought about just “reifying” this pointer structure into an array of indices (pointers), where the addresses were indices.&lt;/p&gt;
&lt;p&gt;Each cell would have to contain:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;The index of the cup to the right&lt;/li&gt;
&lt;li&gt;The index of the preceding cup&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Only…#2 doesn’t need to actually be a part of the cell, because it’s fixed and never mutates. So we only need to have each cell hold #1, and use some sort of scheme to get #2.&lt;/p&gt;
&lt;p&gt;And then that’s when it hit me — if I simply stored Cup #1 at index 0, Cup #2 at index 1, Cup #3 at index 2, etc…then #2 is simply “the previous index”! So in the end we only need an array of indices, where each index corresponds to that cup. The “preceding-cup” structure is fixed, and we only need to update the “cup to the right” pointers!&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt;           &lt;span class=&quot;dt&quot;&gt;Data.Finite&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;qualified&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Data.Vector.Mutable.Sized&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;MV&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;qualified&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Data.Vector.Sized&lt;/span&gt;         &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;CrabState&lt;/span&gt; n s &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;MV.MVector&lt;/span&gt; n s (&lt;span class=&quot;dt&quot;&gt;Finite&lt;/span&gt; n)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Our data structure will be a million-sized mutable vector where index &lt;code&gt;i&lt;/code&gt; stores the index (cup number, essentially) of the cup labeled &lt;code&gt;i&lt;/code&gt; (technically, &lt;code&gt;i+1&lt;/code&gt;). We can use &lt;code&gt;Finite n&lt;/code&gt; (&lt;code&gt;Finite 1000000&lt;/code&gt; in our case) for our index size because it is constrained to be between 0 and 999999, and subtracting past 0 wraps back up to 999999 like we’d want it to.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;step&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;forall&lt;/span&gt; n m s&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;KnownNat&lt;/span&gt; n, &lt;span class=&quot;dt&quot;&gt;PrimMonad&lt;/span&gt; m, &lt;span class=&quot;dt&quot;&gt;PrimState&lt;/span&gt; m &lt;span class=&quot;op&quot;&gt;~&lt;/span&gt; s)&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;CrabState&lt;/span&gt; n s&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Finite&lt;/span&gt; n       &lt;span class=&quot;co&quot;&gt;-- ^ current pointer&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; m (&lt;span class=&quot;dt&quot;&gt;Finite&lt;/span&gt; n)   &lt;span class=&quot;co&quot;&gt;-- ^ next pointer&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;step cs lab &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-7&quot;&gt;&lt;a href=&quot;#cb2-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;-- pull out the next three cups, and the cup fourth to the right&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-8&quot;&gt;&lt;a href=&quot;#cb2-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    (gs&lt;span class=&quot;op&quot;&gt;@&lt;/span&gt;[g1,_,g3],lab&amp;#39;) &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; pull3 lab&lt;/span&gt;
&lt;span id=&quot;cb2-9&quot;&gt;&lt;a href=&quot;#cb2-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-10&quot;&gt;&lt;a href=&quot;#cb2-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;-- update the &amp;quot;cup-to-the-right&amp;quot; of the pointer cup&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-11&quot;&gt;&lt;a href=&quot;#cb2-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    MV.write cs lab lab&amp;#39;&lt;/span&gt;
&lt;span id=&quot;cb2-12&quot;&gt;&lt;a href=&quot;#cb2-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-13&quot;&gt;&lt;a href=&quot;#cb2-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;-- find the first valid &amp;quot;preceding cup&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-14&quot;&gt;&lt;a href=&quot;#cb2-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; target &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;until&lt;/span&gt; (&lt;span class=&quot;ot&quot;&gt;`notElem`&lt;/span&gt; gs) (&lt;span class=&quot;fu&quot;&gt;subtract&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;) (lab &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb2-15&quot;&gt;&lt;a href=&quot;#cb2-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-16&quot;&gt;&lt;a href=&quot;#cb2-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;-- what cup is to the right of the target cup?&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-17&quot;&gt;&lt;a href=&quot;#cb2-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    aftertarg &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; MV.read cs target&lt;/span&gt;
&lt;span id=&quot;cb2-18&quot;&gt;&lt;a href=&quot;#cb2-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-19&quot;&gt;&lt;a href=&quot;#cb2-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;-- pointer shuffling: the target cup should point to the pulled cups&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-20&quot;&gt;&lt;a href=&quot;#cb2-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    MV.write cs target g1&lt;/span&gt;
&lt;span id=&quot;cb2-21&quot;&gt;&lt;a href=&quot;#cb2-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;-- .. and the final pulled cup should point to where the target cup pointed to originally&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-22&quot;&gt;&lt;a href=&quot;#cb2-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    MV.write cs g3 aftertarg&lt;/span&gt;
&lt;span id=&quot;cb2-23&quot;&gt;&lt;a href=&quot;#cb2-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-24&quot;&gt;&lt;a href=&quot;#cb2-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; lab&amp;#39;&lt;/span&gt;
&lt;span id=&quot;cb2-25&quot;&gt;&lt;a href=&quot;#cb2-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-26&quot;&gt;&lt;a href=&quot;#cb2-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    pull3 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Finite&lt;/span&gt; n &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; m ([&lt;span class=&quot;dt&quot;&gt;Finite&lt;/span&gt; n], &lt;span class=&quot;dt&quot;&gt;Finite&lt;/span&gt; n)&lt;/span&gt;
&lt;span id=&quot;cb2-27&quot;&gt;&lt;a href=&quot;#cb2-27&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    pull3 i0 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-28&quot;&gt;&lt;a href=&quot;#cb2-28&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      i1 &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; MV.read cs i0&lt;/span&gt;
&lt;span id=&quot;cb2-29&quot;&gt;&lt;a href=&quot;#cb2-29&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      i2 &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; MV.read cs i1&lt;/span&gt;
&lt;span id=&quot;cb2-30&quot;&gt;&lt;a href=&quot;#cb2-30&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      i3 &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; MV.read cs i2&lt;/span&gt;
&lt;span id=&quot;cb2-31&quot;&gt;&lt;a href=&quot;#cb2-31&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      i4 &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; MV.read cs i3&lt;/span&gt;
&lt;span id=&quot;cb2-32&quot;&gt;&lt;a href=&quot;#cb2-32&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; ([i1,i2,i3],i4)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we just need to initialize from a fully allocated vector by writing at each index the value of the previous cell:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;initialize&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;forall&lt;/span&gt; n m s&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;KnownNat&lt;/span&gt; n, &lt;span class=&quot;dt&quot;&gt;PrimMonad&lt;/span&gt; m, &lt;span class=&quot;dt&quot;&gt;PrimState&lt;/span&gt; m &lt;span class=&quot;op&quot;&gt;~&lt;/span&gt; s)&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V.Vector&lt;/span&gt; n (&lt;span class=&quot;dt&quot;&gt;Finite&lt;/span&gt; n)            &lt;span class=&quot;co&quot;&gt;-- ^ vector, organized left-to-right&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; m (&lt;span class=&quot;dt&quot;&gt;Finite&lt;/span&gt; n, &lt;span class=&quot;dt&quot;&gt;CrabState&lt;/span&gt; n s)      &lt;span class=&quot;co&quot;&gt;-- ^ initial pointer&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;initialize v0 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    cs &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; MV.new&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    for_ finites &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; \i &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt;        &lt;span class=&quot;co&quot;&gt;-- iterate over each index&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-8&quot;&gt;&lt;a href=&quot;#cb3-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      MV.write cs (v0 &lt;span class=&quot;op&quot;&gt;V.!&lt;/span&gt; (i &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;)) (v0 &lt;span class=&quot;op&quot;&gt;V.!&lt;/span&gt; i)&lt;/span&gt;
&lt;span id=&quot;cb3-9&quot;&gt;&lt;a href=&quot;#cb3-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; i0 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; v0 &lt;span class=&quot;ot&quot;&gt;`V.index`&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-10&quot;&gt;&lt;a href=&quot;#cb3-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; (i0, cs)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And now a function to mutate our crab state a given number of points, from an initial pointer index:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;run ::&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;KnownNat&lt;/span&gt; n, &lt;span class=&quot;dt&quot;&gt;PrimMonad&lt;/span&gt; m, &lt;span class=&quot;dt&quot;&gt;PrimState&lt;/span&gt; m &lt;span class=&quot;op&quot;&gt;~&lt;/span&gt; s)&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;                  &lt;span class=&quot;co&quot;&gt;-- ^ number of steps&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-3&quot;&gt;&lt;a href=&quot;#cb4-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Finite&lt;/span&gt; n             &lt;span class=&quot;co&quot;&gt;-- ^ initial index&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-4&quot;&gt;&lt;a href=&quot;#cb4-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;CrabState&lt;/span&gt; n s&lt;/span&gt;
&lt;span id=&quot;cb4-5&quot;&gt;&lt;a href=&quot;#cb4-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; m ()&lt;/span&gt;
&lt;span id=&quot;cb4-6&quot;&gt;&lt;a href=&quot;#cb4-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;run n i0 cs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; go &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; i0&lt;/span&gt;
&lt;span id=&quot;cb4-7&quot;&gt;&lt;a href=&quot;#cb4-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-8&quot;&gt;&lt;a href=&quot;#cb4-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    go m i&lt;/span&gt;
&lt;span id=&quot;cb4-9&quot;&gt;&lt;a href=&quot;#cb4-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; m &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; n    &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; ()&lt;/span&gt;
&lt;span id=&quot;cb4-10&quot;&gt;&lt;a href=&quot;#cb4-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;otherwise&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; go (m &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;=&amp;lt;&amp;lt;&lt;/span&gt; step cs i&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And maybe some functions to read out the actual answers:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;numbersFrom1&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;                  &lt;span class=&quot;co&quot;&gt;-- ^ how many numbers to pull&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-3&quot;&gt;&lt;a href=&quot;#cb5-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;CrabState&lt;/span&gt; n s&lt;/span&gt;
&lt;span id=&quot;cb5-4&quot;&gt;&lt;a href=&quot;#cb5-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; m [&lt;span class=&quot;dt&quot;&gt;Finite&lt;/span&gt; n]&lt;/span&gt;
&lt;span id=&quot;cb5-5&quot;&gt;&lt;a href=&quot;#cb5-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;numbersFrom1 n cs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; go &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-6&quot;&gt;&lt;a href=&quot;#cb5-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-7&quot;&gt;&lt;a href=&quot;#cb5-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    go m i&lt;/span&gt;
&lt;span id=&quot;cb5-8&quot;&gt;&lt;a href=&quot;#cb5-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; m &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; n    &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; []&lt;/span&gt;
&lt;span id=&quot;cb5-9&quot;&gt;&lt;a href=&quot;#cb5-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;otherwise&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-10&quot;&gt;&lt;a href=&quot;#cb5-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;          nxt &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; MV.read cs i&lt;/span&gt;
&lt;span id=&quot;cb5-11&quot;&gt;&lt;a href=&quot;#cb5-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;          (nxt&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; go (m&lt;span class=&quot;op&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;) nxt&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And we have our full pipeline, remembering that we have to subtract 1 to get the index of a cup from the cup number:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb6&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb6-1&quot;&gt;&lt;a href=&quot;#cb6-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part1 ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb6-2&quot;&gt;&lt;a href=&quot;#cb6-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part1 cs0 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; runST &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-3&quot;&gt;&lt;a href=&quot;#cb6-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    cs &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; initialize v0&lt;/span&gt;
&lt;span id=&quot;cb6-4&quot;&gt;&lt;a href=&quot;#cb6-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    run &lt;span class=&quot;dv&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; cs&lt;/span&gt;
&lt;span id=&quot;cb6-5&quot;&gt;&lt;a href=&quot;#cb6-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    (&lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;fromIntegral&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; numbersFrom1 &lt;span class=&quot;dv&quot;&gt;9&lt;/span&gt; cs&lt;/span&gt;
&lt;span id=&quot;cb6-6&quot;&gt;&lt;a href=&quot;#cb6-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-7&quot;&gt;&lt;a href=&quot;#cb6-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    v0 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V.Vector&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;10&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Finite&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;10&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb6-8&quot;&gt;&lt;a href=&quot;#cb6-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; v0 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; V.fromList &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-9&quot;&gt;&lt;a href=&quot;#cb6-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;fu&quot;&gt;fromIntegral&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;subtract&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; cs0&lt;/span&gt;
&lt;span id=&quot;cb6-10&quot;&gt;&lt;a href=&quot;#cb6-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-11&quot;&gt;&lt;a href=&quot;#cb6-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part2 ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-12&quot;&gt;&lt;a href=&quot;#cb6-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2 cs0 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; runST &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-13&quot;&gt;&lt;a href=&quot;#cb6-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    cs &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; initialize v0&lt;/span&gt;
&lt;span id=&quot;cb6-14&quot;&gt;&lt;a href=&quot;#cb6-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    run &lt;span class=&quot;dv&quot;&gt;10000000&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; cs&lt;/span&gt;
&lt;span id=&quot;cb6-15&quot;&gt;&lt;a href=&quot;#cb6-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [x,y] &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;fromIntegral&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; numbersFrom1 &lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt; cs&lt;/span&gt;
&lt;span id=&quot;cb6-16&quot;&gt;&lt;a href=&quot;#cb6-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; (x &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt; y)&lt;/span&gt;
&lt;span id=&quot;cb6-17&quot;&gt;&lt;a href=&quot;#cb6-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-18&quot;&gt;&lt;a href=&quot;#cb6-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    v0 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V.Vector&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1000000&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Finite&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1000000&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb6-19&quot;&gt;&lt;a href=&quot;#cb6-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; v0 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; V.fromList &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-20&quot;&gt;&lt;a href=&quot;#cb6-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        (&lt;span class=&quot;fu&quot;&gt;fromIntegral&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;subtract&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; cs0)&lt;/span&gt;
&lt;span id=&quot;cb6-21&quot;&gt;&lt;a href=&quot;#cb6-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;++&lt;/span&gt; [&lt;span class=&quot;dv&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;..&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Overall, a very fun puzzle that required a bunch of interesting data structure and representation breakthroughs to tackle :)&lt;/p&gt;
&lt;h3 id=&quot;day-23-benchmarks&quot;&gt;Day 23 Benchmarks&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; Day 23a
benchmarking...
time                 4.469 μs   (4.420 μs .. 4.544 μs)
                     0.997 R²   (0.993 R² .. 1.000 R²)
mean                 4.452 μs   (4.424 μs .. 4.542 μs)
std dev              181.5 ns   (39.87 ns .. 343.3 ns)
variance introduced by outliers: 53% (severely inflated)

* parsing and formatting times excluded

&amp;gt;&amp;gt; Day 23b
benchmarking...
time                 194.3 ms   (190.4 ms .. 196.6 ms)
                     1.000 R²   (0.999 R² .. 1.000 R²)
mean                 195.4 ms   (194.3 ms .. 198.1 ms)
std dev              2.172 ms   (125.3 μs .. 3.023 ms)
variance introduced by outliers: 14% (moderately inflated)

* parsing and formatting times excluded&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md#day-23</link>
      <pubDate>Wed, 23 Dec 2020 01:00:00 EST</pubDate>
    </item>

    <item>
      <title>Day 22</title>
      <description>&lt;h2 id=&quot;day-22&quot;&gt;Day 22&lt;/h2&gt;
&lt;!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day22.md`.  If you want to edit this, edit
that file instead!
--&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://adventofcode.com/2020/day/22&quot;&gt;Prompt&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day22.hs&quot;&gt;Code&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://mstksg.github.io/advent-of-code-2020/src/AOC.Challenge.Day22.html&quot;&gt;Rendered&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day22.md&quot;&gt;Standalone Reflection Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This one can be a fun exercise in explicit/direct tail recursion :) It’s a straightforward implementation of an “imperative” algorithm, but we actually gain a lot from implementing our imperative algorithm in a purely functional setting, and can write something that runs faster than we might write in a language with implicit mutation. Immutability can be an optimization, since our data structures are designed around sharing and avoiding deep clones, so storing references and caches to old values are extremely cheap. I explain more about this at the end, but it’s nice that we can get the advantages of imperative programming without most of the drawbacks of implicit mutation slowing down our code.&lt;/p&gt;
&lt;p&gt;This problem is also a nice showcase of Haskell’s standard “queue” data type, &lt;code&gt;Seq&lt;/code&gt; from &lt;em&gt;&lt;a href=&quot;https://hackage.haskell.org/package/containers/docs/Data-Sequence.html&quot;&gt;Data.Sequence&lt;/a&gt;&lt;/em&gt;, with O(1) pushing and popping from both ends.&lt;/p&gt;
&lt;p&gt;I decided to write a function that I could use to parameterize on for both parts.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt;           &lt;span class=&quot;dt&quot;&gt;Data.Sequence&lt;/span&gt;              (&lt;span class=&quot;dt&quot;&gt;Seq&lt;/span&gt;(..))&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt;           &lt;span class=&quot;dt&quot;&gt;Data.Sequence.NonEmpty&lt;/span&gt;     (&lt;span class=&quot;dt&quot;&gt;NESeq&lt;/span&gt;(..))&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;qualified&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Data.Sequence&lt;/span&gt;              &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Seq&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Deck&lt;/span&gt;   &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Seq&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;NEDeck&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;NESeq&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-8&quot;&gt;&lt;a href=&quot;#cb1-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Player&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;P1&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;P2&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-9&quot;&gt;&lt;a href=&quot;#cb1-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-10&quot;&gt;&lt;a href=&quot;#cb1-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;playGameWith&lt;/span&gt;
&lt;span id=&quot;cb1-11&quot;&gt;&lt;a href=&quot;#cb1-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;NEDeck&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;NEDeck&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Player&lt;/span&gt;)       &lt;span class=&quot;co&quot;&gt;-- ^ handler&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-12&quot;&gt;&lt;a href=&quot;#cb1-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Deck&lt;/span&gt;                                     &lt;span class=&quot;co&quot;&gt;-- ^ p1 starting deck&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-13&quot;&gt;&lt;a href=&quot;#cb1-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Deck&lt;/span&gt;                                     &lt;span class=&quot;co&quot;&gt;-- ^ p2 starting deck&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-14&quot;&gt;&lt;a href=&quot;#cb1-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Player&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Deck&lt;/span&gt;)                           &lt;span class=&quot;co&quot;&gt;-- ^ winner and deck&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The handler function will let us specify how to handle the situation when both decks are non-empty (represented by &lt;em&gt;&lt;a href=&quot;https://hackage.haskell.org/package/nonempty-containers/docs/Data-Sequence-NonEmpty.html&quot;&gt;Data.Sequence.NonEmpty&lt;/a&gt;&lt;/em&gt;). If returns &lt;code&gt;Nothing&lt;/code&gt;, we defer to the higher-card-wins &lt;a href=&quot;https://en.wikipedia.org/wiki/War_(card_game)&quot;&gt;War&lt;/a&gt; rules, and if it returns &lt;code&gt;Just&lt;/code&gt;, we take that &lt;code&gt;Player&lt;/code&gt; as the winner of that round.&lt;/p&gt;
&lt;p&gt;For part 1, we always defer to the higher-card-wins rule, so we can ignore our decks and return &lt;code&gt;Nothing&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;game1 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Deck&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Deck&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Player&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Deck&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;game1 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; playGameWith &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; \_ _ &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For part 2, we want to play a game with the tops of the decks given to us, but only if we have enough cards.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;game2 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Deck&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Deck&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Player&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Deck&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;game2 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; playGameWith &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; \(x &lt;span class=&quot;op&quot;&gt;:&amp;lt;||&lt;/span&gt; xs) (y &lt;span class=&quot;op&quot;&gt;:&amp;lt;||&lt;/span&gt; ys) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    xs&amp;#39; &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; takeExactly x xs&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ys&amp;#39; &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; takeExactly y ys&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;fst&lt;/span&gt; (game2 xs&amp;#39; ys&amp;#39;)&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;takeExactly ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Seq&lt;/span&gt; a &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Seq&lt;/span&gt; a)&lt;/span&gt;
&lt;span id=&quot;cb3-8&quot;&gt;&lt;a href=&quot;#cb3-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;takeExactly n xs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; Seq.take n xs &lt;span class=&quot;op&quot;&gt;&amp;lt;$&lt;/span&gt; guard (Seq.length xs &lt;span class=&quot;op&quot;&gt;&amp;gt;=&lt;/span&gt; n)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If we don’t have enough items to take exactly &lt;code&gt;x&lt;/code&gt; items from &lt;code&gt;xs&lt;/code&gt;, then we fail and defer to higher-card-wins rules (and same for &lt;code&gt;y&lt;/code&gt; and &lt;code&gt;ys&lt;/code&gt;). Otherwise, we play a &lt;code&gt;game2&lt;/code&gt; with the exactly-sized deck tops to determine the winner. The way the recursion is structured here is pretty night because there is a loop between the two function pointers (&lt;code&gt;game2&lt;/code&gt;, and the lambda passed to it), so we can go back and forth between them without allocating new functions.&lt;/p&gt;
&lt;p&gt;Now the only thing left is to actually write &lt;code&gt;playGameWith&lt;/code&gt; :D This one is not too bad if we use a helper function to make sure things stay tail-recursive so we don’t accidentally leak space. We also would like to make sure we keep the &lt;em&gt;same&lt;/em&gt; top-level &lt;code&gt;f&lt;/code&gt; in the closure for the whole time, so that the recursive call in &lt;code&gt;go&lt;/code&gt; to &lt;code&gt;go&lt;/code&gt; will go &lt;em&gt;exactly&lt;/em&gt; back to its own function pointer.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt;           &lt;span class=&quot;dt&quot;&gt;Data.Set&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;qualified&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Data.Set&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;S&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-3&quot;&gt;&lt;a href=&quot;#cb4-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-4&quot;&gt;&lt;a href=&quot;#cb4-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;playGameWith&lt;/span&gt;
&lt;span id=&quot;cb4-5&quot;&gt;&lt;a href=&quot;#cb4-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;NEDeck&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;NEDeck&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Player&lt;/span&gt;)       &lt;span class=&quot;co&quot;&gt;-- ^ handler&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-6&quot;&gt;&lt;a href=&quot;#cb4-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Deck&lt;/span&gt;                                     &lt;span class=&quot;co&quot;&gt;-- ^ p1 starting deck&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-7&quot;&gt;&lt;a href=&quot;#cb4-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Deck&lt;/span&gt;                                     &lt;span class=&quot;co&quot;&gt;-- ^ p2 starting deck&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-8&quot;&gt;&lt;a href=&quot;#cb4-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Player&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Deck&lt;/span&gt;)                           &lt;span class=&quot;co&quot;&gt;-- ^ winner and deck&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-9&quot;&gt;&lt;a href=&quot;#cb4-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;playGameWith f &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; go S.empty&lt;/span&gt;
&lt;span id=&quot;cb4-10&quot;&gt;&lt;a href=&quot;#cb4-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-11&quot;&gt;&lt;a href=&quot;#cb4-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    go ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Deck&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Deck&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Deck&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Deck&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Player&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Deck&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb4-12&quot;&gt;&lt;a href=&quot;#cb4-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    go &lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;seen &lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;xs0 &lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;ys0&lt;/span&gt;
&lt;span id=&quot;cb4-13&quot;&gt;&lt;a href=&quot;#cb4-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; (xs0, ys0) &lt;span class=&quot;ot&quot;&gt;`S.member`&lt;/span&gt; seen &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;P1&lt;/span&gt;, xs0)&lt;/span&gt;
&lt;span id=&quot;cb4-14&quot;&gt;&lt;a href=&quot;#cb4-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;otherwise&lt;/span&gt;                  &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt; (xs0, ys0) &lt;span class=&quot;kw&quot;&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-15&quot;&gt;&lt;a href=&quot;#cb4-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            (x &lt;span class=&quot;op&quot;&gt;:&amp;lt;|&lt;/span&gt; xs, y &lt;span class=&quot;op&quot;&gt;:&amp;lt;|&lt;/span&gt; ys) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-16&quot;&gt;&lt;a href=&quot;#cb4-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;              &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; winner &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt; f (x &lt;span class=&quot;op&quot;&gt;:&amp;lt;||&lt;/span&gt; xs) (y &lt;span class=&quot;op&quot;&gt;:&amp;lt;||&lt;/span&gt; ys) &lt;span class=&quot;kw&quot;&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-17&quot;&gt;&lt;a href=&quot;#cb4-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;if&lt;/span&gt; x &lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; y &lt;span class=&quot;kw&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;P1&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;P2&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-18&quot;&gt;&lt;a href=&quot;#cb4-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; p  &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; p&lt;/span&gt;
&lt;span id=&quot;cb4-19&quot;&gt;&lt;a href=&quot;#cb4-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;              &lt;span class=&quot;kw&quot;&gt;in&lt;/span&gt;  &lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt; winner &lt;span class=&quot;kw&quot;&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-20&quot;&gt;&lt;a href=&quot;#cb4-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    &lt;span class=&quot;dt&quot;&gt;P1&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; go seen&amp;#39; (xs &lt;span class=&quot;op&quot;&gt;:|&amp;gt;&lt;/span&gt; x &lt;span class=&quot;op&quot;&gt;:|&amp;gt;&lt;/span&gt; y) ys&lt;/span&gt;
&lt;span id=&quot;cb4-21&quot;&gt;&lt;a href=&quot;#cb4-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    &lt;span class=&quot;dt&quot;&gt;P2&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; go seen&amp;#39; xs (ys &lt;span class=&quot;op&quot;&gt;:|&amp;gt;&lt;/span&gt; y &lt;span class=&quot;op&quot;&gt;:|&amp;gt;&lt;/span&gt; x)&lt;/span&gt;
&lt;span id=&quot;cb4-22&quot;&gt;&lt;a href=&quot;#cb4-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            (&lt;span class=&quot;dt&quot;&gt;Empty&lt;/span&gt;, _    ) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;P2&lt;/span&gt;, ys0)&lt;/span&gt;
&lt;span id=&quot;cb4-23&quot;&gt;&lt;a href=&quot;#cb4-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            (_    , &lt;span class=&quot;dt&quot;&gt;Empty&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;P1&lt;/span&gt;, xs0)&lt;/span&gt;
&lt;span id=&quot;cb4-24&quot;&gt;&lt;a href=&quot;#cb4-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-25&quot;&gt;&lt;a href=&quot;#cb4-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        seen&amp;#39; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; S.insert (xs0, ys0) seen&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Most of this implementation follows the logic straightforwardly, remembering to use &lt;code&gt;f&lt;/code&gt; to give the callback a chance to “intercept” the “highest card win” rule if it wants to. We get a lot of mileage here out of the &lt;code&gt;:&amp;lt;|&lt;/code&gt;, &lt;code&gt;:|&amp;gt;&lt;/code&gt; and &lt;code&gt;Empty&lt;/code&gt; constructors for &lt;code&gt;Seq&lt;/code&gt;, which allows us to match on the head and tail or an empty &lt;code&gt;Seq&lt;/code&gt; as a pattern. Note that this isn’t &lt;em&gt;perfectly&lt;/em&gt; tail-recursive – we do get another layer of data allocated whenever we recurse into a game. But at least it’s tail-recursive within the same game.&lt;/p&gt;
&lt;p&gt;Note that this talk about tail recursion isn’t because we are afraid of overflowing the call stack like in other languages (and trying to take advantage of tail-call optimization) — the value in tail recursion is that we can stay constant-space on the heap (since haskell function calls go on the heap, not a call stack).&lt;/p&gt;
&lt;p&gt;This works, but we can make it a little faster in a way that only purely functional languages can benefit from. Checking for seen decks in a &lt;code&gt;Set (Deck, Deck)&lt;/code&gt; can be pretty expensive in such a tight loop, and it’s definitely the bottleneck of our loop. One quick optimization we can do is use an &lt;code&gt;IntSet&lt;/code&gt; instead of a &lt;code&gt;Set&lt;/code&gt;, and store a “hash” (really, partition index) of our data:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;hashHand ;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Deck&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Deck&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;hashHand xs ys &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; hash (&lt;span class=&quot;fu&quot;&gt;take&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt; (toList xs), &lt;span class=&quot;fu&quot;&gt;take&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt; (toList ys), &lt;span class=&quot;fu&quot;&gt;length&lt;/span&gt; xs)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So instead of checking if a hand pair has been seen before, we can only check &lt;code&gt;hashHand xs0 ys0 `IS.member` seen&lt;/code&gt;, and &lt;code&gt;IS.insert (hashHand xs0 ys0) seen&lt;/code&gt; at every step. This becomes very efficient (takes my time from 1.8s down to 8ms), effectively eliminating the main bottleneck.&lt;/p&gt;
&lt;p&gt;However, this method is mathematically unsound because it’s possible for two different decks to “hash” to the same &lt;code&gt;Int&lt;/code&gt;. It didn’t happen in my own input, but it happened when solving the game for one of my friend’s inputs.&lt;/p&gt;
&lt;p&gt;Instead what we can do is implement “hash set”, with easy negative checks, and expensive positive checks — but those should only happen basically once per &lt;em&gt;game&lt;/em&gt;, and not once per round. We can store a &lt;code&gt;IntMap (Set (Deck, Deck))&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb6&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb6-1&quot;&gt;&lt;a href=&quot;#cb6-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;go ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IntMap&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Deck&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Deck&lt;/span&gt;)) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Deck&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Deck&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Player&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Deck&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb6-2&quot;&gt;&lt;a href=&quot;#cb6-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;go &lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;seen &lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;xs0 &lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;ys0&lt;/span&gt;
&lt;span id=&quot;cb6-3&quot;&gt;&lt;a href=&quot;#cb6-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; collision &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;P1&lt;/span&gt;, xs0)&lt;/span&gt;
&lt;span id=&quot;cb6-4&quot;&gt;&lt;a href=&quot;#cb6-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;otherwise&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt; (xs0, ys0) &lt;span class=&quot;kw&quot;&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-5&quot;&gt;&lt;a href=&quot;#cb6-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        (x &lt;span class=&quot;op&quot;&gt;:&amp;lt;|&lt;/span&gt; xs, y &lt;span class=&quot;op&quot;&gt;:&amp;lt;|&lt;/span&gt; ys) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-6&quot;&gt;&lt;a href=&quot;#cb6-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;          &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; winner &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt; f (x &lt;span class=&quot;op&quot;&gt;:&amp;lt;||&lt;/span&gt; xs) (y &lt;span class=&quot;op&quot;&gt;:&amp;lt;||&lt;/span&gt; ys) &lt;span class=&quot;kw&quot;&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-7&quot;&gt;&lt;a href=&quot;#cb6-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;if&lt;/span&gt; x &lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; y &lt;span class=&quot;kw&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;P1&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;P2&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-8&quot;&gt;&lt;a href=&quot;#cb6-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; p  &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; p&lt;/span&gt;
&lt;span id=&quot;cb6-9&quot;&gt;&lt;a href=&quot;#cb6-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;          &lt;span class=&quot;kw&quot;&gt;in&lt;/span&gt;  &lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt; winner &lt;span class=&quot;kw&quot;&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-10&quot;&gt;&lt;a href=&quot;#cb6-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;dt&quot;&gt;P1&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; go seen&amp;#39; (xs &lt;span class=&quot;op&quot;&gt;:|&amp;gt;&lt;/span&gt; x &lt;span class=&quot;op&quot;&gt;:|&amp;gt;&lt;/span&gt; y) ys&lt;/span&gt;
&lt;span id=&quot;cb6-11&quot;&gt;&lt;a href=&quot;#cb6-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;dt&quot;&gt;P2&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; go seen&amp;#39; xs (ys &lt;span class=&quot;op&quot;&gt;:|&amp;gt;&lt;/span&gt; y &lt;span class=&quot;op&quot;&gt;:|&amp;gt;&lt;/span&gt; x)&lt;/span&gt;
&lt;span id=&quot;cb6-12&quot;&gt;&lt;a href=&quot;#cb6-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        (&lt;span class=&quot;dt&quot;&gt;Empty&lt;/span&gt;, _    ) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;P2&lt;/span&gt;, ys0)&lt;/span&gt;
&lt;span id=&quot;cb6-13&quot;&gt;&lt;a href=&quot;#cb6-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        (_    , &lt;span class=&quot;dt&quot;&gt;Empty&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;P1&lt;/span&gt;, xs0)&lt;/span&gt;
&lt;span id=&quot;cb6-14&quot;&gt;&lt;a href=&quot;#cb6-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-15&quot;&gt;&lt;a href=&quot;#cb6-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    collision &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt; IM.lookup (hashHand xs0 ys0) seen &lt;span class=&quot;kw&quot;&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-16&quot;&gt;&lt;a href=&quot;#cb6-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;False&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-17&quot;&gt;&lt;a href=&quot;#cb6-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; s  &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (xs0, ys0) &lt;span class=&quot;ot&quot;&gt;`S.member`&lt;/span&gt; s&lt;/span&gt;
&lt;span id=&quot;cb6-18&quot;&gt;&lt;a href=&quot;#cb6-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    seen&amp;#39; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; IM.insertWith (&lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt;) (hashHand xs0 ys0) (S.singleton (xs0, ys0)) seen&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note storing the &lt;code&gt;(Deck, Deck)&lt;/code&gt; in our &lt;code&gt;IntMap&lt;/code&gt; is very expensive if we are using in-place mutation for our decks: we’d have to do a full copy of our decks &lt;em&gt;every round&lt;/em&gt; to store them into our set, because mutating them will change them. In the purely functional case, we don’t have to do anything special because no values are ever mutated — the reference to our old data is already there!&lt;/p&gt;
&lt;p&gt;In addition, inserting/popping values off of a &lt;code&gt;Seq&lt;/code&gt; does &lt;em&gt;not&lt;/em&gt; require a full copy: because &lt;code&gt;Seq&lt;/code&gt; is internally a &lt;a href=&quot;https://en.wikipedia.org/wiki/Finger_tree&quot;&gt;finger tree&lt;/a&gt; (a purely functional persistent data structure optimized for these operations), adding a new value does not require a full copy, but instead allocates very little because most of your “new” tree’s internal nodes are pointing at references to the original tree. So no copying is ever made, and storing these &lt;code&gt;Seq&lt;/code&gt;s in our &lt;code&gt;IntMap&lt;/code&gt; is essentially just storing a pointer.&lt;/p&gt;
&lt;p&gt;This is one of the nice ways which immutability can give us performance increases! These are always fun to highlight because there’s some common fantasy that immutability = slower, when in reality it’s often an &lt;em&gt;optimization&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&quot;day-22-benchmarks&quot;&gt;Day 22 Benchmarks&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; Day 22a
benchmarking...
time                 230.6 μs   (228.1 μs .. 236.1 μs)
                     0.998 R²   (0.993 R² .. 1.000 R²)
mean                 228.9 μs   (227.4 μs .. 233.8 μs)
std dev              7.584 μs   (798.7 ns .. 15.31 μs)
variance introduced by outliers: 29% (moderately inflated)

* parsing and formatting times excluded

&amp;gt;&amp;gt; Day 22b
benchmarking...
time                 7.770 ms   (7.469 ms .. 8.183 ms)
                     0.988 R²   (0.976 R² .. 0.999 R²)
mean                 7.805 ms   (7.666 ms .. 7.963 ms)
std dev              398.9 μs   (262.8 μs .. 568.5 μs)
variance introduced by outliers: 25% (moderately inflated)

* parsing and formatting times excluded&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md#day-22</link>
      <pubDate>Tue, 22 Dec 2020 01:00:00 EST</pubDate>
    </item>

    <item>
      <title>Day 21</title>
      <description>&lt;h2 id=&quot;day-21&quot;&gt;Day 21&lt;/h2&gt;
&lt;!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day21.md`.  If you want to edit this, edit
that file instead!
--&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://adventofcode.com/2020/day/21&quot;&gt;Prompt&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day21.hs&quot;&gt;Code&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://mstksg.github.io/advent-of-code-2020/src/AOC.Challenge.Day21.html&quot;&gt;Rendered&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day21.md&quot;&gt;Standalone Reflection Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Another nice self-contained constraint satisfaction problem, along the lines of &lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day16.md&quot;&gt;Day 16&lt;/a&gt; :) Actually, after solving this one, I went back and rewrote my day 16 solution in terms of a common solver function that works for both!&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | Given a map of @k@ to possible @a@s for that @k@, find possible&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- configurations where each @k@ is given its own unique @a@.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;pickUnique ::&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Ord&lt;/span&gt; k, &lt;span class=&quot;dt&quot;&gt;Ord&lt;/span&gt; a) &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; [(k, &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; a)] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; k a]&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;pickUnique mp &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;flip&lt;/span&gt; evalStateT S.empty &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;fu&quot;&gt;fmap&lt;/span&gt; M.fromList &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; for opts &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;traverse&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; \poss &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      seen &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; get&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      pick &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; lift &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; S.toList (poss &lt;span class=&quot;ot&quot;&gt;`S.difference`&lt;/span&gt; seen)&lt;/span&gt;
&lt;span id=&quot;cb1-8&quot;&gt;&lt;a href=&quot;#cb1-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      pick &lt;span class=&quot;op&quot;&gt;&amp;lt;$&lt;/span&gt; modify (S.insert pick)&lt;/span&gt;
&lt;span id=&quot;cb1-9&quot;&gt;&lt;a href=&quot;#cb1-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-10&quot;&gt;&lt;a href=&quot;#cb1-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    opts &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; sortOn (S.size &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;snd&lt;/span&gt;) mp&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It uses &lt;code&gt;StateT&lt;/code&gt; over list, like I described in &lt;a href=&quot;https://blog.jle.im/entry/unique-sample-drawing-searches-with-list-and-statet.html&quot;&gt;a constraint solving blog post&lt;/a&gt;. Basically it explores all of the possibilities of drawing from a state of “items left-over to assign”. The state is a &lt;code&gt;Set a&lt;/code&gt; of items not yet picked, and at every step we non-deterministically &lt;code&gt;pick&lt;/code&gt; an &lt;code&gt;a&lt;/code&gt; out of the given &lt;code&gt;(k, Set a)&lt;/code&gt; of options that hasn’t already been chosen. We use that pick and add that picked item to the picked item set along that branch.&lt;/p&gt;
&lt;p&gt;We also sort by the size of the possibility set for each &lt;code&gt;k&lt;/code&gt;, because starting with smaller possibilities keeps our tree tight at the top, instead of wide — we can eliminate options much more quickly.&lt;/p&gt;
&lt;p&gt;Now all we need to do is to get our information into a &lt;code&gt;[(k, Set a)]&lt;/code&gt;. In our case, this is &lt;code&gt;[(String, Set String)]&lt;/code&gt; – with each allergen, associate a set of possible foods they might be associated with.&lt;/p&gt;
&lt;p&gt;We can do this by just taking an intersection of all the possibilities on each line:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;assembleOptions&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Ord&lt;/span&gt; k, &lt;span class=&quot;dt&quot;&gt;Ord&lt;/span&gt; a)&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; [(&lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; a, &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; k)] &lt;span class=&quot;co&quot;&gt;-- set of foods, set of allergens&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; k (&lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; a)    &lt;span class=&quot;co&quot;&gt;-- each allergen with the foods they were seen with in all occurrences&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;assembleOptions info &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; M.unionsWith S.intersection &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [ M.fromSet (&lt;span class=&quot;fu&quot;&gt;const&lt;/span&gt; igr) alg   &lt;span class=&quot;co&quot;&gt;-- a map of allergens to all foods they were seen with in this item&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-7&quot;&gt;&lt;a href=&quot;#cb2-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; (igr, alg) &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; info&lt;/span&gt;
&lt;span id=&quot;cb2-8&quot;&gt;&lt;a href=&quot;#cb2-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We generate a list of allergens to all foods they were seen with on each item, and then &lt;code&gt;intersect&lt;/code&gt; all of those foods within an allergen, so that our final &lt;code&gt;Map k (Set a)&lt;/code&gt; matches each &lt;code&gt;k&lt;/code&gt; allergen with a set ofall foods that were present in &lt;em&gt;all&lt;/em&gt; of the occurrences of each allergen.&lt;/p&gt;
&lt;p&gt;Now part 2 is basically just reading off the results of &lt;code&gt;pickUnique&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part2 ::&lt;/span&gt; [(&lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;)] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;fmap&lt;/span&gt; M.elems &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; listToMaybe &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; pickUnique &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; assembleOptions&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We definitely have a nice advantage here in that the &lt;code&gt;Map String String&lt;/code&gt; (the result map of allergens to foods) already is sorted in order of allergens (alphabetically), so no need to do anything other than just &lt;code&gt;M.elems&lt;/code&gt; :)&lt;/p&gt;
&lt;p&gt;Part 1 is definitely slightly more complicated: not only do we need to find the allergenic foods, we have to count the occurrences of non-allergenic foods in all the items:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part2 ::&lt;/span&gt; [(&lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;)] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2 info &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-3&quot;&gt;&lt;a href=&quot;#cb4-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    allergenicFoods &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;fmap&lt;/span&gt; (S.fromList &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; M.elems)&lt;/span&gt;
&lt;span id=&quot;cb4-4&quot;&gt;&lt;a href=&quot;#cb4-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                     &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; listToMaybe&lt;/span&gt;
&lt;span id=&quot;cb4-5&quot;&gt;&lt;a href=&quot;#cb4-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                     &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; pickUnique&lt;/span&gt;
&lt;span id=&quot;cb4-6&quot;&gt;&lt;a href=&quot;#cb4-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                     &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; assembleOptions&lt;/span&gt;
&lt;span id=&quot;cb4-7&quot;&gt;&lt;a href=&quot;#cb4-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                     &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; info&lt;/span&gt;
&lt;span id=&quot;cb4-8&quot;&gt;&lt;a href=&quot;#cb4-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-9&quot;&gt;&lt;a href=&quot;#cb4-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      [ &lt;span class=&quot;fu&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;filter&lt;/span&gt; (&lt;span class=&quot;ot&quot;&gt;`S.notMember`&lt;/span&gt; allergenicFoods) foods&lt;/span&gt;
&lt;span id=&quot;cb4-10&quot;&gt;&lt;a href=&quot;#cb4-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; (foods, _) &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; info&lt;/span&gt;
&lt;span id=&quot;cb4-11&quot;&gt;&lt;a href=&quot;#cb4-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      ]&lt;/span&gt;
&lt;span id=&quot;cb4-12&quot;&gt;&lt;a href=&quot;#cb4-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-13&quot;&gt;&lt;a href=&quot;#cb4-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    allFoodOccurrences ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb4-14&quot;&gt;&lt;a href=&quot;#cb4-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    allFoodOccurrences &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;concatMap&lt;/span&gt; (S.toList &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;fst&lt;/span&gt;) info&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;day-21-benchmarks&quot;&gt;Day 21 Benchmarks&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; Day 21a
benchmarking...
time                 270.6 μs   (267.0 μs .. 277.0 μs)
                     0.997 R²   (0.994 R² .. 0.999 R²)
mean                 273.1 μs   (269.2 μs .. 283.4 μs)
std dev              22.37 μs   (8.162 μs .. 40.92 μs)
variance introduced by outliers: 71% (severely inflated)

* parsing and formatting times excluded

&amp;gt;&amp;gt; Day 21b
benchmarking...
time                 162.9 μs   (160.4 μs .. 165.9 μs)
                     0.997 R²   (0.994 R² .. 1.000 R²)
mean                 160.2 μs   (158.4 μs .. 165.3 μs)
std dev              9.685 μs   (3.385 μs .. 17.84 μs)
variance introduced by outliers: 59% (severely inflated)

* parsing and formatting times excluded&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md#day-21</link>
      <pubDate>Mon, 21 Dec 2020 01:00:00 EST</pubDate>
    </item>

    <item>
      <title>Day 20</title>
      <description>&lt;h2 id=&quot;day-20&quot;&gt;Day 20&lt;/h2&gt;
&lt;!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day20.md`.  If you want to edit this, edit
that file instead!
--&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://adventofcode.com/2020/day/20&quot;&gt;Prompt&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day20.hs&quot;&gt;Code&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://mstksg.github.io/advent-of-code-2020/src/AOC.Challenge.Day20.html&quot;&gt;Rendered&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day20.md&quot;&gt;Standalone Reflection Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Ah, the infamous Day 20 :) I actually went through a few different possible solutions for this before settling on the one I have now. It also pushed me to flesh out my “direction manipulation” mini-library (that I used &lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day12.md&quot;&gt;Day 12&lt;/a&gt;) to be a full “orientation manipulation” mini-library. With it, I get to enumerate, manipulate, and combine the eight possible orientations of a 2d square grid in a nice way.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Dir&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;North&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;East&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;South&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;West&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | Rotate a point by a direction&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;rotPoint ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Num&lt;/span&gt; a &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Dir&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; a &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; a&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;allDir ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Dir&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;allDir &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;North&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;..&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb1-8&quot;&gt;&lt;a href=&quot;#cb1-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-9&quot;&gt;&lt;a href=&quot;#cb1-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- All of these instances are described in my day 12 writeup&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-10&quot;&gt;&lt;a href=&quot;#cb1-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Semigroup&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Dir&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-11&quot;&gt;&lt;a href=&quot;#cb1-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Monoid&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Dir&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-12&quot;&gt;&lt;a href=&quot;#cb1-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Group&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Dir&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-13&quot;&gt;&lt;a href=&quot;#cb1-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Abelian&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Dir&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-14&quot;&gt;&lt;a href=&quot;#cb1-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-15&quot;&gt;&lt;a href=&quot;#cb1-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | A possible orientation (flip and rotate) of a 2d square grid&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-16&quot;&gt;&lt;a href=&quot;#cb1-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; {&lt;span class=&quot;ot&quot;&gt; d8Rot ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Dir&lt;/span&gt;,&lt;span class=&quot;ot&quot;&gt; d8Flip ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Bool&lt;/span&gt; }&lt;/span&gt;
&lt;span id=&quot;cb1-17&quot;&gt;&lt;a href=&quot;#cb1-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-18&quot;&gt;&lt;a href=&quot;#cb1-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Semigroup&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-19&quot;&gt;&lt;a href=&quot;#cb1-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; x1 &lt;span class=&quot;dt&quot;&gt;False&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; x2 y2 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; (x1 &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt; x2) y2&lt;/span&gt;
&lt;span id=&quot;cb1-20&quot;&gt;&lt;a href=&quot;#cb1-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; x1 &lt;span class=&quot;dt&quot;&gt;True&lt;/span&gt;  &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; x2 y2 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; (x1 &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt; invert x2) (&lt;span class=&quot;fu&quot;&gt;not&lt;/span&gt; y2)&lt;/span&gt;
&lt;span id=&quot;cb1-21&quot;&gt;&lt;a href=&quot;#cb1-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-22&quot;&gt;&lt;a href=&quot;#cb1-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Monoid&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-23&quot;&gt;&lt;a href=&quot;#cb1-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;fu&quot;&gt;mempty&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;North&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;False&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-24&quot;&gt;&lt;a href=&quot;#cb1-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-25&quot;&gt;&lt;a href=&quot;#cb1-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Group&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-26&quot;&gt;&lt;a href=&quot;#cb1-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    invert (&lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; x &lt;span class=&quot;dt&quot;&gt;False&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; (invert x) &lt;span class=&quot;dt&quot;&gt;False&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-27&quot;&gt;&lt;a href=&quot;#cb1-27&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    invert (&lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; x &lt;span class=&quot;dt&quot;&gt;True&lt;/span&gt; ) &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; x          &lt;span class=&quot;dt&quot;&gt;True&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-28&quot;&gt;&lt;a href=&quot;#cb1-28&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-29&quot;&gt;&lt;a href=&quot;#cb1-29&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;allD8 ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb1-30&quot;&gt;&lt;a href=&quot;#cb1-30&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;allD8 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; allDir &lt;span class=&quot;op&quot;&gt;&amp;lt;*&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;False&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;True&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb1-31&quot;&gt;&lt;a href=&quot;#cb1-31&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-32&quot;&gt;&lt;a href=&quot;#cb1-32&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | Rotate and flip a point by a &amp;#39;D8&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-33&quot;&gt;&lt;a href=&quot;#cb1-33&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;orientPoint ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Num&lt;/span&gt; a &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; a &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; a&lt;/span&gt;
&lt;span id=&quot;cb1-34&quot;&gt;&lt;a href=&quot;#cb1-34&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;orientPoint &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-35&quot;&gt;&lt;a href=&quot;#cb1-35&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;North&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;False&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;id&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-36&quot;&gt;&lt;a href=&quot;#cb1-36&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;East&lt;/span&gt;  &lt;span class=&quot;dt&quot;&gt;False&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; \(&lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; x y) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt;   y  (&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;x)&lt;/span&gt;
&lt;span id=&quot;cb1-37&quot;&gt;&lt;a href=&quot;#cb1-37&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;West&lt;/span&gt;  &lt;span class=&quot;dt&quot;&gt;False&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; \(&lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; x y) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;y)   x&lt;/span&gt;
&lt;span id=&quot;cb1-38&quot;&gt;&lt;a href=&quot;#cb1-38&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;South&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;False&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; \(&lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; x y) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;x) (&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;y)&lt;/span&gt;
&lt;span id=&quot;cb1-39&quot;&gt;&lt;a href=&quot;#cb1-39&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;North&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;True&lt;/span&gt;  &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; \(&lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; x y) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;x)   y&lt;/span&gt;
&lt;span id=&quot;cb1-40&quot;&gt;&lt;a href=&quot;#cb1-40&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;East&lt;/span&gt;  &lt;span class=&quot;dt&quot;&gt;True&lt;/span&gt;  &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; \(&lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; x y) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt;   y    x&lt;/span&gt;
&lt;span id=&quot;cb1-41&quot;&gt;&lt;a href=&quot;#cb1-41&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;West&lt;/span&gt;  &lt;span class=&quot;dt&quot;&gt;True&lt;/span&gt;  &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; \(&lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; x y) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;y) (&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;x)&lt;/span&gt;
&lt;span id=&quot;cb1-42&quot;&gt;&lt;a href=&quot;#cb1-42&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;South&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;True&lt;/span&gt;  &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; \(&lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; x y) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt;   x  (&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;y)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Having orientations as a data type I can manipulate as first-class values helped me “think” my way through everything a little easier.&lt;/p&gt;
&lt;p&gt;First things first, we can break apart a 10x10 tile into the parts that actually matter: its eight edges (which we can represent as a set of &lt;code&gt;Finite 10&lt;/code&gt;s) and its core (which we can represent as a set of &lt;code&gt;V2 (Finite 8)&lt;/code&gt;, 8x8 points). I’m using &lt;code&gt;Finite&lt;/code&gt; from &lt;em&gt;&lt;a href=&quot;https://hackage.haskell.org/package/finite-typelits&quot;&gt;finite-typelits&lt;/a&gt;&lt;/em&gt; mostly as a way for me to keep track of what I have at each stage — remember that &lt;code&gt;Finite 8&lt;/code&gt;, for instance, is one of 0,1,2,3,4,5,6, or 7. This is also handy because the library gives us &lt;code&gt;strengthen &amp;lt;=&amp;lt; unshift :: Finite 10 -&amp;gt; Maybe (Finite 8)&lt;/code&gt;, that lets us “chop off” the outer edges of a &lt;code&gt;Set (Finite 10)&lt;/code&gt; to get the &lt;code&gt;Set (Finite 8)&lt;/code&gt; core.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Edge&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Finite&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;10&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Core&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Finite&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;8&lt;/span&gt;))&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | Shift corner to (0,0)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;shiftToZero ::&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Applicative&lt;/span&gt; f, &lt;span class=&quot;dt&quot;&gt;Num&lt;/span&gt; a, &lt;span class=&quot;dt&quot;&gt;Ord&lt;/span&gt; a) &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; a) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; a)&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-7&quot;&gt;&lt;a href=&quot;#cb2-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | mapMaybe but for sets&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-8&quot;&gt;&lt;a href=&quot;#cb2-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;mapMaybeSet ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Ord&lt;/span&gt; b &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; (a &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; b) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; a &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; b&lt;/span&gt;
&lt;span id=&quot;cb2-9&quot;&gt;&lt;a href=&quot;#cb2-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-10&quot;&gt;&lt;a href=&quot;#cb2-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;toTiles&lt;/span&gt;
&lt;span id=&quot;cb2-11&quot;&gt;&lt;a href=&quot;#cb2-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Finite&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;10&lt;/span&gt;))&lt;/span&gt;
&lt;span id=&quot;cb2-12&quot;&gt;&lt;a href=&quot;#cb2-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; ((&lt;span class=&quot;dt&quot;&gt;Core&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Edge&lt;/span&gt;), &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Edge&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb2-13&quot;&gt;&lt;a href=&quot;#cb2-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;toTiles ps &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; ((core, getEdge), M.toList (&lt;span class=&quot;fu&quot;&gt;map&lt;/span&gt; swap oToEdge))&lt;/span&gt;
&lt;span id=&quot;cb2-14&quot;&gt;&lt;a href=&quot;#cb2-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-15&quot;&gt;&lt;a href=&quot;#cb2-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    core      &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; mapMaybeSet (&lt;span class=&quot;fu&quot;&gt;traverse&lt;/span&gt; (strengthen &lt;span class=&quot;op&quot;&gt;&amp;lt;=&amp;lt;&lt;/span&gt; unshift)) ps&lt;/span&gt;
&lt;span id=&quot;cb2-16&quot;&gt;&lt;a href=&quot;#cb2-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    getEdge o &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; oMap &lt;span class=&quot;op&quot;&gt;M.!&lt;/span&gt; o&lt;/span&gt;
&lt;span id=&quot;cb2-17&quot;&gt;&lt;a href=&quot;#cb2-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    oMap      &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; M.fromList oToEdge&lt;/span&gt;
&lt;span id=&quot;cb2-18&quot;&gt;&lt;a href=&quot;#cb2-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    oToEdge   &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-19&quot;&gt;&lt;a href=&quot;#cb2-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        [ (o, mapMaybeSet (\(&lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; x y) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; x &lt;span class=&quot;op&quot;&gt;&amp;lt;$&lt;/span&gt; guard (y &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;)) ps&amp;#39;)&lt;/span&gt;
&lt;span id=&quot;cb2-20&quot;&gt;&lt;a href=&quot;#cb2-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; o &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; allD8&lt;/span&gt;
&lt;span id=&quot;cb2-21&quot;&gt;&lt;a href=&quot;#cb2-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        , &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; ps&amp;#39; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; shiftToZero &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; orientPoint (invert o) &lt;span class=&quot;ot&quot;&gt;`S.map`&lt;/span&gt; ps&lt;/span&gt;
&lt;span id=&quot;cb2-22&quot;&gt;&lt;a href=&quot;#cb2-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Both “orientation to edge at that orientation” (&lt;code&gt;D8 -&amp;gt; Edge&lt;/code&gt;) and “edge to the orientation that that edge exists at” (&lt;code&gt;Map Edge D8&lt;/code&gt;) are useful things to have, so we can generate them both here.&lt;/p&gt;
&lt;p&gt;Once we do this we can get three separate &lt;code&gt;IntMap&lt;/code&gt;s after parsing the file:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;IntMap&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Core&lt;/span&gt;          &lt;span class=&quot;co&quot;&gt;-- a map of tile id&amp;#39;s to their cores (for drawing)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;IntMap&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Edge&lt;/span&gt;)  &lt;span class=&quot;co&quot;&gt;-- a map of tile id&amp;#39;s to their edges at each orientation&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;IntMap&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Edge&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt;) &lt;span class=&quot;co&quot;&gt;-- a map of tile id&amp;#39;s to all of their edges and the orientations they are at&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now for the actual solve — we’re going to build up a &lt;code&gt;Map Point (Int, D8)&lt;/code&gt; one at a time, where the point (&lt;code&gt;V2 Int&lt;/code&gt;) is going to contain the tile id at that point, as well as the orientation that tile has to be at.&lt;/p&gt;
&lt;p&gt;To do that, we’re going to use a queue of “open edges”: the location that the open edge is facing, and the direction (north/south/east/west) of that open edge – a &lt;code&gt;Map Edge (Point, Dir)&lt;/code&gt;. We’ll also keep a set of tile id’s that have not been placed yet. And then at each step:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Pop an edge off of that queue – &lt;code&gt;(Edge, (Point, Dir))&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Search to see if any non-used tiles have any matching edge
&lt;ol type=&quot;a&quot;&gt;
&lt;li&gt;If there is not any, it means that that edge is at the edge of the overall map, so just skip.&lt;/li&gt;
&lt;li&gt;If there is a tile, place that tile at the indicated &lt;code&gt;(Point, Dir)&lt;/code&gt; and place all of &lt;em&gt;its&lt;/em&gt; edges into the queue.&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
&lt;li&gt;Repeat until the queue is empty.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | A placement is a Tile ID and the orientation of that tile&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Placement&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb4-3&quot;&gt;&lt;a href=&quot;#cb4-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;     &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-4&quot;&gt;&lt;a href=&quot;#cb4-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-5&quot;&gt;&lt;a href=&quot;#cb4-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;assembleMap&lt;/span&gt;
&lt;span id=&quot;cb4-6&quot;&gt;&lt;a href=&quot;#cb4-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IntMap&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Edge&lt;/span&gt;)              &lt;span class=&quot;co&quot;&gt;-- ^ tile id to the edge at each orientation&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-7&quot;&gt;&lt;a href=&quot;#cb4-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IntMap&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Edge&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Placement&lt;/span&gt;)      &lt;span class=&quot;co&quot;&gt;-- ^ tile id to the map of edges to what tile id, orientation that edge is at&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-8&quot;&gt;&lt;a href=&quot;#cb4-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Placement&lt;/span&gt;              &lt;span class=&quot;co&quot;&gt;-- ^ map of points to the tile id, orientation at each point&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-9&quot;&gt;&lt;a href=&quot;#cb4-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;assembleMap tileMap tiles0 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-10&quot;&gt;&lt;a href=&quot;#cb4-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        go (toQueue &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;mempty&lt;/span&gt; t0id allDir)&lt;/span&gt;
&lt;span id=&quot;cb4-11&quot;&gt;&lt;a href=&quot;#cb4-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;           (IM.keysSet tiles1)&lt;/span&gt;
&lt;span id=&quot;cb4-12&quot;&gt;&lt;a href=&quot;#cb4-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;           (M.singleton &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; (t0id, &lt;span class=&quot;fu&quot;&gt;mempty&lt;/span&gt;))&lt;/span&gt;
&lt;span id=&quot;cb4-13&quot;&gt;&lt;a href=&quot;#cb4-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-14&quot;&gt;&lt;a href=&quot;#cb4-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;-- populate the initial tile and the initial queue&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-15&quot;&gt;&lt;a href=&quot;#cb4-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ((_   , t0Map), tiles1)  &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; IM.deleteFindMin tiles0&lt;/span&gt;
&lt;span id=&quot;cb4-16&quot;&gt;&lt;a href=&quot;#cb4-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ((_, (t0id, _)), _     ) &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; M.deleteFindMin  t0Map&lt;/span&gt;
&lt;span id=&quot;cb4-17&quot;&gt;&lt;a href=&quot;#cb4-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-18&quot;&gt;&lt;a href=&quot;#cb4-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;-- a cache of edges to tiles ID&amp;#39;s (and orientations) that have that edge.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-19&quot;&gt;&lt;a href=&quot;#cb4-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    tileCache ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Edge&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Placement&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb4-20&quot;&gt;&lt;a href=&quot;#cb4-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    tileCache &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; M.fromListWith (&lt;span class=&quot;op&quot;&gt;++&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb4-21&quot;&gt;&lt;a href=&quot;#cb4-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      [ (edge, [placement])&lt;/span&gt;
&lt;span id=&quot;cb4-22&quot;&gt;&lt;a href=&quot;#cb4-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; (_   , tileEdges) &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; IM.toList tiles0&lt;/span&gt;
&lt;span id=&quot;cb4-23&quot;&gt;&lt;a href=&quot;#cb4-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      , (edge, placement) &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; M.toList tileEdges&lt;/span&gt;
&lt;span id=&quot;cb4-24&quot;&gt;&lt;a href=&quot;#cb4-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      ]&lt;/span&gt;
&lt;span id=&quot;cb4-25&quot;&gt;&lt;a href=&quot;#cb4-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-26&quot;&gt;&lt;a href=&quot;#cb4-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    go  ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Edge&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Dir&lt;/span&gt;)     &lt;span class=&quot;co&quot;&gt;-- ^ queue: edge -&amp;gt; place, orientation&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-27&quot;&gt;&lt;a href=&quot;#cb4-27&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IntSet&lt;/span&gt;                    &lt;span class=&quot;co&quot;&gt;-- ^ leftover points&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-28&quot;&gt;&lt;a href=&quot;#cb4-28&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Placement&lt;/span&gt;       &lt;span class=&quot;co&quot;&gt;-- ^ current map&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-29&quot;&gt;&lt;a href=&quot;#cb4-29&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Placement&lt;/span&gt;       &lt;span class=&quot;co&quot;&gt;-- ^ sweet tail rescursion&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-30&quot;&gt;&lt;a href=&quot;#cb4-30&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    go queue tiles mp &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt; M.minViewWithKey queue &lt;span class=&quot;kw&quot;&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-31&quot;&gt;&lt;a href=&quot;#cb4-31&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; mp&lt;/span&gt;
&lt;span id=&quot;cb4-32&quot;&gt;&lt;a href=&quot;#cb4-32&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; ((edge, (pos, d)), queue&amp;#39;) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-33&quot;&gt;&lt;a href=&quot;#cb4-33&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt; find ((&lt;span class=&quot;ot&quot;&gt;`IS.member`&lt;/span&gt; tiles) &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;fst&lt;/span&gt;) (tileCache &lt;span class=&quot;op&quot;&gt;NEM.!&lt;/span&gt; edge) &lt;span class=&quot;kw&quot;&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-34&quot;&gt;&lt;a href=&quot;#cb4-34&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;          &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;          &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; go queue&amp;#39; tiles mp&lt;/span&gt;
&lt;span id=&quot;cb4-35&quot;&gt;&lt;a href=&quot;#cb4-35&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;          &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; (tileId, o) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-36&quot;&gt;&lt;a href=&quot;#cb4-36&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;co&quot;&gt;-- If we&amp;#39;re adding a North edge, then it&amp;#39;s the new tile&amp;#39;s South&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-37&quot;&gt;&lt;a href=&quot;#cb4-37&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;co&quot;&gt;-- edge; if we are adding a East edge, it&amp;#39;s the new tile&amp;#39;s West&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-38&quot;&gt;&lt;a href=&quot;#cb4-38&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;co&quot;&gt;-- edge, etc; (d &amp;lt;&amp;gt; South) is the right relationship to properly&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-39&quot;&gt;&lt;a href=&quot;#cb4-39&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;co&quot;&gt;-- flip&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-40&quot;&gt;&lt;a href=&quot;#cb4-40&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; o&amp;#39;       &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; o &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; (d &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;South&lt;/span&gt;) &lt;span class=&quot;dt&quot;&gt;True&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-41&quot;&gt;&lt;a href=&quot;#cb4-41&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                newQueue &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; toQueue pos o&amp;#39;&lt;/span&gt;
&lt;span id=&quot;cb4-42&quot;&gt;&lt;a href=&quot;#cb4-42&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    tileId&lt;/span&gt;
&lt;span id=&quot;cb4-43&quot;&gt;&lt;a href=&quot;#cb4-43&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    (&lt;span class=&quot;fu&quot;&gt;filter&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;/=&lt;/span&gt; d &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;South&lt;/span&gt;) allDir)&lt;/span&gt;
&lt;span id=&quot;cb4-44&quot;&gt;&lt;a href=&quot;#cb4-44&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;kw&quot;&gt;in&lt;/span&gt;  go  (newQueue &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt; queue)&lt;/span&gt;
&lt;span id=&quot;cb4-45&quot;&gt;&lt;a href=&quot;#cb4-45&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    (IS.delete tileId tiles)&lt;/span&gt;
&lt;span id=&quot;cb4-46&quot;&gt;&lt;a href=&quot;#cb4-46&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    (M.insert pos (tileId, invert o&amp;#39;) mp)&lt;/span&gt;
&lt;span id=&quot;cb4-47&quot;&gt;&lt;a href=&quot;#cb4-47&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-48&quot;&gt;&lt;a href=&quot;#cb4-48&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;-- | For a given image, add the given edges into the queue&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-49&quot;&gt;&lt;a href=&quot;#cb4-49&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    toQueue&lt;/span&gt;
&lt;span id=&quot;cb4-50&quot;&gt;&lt;a href=&quot;#cb4-50&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;        ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Foldable&lt;/span&gt; f&lt;/span&gt;
&lt;span id=&quot;cb4-51&quot;&gt;&lt;a href=&quot;#cb4-51&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;            &lt;span class=&quot;co&quot;&gt;-- ^ location of corner&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-52&quot;&gt;&lt;a href=&quot;#cb4-52&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt;               &lt;span class=&quot;co&quot;&gt;-- ^ orientation to insert&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-53&quot;&gt;&lt;a href=&quot;#cb4-53&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;              &lt;span class=&quot;co&quot;&gt;-- ^ tile id&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-54&quot;&gt;&lt;a href=&quot;#cb4-54&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; f &lt;span class=&quot;dt&quot;&gt;Dir&lt;/span&gt;            &lt;span class=&quot;co&quot;&gt;-- ^ edges to insert&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-55&quot;&gt;&lt;a href=&quot;#cb4-55&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Edge&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Dir&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb4-56&quot;&gt;&lt;a href=&quot;#cb4-56&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    toQueue p0 o tileId ds &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; M.fromList &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; ds &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;amp;&amp;gt;&lt;/span&gt; \d &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt;   &lt;span class=&quot;co&quot;&gt;-- for each dir&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-57&quot;&gt;&lt;a href=&quot;#cb4-57&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        ( (tileMap &lt;span class=&quot;op&quot;&gt;IM.!&lt;/span&gt; tileId) (o &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;D8&lt;/span&gt; d &lt;span class=&quot;dt&quot;&gt;False&lt;/span&gt;)   &lt;span class=&quot;co&quot;&gt;-- the edge&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-58&quot;&gt;&lt;a href=&quot;#cb4-58&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        , ( p0 &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; rotPoint d (&lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;))             &lt;span class=&quot;co&quot;&gt;-- the new point&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-59&quot;&gt;&lt;a href=&quot;#cb4-59&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;          , d&lt;/span&gt;
&lt;span id=&quot;cb4-60&quot;&gt;&lt;a href=&quot;#cb4-60&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;          )&lt;/span&gt;
&lt;span id=&quot;cb4-61&quot;&gt;&lt;a href=&quot;#cb4-61&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        )&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can wrap this all up in a solver to extract the &lt;code&gt;Map Point Placement&lt;/code&gt; (using &lt;code&gt;assembleMap&lt;/code&gt;) and the &lt;code&gt;Set Point&lt;/code&gt; — the “actual” pixel map that represents all of the points themselves in 2d space.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;solve&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IntMap&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Finite&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;10&lt;/span&gt;)))&lt;/span&gt;
&lt;span id=&quot;cb5-3&quot;&gt;&lt;a href=&quot;#cb5-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Placement&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb5-4&quot;&gt;&lt;a href=&quot;#cb5-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;solve ts &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; (shiftToZero mp, blitted)&lt;/span&gt;
&lt;span id=&quot;cb5-5&quot;&gt;&lt;a href=&quot;#cb5-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-6&quot;&gt;&lt;a href=&quot;#cb5-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    info    &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; toTiles &lt;span class=&quot;op&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; ts&lt;/span&gt;
&lt;span id=&quot;cb5-7&quot;&gt;&lt;a href=&quot;#cb5-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    edgeMap &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; IM.mapWithKey (\i (_, e) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (i,) &lt;span class=&quot;op&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; e) info&lt;/span&gt;
&lt;span id=&quot;cb5-8&quot;&gt;&lt;a href=&quot;#cb5-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    edges   &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;snd&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;fst&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; info&lt;/span&gt;
&lt;span id=&quot;cb5-9&quot;&gt;&lt;a href=&quot;#cb5-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    mp      &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; assembleMap edges edgeMap&lt;/span&gt;
&lt;span id=&quot;cb5-10&quot;&gt;&lt;a href=&quot;#cb5-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    blitted &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;flip&lt;/span&gt; M.foldMapWithKey mp &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; \p (tileId, o) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-11&quot;&gt;&lt;a href=&quot;#cb5-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; core &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;fst&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;fst&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; info &lt;span class=&quot;op&quot;&gt;IM.!&lt;/span&gt; tileId&lt;/span&gt;
&lt;span id=&quot;cb5-12&quot;&gt;&lt;a href=&quot;#cb5-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;kw&quot;&gt;in&lt;/span&gt;  S.map ((&lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; (p &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;8&lt;/span&gt;)) &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; shiftToZero &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; orientPoint o) core&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can use the &lt;code&gt;Map Point Placement&lt;/code&gt; to get the answer to part 1: just look at the tile id’s at the corners of the map. Since we &lt;code&gt;shiftToZero&lt;/code&gt;, we can just look up &lt;code&gt;mp M.! V2 0 0&lt;/code&gt;, &lt;code&gt;mp M.! V2 0 12&lt;/code&gt;, &lt;code&gt;mp M.! V2 12 0&lt;/code&gt;, and &lt;code&gt;mp M.! V2 12 12&lt;/code&gt;, and multiply them all together.&lt;/p&gt;
&lt;p&gt;For part 2, after we assemble the actual &lt;code&gt;Point&lt;/code&gt;, we can do a search for all dragons at all orientations.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb6&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb6-1&quot;&gt;&lt;a href=&quot;#cb6-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | given a pattern and a map of points, poke out all points matching that&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-2&quot;&gt;&lt;a href=&quot;#cb6-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- pattern.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-3&quot;&gt;&lt;a href=&quot;#cb6-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;pokePattern&lt;/span&gt;
&lt;span id=&quot;cb6-4&quot;&gt;&lt;a href=&quot;#cb6-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;    &lt;span class=&quot;co&quot;&gt;-- ^ pattern&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-5&quot;&gt;&lt;a href=&quot;#cb6-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;    &lt;span class=&quot;co&quot;&gt;-- ^ map&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-6&quot;&gt;&lt;a href=&quot;#cb6-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-7&quot;&gt;&lt;a href=&quot;#cb6-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;pokePattern pat ps0 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; foldl&amp;#39; go ps0 (&lt;span class=&quot;fu&quot;&gt;range&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;96&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;96&lt;/span&gt;))&lt;/span&gt;
&lt;span id=&quot;cb6-8&quot;&gt;&lt;a href=&quot;#cb6-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-9&quot;&gt;&lt;a href=&quot;#cb6-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    go ps d&lt;/span&gt;
&lt;span id=&quot;cb6-10&quot;&gt;&lt;a href=&quot;#cb6-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; pat&amp;#39; &lt;span class=&quot;ot&quot;&gt;`S.isSubsetOf`&lt;/span&gt; ps &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; ps &lt;span class=&quot;dt&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;\\ pat&amp;#39;&lt;/span&gt;
&lt;span id=&quot;cb6-11&quot;&gt;&lt;a href=&quot;#cb6-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;otherwise&lt;/span&gt;              &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; ps&lt;/span&gt;
&lt;span id=&quot;cb6-12&quot;&gt;&lt;a href=&quot;#cb6-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-13&quot;&gt;&lt;a href=&quot;#cb6-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        pat&amp;#39; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; S.mapMonotonic (&lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; d) pat&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And now we try &lt;code&gt;pokePattern&lt;/code&gt; with the dragon at all orientations until we find one that gets any pokes:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb7&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb7-1&quot;&gt;&lt;a href=&quot;#cb7-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;dragon ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;         &lt;span class=&quot;co&quot;&gt;-- the dragon image&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-2&quot;&gt;&lt;a href=&quot;#cb7-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-3&quot;&gt;&lt;a href=&quot;#cb7-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;allDragons ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;]   &lt;span class=&quot;co&quot;&gt;-- the dragon image at all orientations&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-4&quot;&gt;&lt;a href=&quot;#cb7-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;allDragons &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-5&quot;&gt;&lt;a href=&quot;#cb7-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [ shiftToZero &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; orientPoint o &lt;span class=&quot;ot&quot;&gt;`S.map`&lt;/span&gt; dragon&lt;/span&gt;
&lt;span id=&quot;cb7-6&quot;&gt;&lt;a href=&quot;#cb7-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; o &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; allD8&lt;/span&gt;
&lt;span id=&quot;cb7-7&quot;&gt;&lt;a href=&quot;#cb7-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ]&lt;/span&gt;
&lt;span id=&quot;cb7-8&quot;&gt;&lt;a href=&quot;#cb7-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-9&quot;&gt;&lt;a href=&quot;#cb7-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;dragonCount&lt;/span&gt;
&lt;span id=&quot;cb7-10&quot;&gt;&lt;a href=&quot;#cb7-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-11&quot;&gt;&lt;a href=&quot;#cb7-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-12&quot;&gt;&lt;a href=&quot;#cb7-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;dragonCount fullMap &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; listToMaybe&lt;/span&gt;
&lt;span id=&quot;cb7-13&quot;&gt;&lt;a href=&quot;#cb7-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [ res&lt;/span&gt;
&lt;span id=&quot;cb7-14&quot;&gt;&lt;a href=&quot;#cb7-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; drgn &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; allDragons&lt;/span&gt;
&lt;span id=&quot;cb7-15&quot;&gt;&lt;a href=&quot;#cb7-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; res &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; S.size &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; pokePattern drgn fullMap&lt;/span&gt;
&lt;span id=&quot;cb7-16&quot;&gt;&lt;a href=&quot;#cb7-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , res &lt;span class=&quot;op&quot;&gt;/=&lt;/span&gt; S.size fullMap&lt;/span&gt;
&lt;span id=&quot;cb7-17&quot;&gt;&lt;a href=&quot;#cb7-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And that concludes my solve of what was probably the most complex challenge of the month! Overall a lot of moving parts, but I was at least very happy to be able to use some knowledge of group theory (in particular, how the orientations of a square compose and interact) to break the puzzle down into pieces that were much easier to think about.&lt;/p&gt;
&lt;h3 id=&quot;day-20-benchmarks&quot;&gt;Day 20 Benchmarks&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; Day 20a
benchmarking...
time                 29.10 ms   (28.84 ms .. 29.92 ms)
                     0.997 R²   (0.990 R² .. 1.000 R²)
mean                 29.03 ms   (28.81 ms .. 29.63 ms)
std dev              762.3 μs   (159.7 μs .. 1.370 ms)

* parsing and formatting times excluded

&amp;gt;&amp;gt; Day 20b
benchmarking...
time                 73.35 ms   (66.76 ms .. 90.08 ms)
                     0.931 R²   (0.829 R² .. 1.000 R²)
mean                 69.27 ms   (66.81 ms .. 78.84 ms)
std dev              7.768 ms   (154.8 μs .. 13.53 ms)
variance introduced by outliers: 35% (moderately inflated)

* parsing and formatting times excluded&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md#day-20</link>
      <pubDate>Sun, 20 Dec 2020 01:00:00 EST</pubDate>
    </item>

    <item>
      <title>Day 19</title>
      <description>&lt;h2 id=&quot;day-19&quot;&gt;Day 19&lt;/h2&gt;
&lt;!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day19.md`.  If you want to edit this, edit
that file instead!
--&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://adventofcode.com/2020/day/19&quot;&gt;Prompt&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day19.hs&quot;&gt;Code&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://mstksg.github.io/advent-of-code-2020/src/AOC.Challenge.Day19.html&quot;&gt;Rendered&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day19.md&quot;&gt;Standalone Reflection Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I had originally solved this puzzle using recursive knot tying and a funky custom Monad — the writeup for that is &lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/5065aad720f6996386e9c94fbd7904a6fa9f2d9d/reflections-out/day19.md&quot;&gt;available online here&lt;/a&gt;. But after some thought and reflection, I saw that things might be a little cleaner as a hylomorphism from &lt;em&gt;&lt;a href=&quot;https://hackage.haskell.org/package/recursion-schemes&quot;&gt;recursion-schemes&lt;/a&gt;&lt;/em&gt;, so I did a rewrite based on it! It also ended up being about 25% faster to run, which was a nice bonus. Note that I do have a &lt;a href=&quot;&quot;&gt;blog post on hylomorphisms and recurion schemes&lt;/a&gt; (https://blog.jle.im/entry/tries-with-recursion-schemes.html), if you’d like to investigate more about the topic :)&lt;/p&gt;
&lt;p&gt;The central type (“base functor”) is &lt;code&gt;Rule&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Rule&lt;/span&gt; a &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Simple&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Char&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Compound&lt;/span&gt; [[a]]&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Show&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Eq&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Ord&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Generic&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Functor&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A &lt;code&gt;Rule a&lt;/code&gt; is either a “base” &lt;code&gt;Char&lt;/code&gt; match, or it is a list of options of sequences (a list of “or”’s of “and then”’s) of &lt;code&gt;a&lt;/code&gt;. The choice of &lt;code&gt;a&lt;/code&gt; gives us our interesting behavior.&lt;/p&gt;
&lt;p&gt;For example, our initial ruleset from the input file is a list of &lt;code&gt;Rule Int&lt;/code&gt;s: either they are a simple &lt;code&gt;Char&lt;/code&gt;, or they contain a list of options of sequences of rule id’s (&lt;code&gt;Int&lt;/code&gt;). We can load it all as an &lt;code&gt;IntMap (Rule Int)&lt;/code&gt;, where each &lt;code&gt;Rule Int&lt;/code&gt; is stored under its rule ID.&lt;/p&gt;
&lt;p&gt;Just to help us get an intuition for this type, let’s look at what happens if we want to “expand” out a rule all the way to only leaves at the end of a bunch of nested choices and sequences. This isn’t required for the solve, but could be pretty fun.&lt;/p&gt;
&lt;p&gt;For that, we can use the &lt;code&gt;Fix&lt;/code&gt; data type:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Fix&lt;/span&gt; f &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Fix&lt;/span&gt; (f (&lt;span class=&quot;dt&quot;&gt;Fix&lt;/span&gt; f))&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;ExpandedRule&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Fix&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Rule&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A &lt;code&gt;Fix Rule&lt;/code&gt; is infinite nested &lt;code&gt;Rule&lt;/code&gt;s: it’s essentially &lt;code&gt;Rule (Rule (Rule (Rule ...)))&lt;/code&gt; forever, meaning underneath each &lt;code&gt;Compound&lt;/code&gt; are new rules, and at the end of it all we only have &lt;code&gt;Leaf Char&lt;/code&gt;s, and no more &lt;code&gt;Int&lt;/code&gt;s. For example, we could represent rule 0 of&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;0: 1 2 | 3
1: 3
2: 3 3
3: &amp;quot;a&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;as&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;Fix&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Compound&lt;/span&gt; [&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [&lt;span class=&quot;dt&quot;&gt;Fix&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Compoud&lt;/span&gt; [[&lt;span class=&quot;dt&quot;&gt;Fix&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Leaf&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;)]], &lt;span class=&quot;dt&quot;&gt;Fix&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Compound&lt;/span&gt; [[&lt;span class=&quot;dt&quot;&gt;Fix&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Leaf&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;), &lt;span class=&quot;dt&quot;&gt;Fix&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Leaf&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;)]]]&lt;/span&gt;
&lt;span id=&quot;cb4-3&quot;&gt;&lt;a href=&quot;#cb4-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , [&lt;span class=&quot;dt&quot;&gt;Fix&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Leaf&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;)]&lt;/span&gt;
&lt;span id=&quot;cb4-4&quot;&gt;&lt;a href=&quot;#cb4-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But, given an &lt;code&gt;IntMap (Rule Int)&lt;/code&gt; (the “unexpanded” raw rules as they are in the input file), how do we get our &lt;code&gt;Fix Rule&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;We can use the handy &lt;code&gt;ana&lt;/code&gt; function, which, given an expansion function &lt;code&gt;a -&amp;gt; Rule a&lt;/code&gt;, returns a &lt;code&gt;a -&amp;gt; Fix Rule&lt;/code&gt;: It runs the &lt;code&gt;a -&amp;gt; Rule a&lt;/code&gt; expansion function on the “seed” &lt;code&gt;a&lt;/code&gt;, and then runs it again on all the &lt;code&gt;a&lt;/code&gt;s in the result, and again, and again, etc., until there are no more &lt;code&gt;a&lt;/code&gt;s to expand.&lt;/p&gt;
&lt;p&gt;Well, in our case, our “expansion” function is &lt;code&gt;Int -&amp;gt; Rule Int&lt;/code&gt;: “To expand an &lt;code&gt;Int&lt;/code&gt;, look it up in the &lt;code&gt;IntMap Int (RuleInt)&lt;/code&gt;”. And that gives us a function to fully expand any rule number:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;expandRule ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IntMap&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Rule&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Fix&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Rule&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;expandRule rs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; ana (rs &lt;span class=&quot;op&quot;&gt;IM.!&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Neat, huh? That will fully expand the rule at any index by repeatedly re-expanding it with &lt;code&gt;(rs IM.!)&lt;/code&gt; until we are out of things to expand.&lt;/p&gt;
&lt;p&gt;Another fun thing we can write that we could actually use for part 1 is to turn an &lt;code&gt;Fix Rule&lt;/code&gt; into a list of all possible strings to match. We want to write a &lt;code&gt;Fix Rule -&amp;gt; [String]&lt;/code&gt; function by tearing down our recursive data type, and this could be nicely expressed with a catamorphism (&lt;code&gt;cata :: (Rule a -&amp;gt; a) -&amp;gt; Fix Rule -&amp;gt; a&lt;/code&gt;), where we specify how to tear down a “single layer” of our &lt;code&gt;Rule&lt;/code&gt; type, and &lt;code&gt;cata&lt;/code&gt; will generalize that to tear down the entire structure. I talk about this a bit &lt;a href=&quot;https://blog.jle.im/entry/tries-with-recursion-schemes.html&quot;&gt;in my recursion schemes blog post&lt;/a&gt;, and the explanation I give is “The &lt;code&gt;a&lt;/code&gt; values in the &lt;code&gt;Rule&lt;/code&gt; become the very things we swore to create.” — in this case, the &lt;code&gt;[String]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;So let’s write our &lt;code&gt;Rule [String] -&amp;gt; [String]&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb6&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb6-1&quot;&gt;&lt;a href=&quot;#cb6-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;generateAlg ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Rule&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb6-2&quot;&gt;&lt;a href=&quot;#cb6-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;generateAlg &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-3&quot;&gt;&lt;a href=&quot;#cb6-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;Simple&lt;/span&gt; c   &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [[c]]                                   &lt;span class=&quot;co&quot;&gt;-- the single single-char string is created&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-4&quot;&gt;&lt;a href=&quot;#cb6-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;Compoud&lt;/span&gt; xs &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;concatMap&lt;/span&gt; (&lt;span class=&quot;fu&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;concat&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;sequence&lt;/span&gt;) xs   &lt;span class=&quot;co&quot;&gt;-- concat/sequence all options&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And now &lt;code&gt;cata generateAlg&lt;/code&gt; will generate all possible matches from a ruleset&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb7&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb7-1&quot;&gt;&lt;a href=&quot;#cb7-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;ghci&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; cata generateAlg&lt;/span&gt;
&lt;span id=&quot;cb7-2&quot;&gt;&lt;a href=&quot;#cb7-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    (&lt;span class=&quot;dt&quot;&gt;Fix&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Compound&lt;/span&gt; [[&lt;span class=&quot;dt&quot;&gt;Fix&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Leaf&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;&amp;#39;h&amp;#39;&lt;/span&gt;), &lt;span class=&quot;dt&quot;&gt;Fix&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Leaf&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;&amp;#39;e&amp;#39;&lt;/span&gt;)], [&lt;span class=&quot;dt&quot;&gt;Fix&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Leaf&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;&amp;#39;h&amp;#39;&lt;/span&gt;)], [&lt;span class=&quot;dt&quot;&gt;Fix&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Leaf&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;&amp;#39;q&amp;#39;&lt;/span&gt;)]])&lt;/span&gt;
&lt;span id=&quot;cb7-3&quot;&gt;&lt;a href=&quot;#cb7-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;[&lt;span class=&quot;st&quot;&gt;&amp;quot;he&amp;quot;&lt;/span&gt;,&lt;span class=&quot;st&quot;&gt;&amp;quot;h&amp;quot;&lt;/span&gt;,&lt;span class=&quot;st&quot;&gt;&amp;quot;q&amp;quot;&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Okay, that’s enough playing around for now…time to find our real solution :)&lt;/p&gt;
&lt;p&gt;Note that we can “interpret” a rule to match it on a string by turning it into a &lt;code&gt;String -&amp;gt; [String]&lt;/code&gt;: it’ll take a string and return a list of the leftovers of every possible match. For example, running the rules &lt;code&gt;(he)|h|q&lt;/code&gt; on &lt;code&gt;&quot;hello&quot;&lt;/code&gt; &lt;em&gt;should&lt;/em&gt; give us &lt;code&gt;[&quot;llo&quot;,&quot;ello&quot;]&lt;/code&gt;. Then we can just see if we have any matches that return empty leftovers.&lt;/p&gt;
&lt;p&gt;For aid in thinking, let’s imagine turning a &lt;code&gt;Fix Rule&lt;/code&gt; into a &lt;code&gt;String -&amp;gt; [String]&lt;/code&gt;. We can do that with the help of &lt;code&gt;cata :: (Rule a -&amp;gt; a) -&amp;gt; Fix Rule -&amp;gt; a&lt;/code&gt;. Because we want to write a &lt;code&gt;Fix Rule -&amp;gt; (String -&amp;gt; [String])&lt;/code&gt;, our catamorphism function (“algebra”) is &lt;code&gt;Rule (String -&amp;gt; [String]) -&amp;gt; (String -&amp;gt; [String])&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb8&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb8-1&quot;&gt;&lt;a href=&quot;#cb8-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;matchAlg ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Rule&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;]) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb8-2&quot;&gt;&lt;a href=&quot;#cb8-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;matchAlg &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb8-3&quot;&gt;&lt;a href=&quot;#cb8-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;Simple&lt;/span&gt; c &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb8-4&quot;&gt;&lt;a href=&quot;#cb8-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      []   &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; []&lt;/span&gt;
&lt;span id=&quot;cb8-5&quot;&gt;&lt;a href=&quot;#cb8-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      d&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;ds &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;if&lt;/span&gt; c &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; d &lt;span class=&quot;kw&quot;&gt;then&lt;/span&gt; [ds] &lt;span class=&quot;kw&quot;&gt;else&lt;/span&gt; []&lt;/span&gt;
&lt;span id=&quot;cb8-6&quot;&gt;&lt;a href=&quot;#cb8-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;Compound&lt;/span&gt; xs &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; \str &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb8-7&quot;&gt;&lt;a href=&quot;#cb8-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;fu&quot;&gt;concatMap&lt;/span&gt; (sequenceAll str) xs&lt;/span&gt;
&lt;span id=&quot;cb8-8&quot;&gt;&lt;a href=&quot;#cb8-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb8-9&quot;&gt;&lt;a href=&quot;#cb8-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;-- run the String -&amp;gt; [String]s on an input String one after the other&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb8-10&quot;&gt;&lt;a href=&quot;#cb8-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    sequenceAll ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;]] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb8-11&quot;&gt;&lt;a href=&quot;#cb8-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    sequenceAll s0 fs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;foldr&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;&amp;gt;=&amp;gt;&lt;/span&gt;) &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; fs s0&lt;/span&gt;
&lt;span id=&quot;cb8-12&quot;&gt;&lt;a href=&quot;#cb8-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb8-13&quot;&gt;&lt;a href=&quot;#cb8-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;match ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Fix&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Rule&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb8-14&quot;&gt;&lt;a href=&quot;#cb8-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;match &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; cata matchAlg&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We want to fail on our input string (return no matches) if we see a &lt;code&gt;Simple c&lt;/code&gt; with either an empty input string or one that doesn’t match the &lt;code&gt;c&lt;/code&gt;. Then for the &lt;code&gt;Compound&lt;/code&gt; case with our &lt;code&gt;xs :: [[String -&amp;gt; [String]]]&lt;/code&gt;, we take a choice (&lt;code&gt;concatMap&lt;/code&gt;) of all of the possible full sequences of the inner &lt;code&gt;[String -&amp;gt; [String]]&lt;/code&gt; sequences.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb9&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb9-1&quot;&gt;&lt;a href=&quot;#cb9-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;ghci&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; match (&lt;span class=&quot;dt&quot;&gt;Fix&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Compound&lt;/span&gt; [[&lt;span class=&quot;dt&quot;&gt;Fix&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Leaf&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;&amp;#39;h&amp;#39;&lt;/span&gt;), &lt;span class=&quot;dt&quot;&gt;Fix&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Leaf&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;&amp;#39;e&amp;#39;&lt;/span&gt;)], [&lt;span class=&quot;dt&quot;&gt;Fix&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Leaf&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;&amp;#39;h&amp;#39;&lt;/span&gt;)], [&lt;span class=&quot;dt&quot;&gt;Fix&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Leaf&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;&amp;#39;q&amp;#39;&lt;/span&gt;)]])&lt;/span&gt;
&lt;span id=&quot;cb9-2&quot;&gt;&lt;a href=&quot;#cb9-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;st&quot;&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-3&quot;&gt;&lt;a href=&quot;#cb9-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;[&lt;span class=&quot;st&quot;&gt;&amp;quot;llo&amp;quot;&lt;/span&gt;, &lt;span class=&quot;st&quot;&gt;&amp;quot;ello&amp;quot;&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Alright, so now how do we solve the final puzzle?&lt;/p&gt;
&lt;p&gt;It looks like we need to “generate” a &lt;code&gt;Fix Rule&lt;/code&gt;, and &lt;em&gt;immediately&lt;/em&gt; tear it down into a &lt;code&gt;String -&amp;gt; [String]&lt;/code&gt; to use it to match a string. “Generate recursively and immediately tear down recursively”…that’s a hylomorphism!&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb10&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb10-1&quot;&gt;&lt;a href=&quot;#cb10-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;hylo ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Functor&lt;/span&gt; f &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; (f b &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; b) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (a &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; f a) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; a &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; b&lt;/span&gt;
&lt;span id=&quot;cb10-2&quot;&gt;&lt;a href=&quot;#cb10-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb10-3&quot;&gt;&lt;a href=&quot;#cb10-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- which we use as...&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb10-4&quot;&gt;&lt;a href=&quot;#cb10-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;hylo ::&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Rule&lt;/span&gt; b &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; b) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (a &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Rule&lt;/span&gt; a) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; a &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; b&lt;/span&gt;
&lt;span id=&quot;cb10-5&quot;&gt;&lt;a href=&quot;#cb10-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb10-6&quot;&gt;&lt;a href=&quot;#cb10-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- which we use as...&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb10-7&quot;&gt;&lt;a href=&quot;#cb10-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;hylo  ::&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Rule&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;]) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;]))&lt;/span&gt;
&lt;span id=&quot;cb10-8&quot;&gt;&lt;a href=&quot;#cb10-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Rule&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb10-9&quot;&gt;&lt;a href=&quot;#cb10-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb10-10&quot;&gt;&lt;a href=&quot;#cb10-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If we give &lt;code&gt;hylo&lt;/code&gt; a way to “break down nested &lt;code&gt;Rule&lt;/code&gt;s” and a way to “build up nested &lt;code&gt;Rule&lt;/code&gt;s”, then it can actually iteratively expand up &lt;code&gt;Rule&lt;/code&gt;s while immediately tearing them down. The nice thing about this is that it’s very lazy: it’ll only &lt;em&gt;call&lt;/em&gt; the generator function if you ever &lt;em&gt;need&lt;/em&gt; the thing during your teardown function. Since our teardown function (the &lt;code&gt;String -&amp;gt; [String]&lt;/code&gt;) will terminate whenever we encounter an empty string or no matches, &lt;code&gt;hylo&lt;/code&gt; will only run the build-up function until the point that we hit one of those conditions. You can also think of it as running it on a &lt;code&gt;Rule Int&lt;/code&gt; where each &lt;code&gt;Int&lt;/code&gt; is dynamically looked up as you need it from the rules map.&lt;/p&gt;
&lt;p&gt;The neat thing about this is that we don’t ever need &lt;code&gt;Fix&lt;/code&gt; at all: it’s all built up and torn down “in-place”, and we never built up any intermediate value. That’s why I mentioned that the &lt;code&gt;Fix&lt;/code&gt; part earlier was more of a side-tangent! But it definitely helps us understand the big picture, I feel.&lt;/p&gt;
&lt;p&gt;Our final code (the whole of it, minus the parser) ends up being:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb11&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb11-1&quot;&gt;&lt;a href=&quot;#cb11-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Rule&lt;/span&gt; a &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Simple&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Char&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-2&quot;&gt;&lt;a href=&quot;#cb11-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Compound&lt;/span&gt; [[a]]&lt;/span&gt;
&lt;span id=&quot;cb11-3&quot;&gt;&lt;a href=&quot;#cb11-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Show&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Eq&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Ord&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Generic&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Functor&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb11-4&quot;&gt;&lt;a href=&quot;#cb11-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-5&quot;&gt;&lt;a href=&quot;#cb11-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;matchAlg ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Rule&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;]) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb11-6&quot;&gt;&lt;a href=&quot;#cb11-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;matchAlg &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-7&quot;&gt;&lt;a href=&quot;#cb11-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;Simple&lt;/span&gt; c &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-8&quot;&gt;&lt;a href=&quot;#cb11-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      []   &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; []&lt;/span&gt;
&lt;span id=&quot;cb11-9&quot;&gt;&lt;a href=&quot;#cb11-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      d&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;ds &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;if&lt;/span&gt; c &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; d &lt;span class=&quot;kw&quot;&gt;then&lt;/span&gt; [ds] &lt;span class=&quot;kw&quot;&gt;else&lt;/span&gt; []&lt;/span&gt;
&lt;span id=&quot;cb11-10&quot;&gt;&lt;a href=&quot;#cb11-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;Compound&lt;/span&gt; xs &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; \str &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-11&quot;&gt;&lt;a href=&quot;#cb11-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;fu&quot;&gt;concatMap&lt;/span&gt; (sequenceAll str) xs&lt;/span&gt;
&lt;span id=&quot;cb11-12&quot;&gt;&lt;a href=&quot;#cb11-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-13&quot;&gt;&lt;a href=&quot;#cb11-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    sequenceAll s0 fs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;foldr&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;&amp;gt;=&amp;gt;&lt;/span&gt;) &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; fs s0&lt;/span&gt;
&lt;span id=&quot;cb11-14&quot;&gt;&lt;a href=&quot;#cb11-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-15&quot;&gt;&lt;a href=&quot;#cb11-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;matcher ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IntMap&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Rule&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb11-16&quot;&gt;&lt;a href=&quot;#cb11-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;matcher rules &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; hylo matchAlg (rules &lt;span class=&quot;op&quot;&gt;IM.!&lt;/span&gt;) &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-17&quot;&gt;&lt;a href=&quot;#cb11-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-18&quot;&gt;&lt;a href=&quot;#cb11-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;solver ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IntMap&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Rule&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-19&quot;&gt;&lt;a href=&quot;#cb11-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;solver rules &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;filter&lt;/span&gt; (&lt;span class=&quot;fu&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; matcher rules)&lt;/span&gt;
&lt;span id=&quot;cb11-20&quot;&gt;&lt;a href=&quot;#cb11-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-21&quot;&gt;&lt;a href=&quot;#cb11-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part1 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IntMap&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Rule&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-22&quot;&gt;&lt;a href=&quot;#cb11-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part1 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; solver&lt;/span&gt;
&lt;span id=&quot;cb11-23&quot;&gt;&lt;a href=&quot;#cb11-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-24&quot;&gt;&lt;a href=&quot;#cb11-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part2 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IntMap&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Rule&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-25&quot;&gt;&lt;a href=&quot;#cb11-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2 rs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; solver (extraRules &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt; rs)&lt;/span&gt;
&lt;span id=&quot;cb11-26&quot;&gt;&lt;a href=&quot;#cb11-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-27&quot;&gt;&lt;a href=&quot;#cb11-27&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;extraRules ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IntMap&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Rule&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb11-28&quot;&gt;&lt;a href=&quot;#cb11-28&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;extraRules &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; IM.fromList [&lt;/span&gt;
&lt;span id=&quot;cb11-29&quot;&gt;&lt;a href=&quot;#cb11-29&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    (&lt;span class=&quot;dv&quot;&gt;8&lt;/span&gt; , &lt;span class=&quot;dt&quot;&gt;Compound&lt;/span&gt; [[&lt;span class=&quot;dv&quot;&gt;42&lt;/span&gt;],[&lt;span class=&quot;dv&quot;&gt;42&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;8&lt;/span&gt;]])&lt;/span&gt;
&lt;span id=&quot;cb11-30&quot;&gt;&lt;a href=&quot;#cb11-30&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , (&lt;span class=&quot;dv&quot;&gt;11&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Compound&lt;/span&gt; [[&lt;span class=&quot;dv&quot;&gt;42&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;31&lt;/span&gt;],[&lt;span class=&quot;dv&quot;&gt;42&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;11&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;31&lt;/span&gt;]])&lt;/span&gt;
&lt;span id=&quot;cb11-31&quot;&gt;&lt;a href=&quot;#cb11-31&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As a nice little bonus, we can also use &lt;code&gt;generateAlg&lt;/code&gt; with a hylomorphism to also turn an &lt;code&gt;IntMap (Rule Int)&lt;/code&gt; into a list of all possible strings, which works for part 1 but would return an infinite list for part 2.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb12&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb12-1&quot;&gt;&lt;a href=&quot;#cb12-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;generateAll ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IntMap&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Rule&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb12-2&quot;&gt;&lt;a href=&quot;#cb12-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;generateAll rules &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; hylo generateAlg (rules &lt;span class=&quot;op&quot;&gt;IM.!&lt;/span&gt;) &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;day-19-benchmarks&quot;&gt;Day 19 Benchmarks&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; Day 19a
benchmarking...
time                 4.273 ms   (4.202 ms .. 4.507 ms)
                     0.990 R²   (0.965 R² .. 1.000 R²)
mean                 4.244 ms   (4.200 ms .. 4.390 ms)
std dev              220.8 μs   (54.67 μs .. 480.5 μs)
variance introduced by outliers: 30% (moderately inflated)

* parsing and formatting times excluded

&amp;gt;&amp;gt; Day 19b
benchmarking...
time                 27.13 ms   (26.34 ms .. 28.22 ms)
                     0.994 R²   (0.987 R² .. 1.000 R²)
mean                 26.20 ms   (25.94 ms .. 26.80 ms)
std dev              908.6 μs   (525.5 μs .. 1.450 ms)
variance introduced by outliers: 10% (moderately inflated)

* parsing and formatting times excluded&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md#day-19</link>
      <pubDate>Sat, 19 Dec 2020 01:00:00 EST</pubDate>
    </item>

    <item>
      <title>Day 18</title>
      <description>&lt;h2 id=&quot;day-18&quot;&gt;Day 18&lt;/h2&gt;
&lt;!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day18.md`.  If you want to edit this, edit
that file instead!
--&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://adventofcode.com/2020/day/18&quot;&gt;Prompt&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day18.hs&quot;&gt;Code&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://mstksg.github.io/advent-of-code-2020/src/AOC.Challenge.Day18.html&quot;&gt;Rendered&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day18.md&quot;&gt;Standalone Reflection Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Let’s parse with parser combinators!&lt;/p&gt;
&lt;p&gt;The main way I have learned how to deal with these binary-operation parsers is to separate out the stages into a “bottom” level containing only the leaves (here, the int literals) and parentheses, and then build up layers of precedence one-by-one from highest to lowest. For the first part we only have two layers, then, since we only have one level of precedence.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;{-# LANGUAGE OverloadedStrings #-}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;qualified&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Text.Megaparsec&lt;/span&gt;            &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;P&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;qualified&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Text.Megaparsec.Char&lt;/span&gt;       &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;P&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;qualified&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Text.Megaparsec.Char.Lexer&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;PP&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;P.Parsec&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Void&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-8&quot;&gt;&lt;a href=&quot;#cb1-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-9&quot;&gt;&lt;a href=&quot;#cb1-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;parseBottom1 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-10&quot;&gt;&lt;a href=&quot;#cb1-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;parseBottom1 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; P.choice&lt;/span&gt;
&lt;span id=&quot;cb1-11&quot;&gt;&lt;a href=&quot;#cb1-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [ PP.decimal&lt;/span&gt;
&lt;span id=&quot;cb1-12&quot;&gt;&lt;a href=&quot;#cb1-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , P.between &lt;span class=&quot;st&quot;&gt;&amp;quot;(&amp;quot;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;)&amp;quot;&lt;/span&gt; parseTop1  &lt;span class=&quot;co&quot;&gt;-- use -XOverloadedStrings to get parsers that match strings&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-13&quot;&gt;&lt;a href=&quot;#cb1-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ]&lt;/span&gt;
&lt;span id=&quot;cb1-14&quot;&gt;&lt;a href=&quot;#cb1-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-15&quot;&gt;&lt;a href=&quot;#cb1-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;parseTop1 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-16&quot;&gt;&lt;a href=&quot;#cb1-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;parseTop1 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-17&quot;&gt;&lt;a href=&quot;#cb1-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    leftOfOp &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; parseBottom1   &lt;span class=&quot;co&quot;&gt;-- parse the left hand side of a possible binary operator&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-18&quot;&gt;&lt;a href=&quot;#cb1-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    doNext acc&lt;/span&gt;
&lt;span id=&quot;cb1-19&quot;&gt;&lt;a href=&quot;#cb1-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-20&quot;&gt;&lt;a href=&quot;#cb1-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    doNext acc &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; P.choice          &lt;span class=&quot;co&quot;&gt;-- once we parse a left hand side, pick from:&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-21&quot;&gt;&lt;a href=&quot;#cb1-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      [ &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot; * &amp;quot;&lt;/span&gt;                        &lt;span class=&quot;co&quot;&gt;-- either it&amp;#39;s a *&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-22&quot;&gt;&lt;a href=&quot;#cb1-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;           rightOfOp &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; parseBottom1    &lt;span class=&quot;co&quot;&gt;--   ... so we parse the right hand side and multiply&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-23&quot;&gt;&lt;a href=&quot;#cb1-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;           doNext (acc &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt; rightOfOp)&lt;/span&gt;
&lt;span id=&quot;cb1-24&quot;&gt;&lt;a href=&quot;#cb1-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      , &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot; + &amp;quot;&lt;/span&gt;                        &lt;span class=&quot;co&quot;&gt;-- or it&amp;#39;s a +&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-25&quot;&gt;&lt;a href=&quot;#cb1-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;           rightOfOp &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; parseBottom1    &lt;span class=&quot;co&quot;&gt;--   ... so we parse the right hand side and add&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-26&quot;&gt;&lt;a href=&quot;#cb1-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;           doNext (acc &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; rightOfOp)&lt;/span&gt;
&lt;span id=&quot;cb1-27&quot;&gt;&lt;a href=&quot;#cb1-27&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      , &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; acc                        &lt;span class=&quot;co&quot;&gt;-- otherwise that was it, no operator&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-28&quot;&gt;&lt;a href=&quot;#cb1-28&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Remember that &lt;code&gt;leftOfOp&lt;/code&gt; could either come from a leaf literal number or from a parenthesized equation. In the end, we get an &lt;code&gt;Int&lt;/code&gt;, representing whatever number was on the left hand side of our operator. Then we move into &lt;code&gt;doNext&lt;/code&gt;, which continually accumulates new operations after that first &lt;code&gt;leftOfOp&lt;/code&gt; parse.&lt;/p&gt;
&lt;p&gt;If we see a &lt;code&gt;*&lt;/code&gt;, we parse the right hand side, fold that into our accumulator and repeat until we hit a dead end and yield our accumulated value; same for &lt;code&gt;+&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So there’s this sort of “cycle” that &lt;code&gt;parseTop&lt;/code&gt; defers to &lt;code&gt;parseBottom&lt;/code&gt; for its underlying things “in between” the operators, but &lt;code&gt;parseBottom&lt;/code&gt; loops back up to &lt;code&gt;parseTop&lt;/code&gt; to handle what is in the parentheses.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part1 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part1 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; P.parseMaybe &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;          &lt;span class=&quot;fu&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; P.many parseTop1&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The twist for part 2 is that now we have to have another layer of precedence, so we split things out:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;parseBottom2 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;parseBottom2 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; P.choice&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [ PP.decimal&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , P.between &lt;span class=&quot;st&quot;&gt;&amp;quot;(&amp;quot;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;)&amp;quot;&lt;/span&gt; parseTop2&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ]&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;parseMiddle2 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-8&quot;&gt;&lt;a href=&quot;#cb3-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;parseMiddle2 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-9&quot;&gt;&lt;a href=&quot;#cb3-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    leftOfOp &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; parseBottom2&lt;/span&gt;
&lt;span id=&quot;cb3-10&quot;&gt;&lt;a href=&quot;#cb3-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    doNext leftOfOp&lt;/span&gt;
&lt;span id=&quot;cb3-11&quot;&gt;&lt;a href=&quot;#cb3-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-12&quot;&gt;&lt;a href=&quot;#cb3-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    doNext acc &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; P.choice&lt;/span&gt;
&lt;span id=&quot;cb3-13&quot;&gt;&lt;a href=&quot;#cb3-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      [ &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot; + &amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-14&quot;&gt;&lt;a href=&quot;#cb3-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;           rightOfOp &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; parseBottom2&lt;/span&gt;
&lt;span id=&quot;cb3-15&quot;&gt;&lt;a href=&quot;#cb3-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;           doNext (acc &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; rightOfOp)&lt;/span&gt;
&lt;span id=&quot;cb3-16&quot;&gt;&lt;a href=&quot;#cb3-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      , &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; acc&lt;/span&gt;
&lt;span id=&quot;cb3-17&quot;&gt;&lt;a href=&quot;#cb3-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      ]&lt;/span&gt;
&lt;span id=&quot;cb3-18&quot;&gt;&lt;a href=&quot;#cb3-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-19&quot;&gt;&lt;a href=&quot;#cb3-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;parseTop2 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-20&quot;&gt;&lt;a href=&quot;#cb3-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;parseTop2 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-21&quot;&gt;&lt;a href=&quot;#cb3-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    leftOfOp &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; parseMiddle2&lt;/span&gt;
&lt;span id=&quot;cb3-22&quot;&gt;&lt;a href=&quot;#cb3-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    doNext leftOfOp&lt;/span&gt;
&lt;span id=&quot;cb3-23&quot;&gt;&lt;a href=&quot;#cb3-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-24&quot;&gt;&lt;a href=&quot;#cb3-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    doNext acc &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; P.choice&lt;/span&gt;
&lt;span id=&quot;cb3-25&quot;&gt;&lt;a href=&quot;#cb3-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      [ &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot; * &amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-26&quot;&gt;&lt;a href=&quot;#cb3-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;           rightOfOp &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; parseMiddle2&lt;/span&gt;
&lt;span id=&quot;cb3-27&quot;&gt;&lt;a href=&quot;#cb3-27&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;           doNext (acc &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt; rightOfOp)&lt;/span&gt;
&lt;span id=&quot;cb3-28&quot;&gt;&lt;a href=&quot;#cb3-28&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      , &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; acc&lt;/span&gt;
&lt;span id=&quot;cb3-29&quot;&gt;&lt;a href=&quot;#cb3-29&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So the parser dependency again is kind of interesting: &lt;code&gt;parseTop2&lt;/code&gt; is built up of chained &lt;code&gt;parseMiddle2&lt;/code&gt;s, which is built up of chained &lt;code&gt;parseBottom2&lt;/code&gt;, which could loop back up with &lt;code&gt;parseTop2&lt;/code&gt; if detect parentheses.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part2 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; P.parseMaybe &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-3&quot;&gt;&lt;a href=&quot;#cb4-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;          &lt;span class=&quot;fu&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; (parseTop2 &lt;span class=&quot;ot&quot;&gt;`P.sepBy`&lt;/span&gt; P.newline)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that this chaining and looping behavior can be abstracted out — that’s essentially what I wrote in my &lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day18.hs&quot;&gt;cleaned up solution&lt;/a&gt;. But also the &lt;em&gt;&lt;a href=&quot;https://hackage.haskell.org/package/parser-combinators-1.2.1/docs/Control-Monad-Combinators-Expr.html&quot;&gt;Control.Monad.Combinators.Expr&lt;/a&gt;&lt;/em&gt; module also abstracts over this pattern, letting you specify the “layers” you want, and it’ll generate the right parser for you with the correct weaving of dependencies like I described here. But still, I think it’s fun to see how these things end up looking like under the hood :)&lt;/p&gt;
&lt;h3 id=&quot;day-18-benchmarks&quot;&gt;Day 18 Benchmarks&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; Day 18a
benchmarking...
time                 2.824 ms   (2.691 ms .. 3.014 ms)
                     0.975 R²   (0.952 R² .. 0.998 R²)
mean                 2.748 ms   (2.703 ms .. 2.844 ms)
std dev              208.7 μs   (100.8 μs .. 383.4 μs)
variance introduced by outliers: 53% (severely inflated)

* parsing and formatting times excluded

&amp;gt;&amp;gt; Day 18b
benchmarking...
time                 2.270 ms   (2.143 ms .. 2.447 ms)
                     0.974 R²   (0.958 R² .. 0.996 R²)
mean                 2.231 ms   (2.180 ms .. 2.378 ms)
std dev              236.7 μs   (129.2 μs .. 403.0 μs)
variance introduced by outliers: 70% (severely inflated)

* parsing and formatting times excluded&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md#day-18</link>
      <pubDate>Fri, 18 Dec 2020 01:00:00 EST</pubDate>
    </item>

    <item>
      <title>Day 17</title>
      <description>&lt;h2 id=&quot;day-17&quot;&gt;Day 17&lt;/h2&gt;
&lt;!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day17.md`.  If you want to edit this, edit
that file instead!
--&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://adventofcode.com/2020/day/17&quot;&gt;Prompt&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day17.hs&quot;&gt;Code&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://mstksg.github.io/advent-of-code-2020/src/AOC.Challenge.Day17.html&quot;&gt;Rendered&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day17.md&quot;&gt;Standalone Reflection Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Neat, Game of Life! :D Actually, the 3D/4D twist does make a big impact for the best method we’d pick: we run into the &lt;a href=&quot;https://en.wikipedia.org/wiki/Curse_of_dimensionality&quot;&gt;curse of dimensionality&lt;/a&gt;. It means that when we get to 3D and 4D, our world will become vanishingly sparse. In my own input, only about 4% of the 3D space ended up being active, and 2% of my 4D space ends up being active. This means that holding a dense vector of all possible active points (which will be &lt;code&gt;(6+8+6)^n&lt;/code&gt;) is up to 98% wasteful. And because of the way this process works, we have to completely copy our entire space at every iteration.&lt;/p&gt;
&lt;p&gt;In these times, I’m happy that Haskell has a nice immutable sparse data structure like &lt;code&gt;Set&lt;/code&gt;. Sparse being beneficial in that we can easily look up and process only the 2% of active squares, and immutable being beneficial in that each step already requires a full copy in any case, so immutability doesn’t give us any drawback.&lt;/p&gt;
&lt;p&gt;First a function to get all neighbors of a point, using the &lt;code&gt;V3&lt;/code&gt; type from the &lt;em&gt;&lt;a href=&quot;https://hackage.haskell.org/package/linear&quot;&gt;linear&lt;/a&gt;&lt;/em&gt; library, which I’ve used many times already for its convenient &lt;code&gt;Num&lt;/code&gt; and &lt;code&gt;Applicative&lt;/code&gt; instances:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt;           &lt;span class=&quot;dt&quot;&gt;Data.Set&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;qualified&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Data.Set&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;S&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- from linear&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V3&lt;/span&gt; a &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V3&lt;/span&gt; a a a&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- its Applicative instance&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; x &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V3&lt;/span&gt; x x x&lt;/span&gt;
&lt;span id=&quot;cb1-8&quot;&gt;&lt;a href=&quot;#cb1-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-9&quot;&gt;&lt;a href=&quot;#cb1-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;neighbsSet ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V3&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;V3&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb1-10&quot;&gt;&lt;a href=&quot;#cb1-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;neighbsSet p &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; S.fromList&lt;/span&gt;
&lt;span id=&quot;cb1-11&quot;&gt;&lt;a href=&quot;#cb1-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [ p &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; d&lt;/span&gt;
&lt;span id=&quot;cb1-12&quot;&gt;&lt;a href=&quot;#cb1-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; d &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;sequence&lt;/span&gt; (&lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; [&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;])&lt;/span&gt;
&lt;span id=&quot;cb1-13&quot;&gt;&lt;a href=&quot;#cb1-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , d &lt;span class=&quot;op&quot;&gt;/=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-14&quot;&gt;&lt;a href=&quot;#cb1-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Just as a reminder, &lt;code&gt;pure [0,1]&lt;/code&gt; for &lt;code&gt;V3 Int&lt;/code&gt; gives us &lt;code&gt;V3 [0,1] [0,1] [0,1]&lt;/code&gt;, and if we &lt;code&gt;sequence&lt;/code&gt; that we get a cartesian N-product of all combinations &lt;code&gt;[V3 0 0, V3 0 0 1, V3 0 1 0, V3 0 1 1, V3 1 0 0, .. etc.]&lt;/code&gt;. We add each of those to &lt;code&gt;p&lt;/code&gt;, except for the one that is &lt;code&gt;V3 0 0 0&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now we can write our stepper, which takes a &lt;code&gt;Set (V3 Int)&lt;/code&gt; and returns the next &lt;code&gt;Set (V3 Int)&lt;/code&gt; after applying the rules. We can do that first by making a &lt;code&gt;Map (V3 Int) Int&lt;/code&gt;, where &lt;code&gt;Int&lt;/code&gt; is the number of neighbors at a given point. This can be done by “exploding” every &lt;code&gt;V3 Int&lt;/code&gt; in our set to a &lt;code&gt;Map (V3 Int) Int&lt;/code&gt;, a map of all its neighbors keyed to values 1, and then using &lt;code&gt;M.unionsWith (+)&lt;/code&gt; to union together all of those exploded neighbors, adding any overlapping keys.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt;           &lt;span class=&quot;dt&quot;&gt;Data.Map&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;qualified&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Data.Map&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;M&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;neighborMap ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;V3&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;V3&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;) &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;neighborMap ps &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; M.unionsWith (&lt;span class=&quot;op&quot;&gt;+&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [ M.fromSet (&lt;span class=&quot;fu&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;) (neighbsSet p)&lt;/span&gt;
&lt;span id=&quot;cb2-7&quot;&gt;&lt;a href=&quot;#cb2-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; p &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; S.toList ps&lt;/span&gt;
&lt;span id=&quot;cb2-8&quot;&gt;&lt;a href=&quot;#cb2-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now to implement the rules:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;stepper&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;V3&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;V3&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;stepper ps &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; stayAlive &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt; comeAlive&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    neighborCounts &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; neighborMap ps&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    stayAlive &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; M.keysSet &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; M.filter (\n &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; n &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;||&lt;/span&gt; n &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-8&quot;&gt;&lt;a href=&quot;#cb3-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                  neighborCounts &lt;span class=&quot;ot&quot;&gt;`M.restrictKeys`&lt;/span&gt; ps&lt;/span&gt;
&lt;span id=&quot;cb3-9&quot;&gt;&lt;a href=&quot;#cb3-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    comeAlive &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; M.keysSet &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; M.filter (&lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-10&quot;&gt;&lt;a href=&quot;#cb3-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                  neighborCounts &lt;span class=&quot;ot&quot;&gt;`M.withoutKeys`&lt;/span&gt;  ps&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;stayAlive&lt;/code&gt; is all of the &lt;code&gt;neighborCounts&lt;/code&gt; keys that correspond to already-alive points (&lt;code&gt;neighborCounts `M.restrictKeys` ps&lt;/code&gt;), but filtered to the counts that are 2 or 3. &lt;code&gt;comeAlive&lt;/code&gt; is all of the &lt;code&gt;neighborCounts&lt;/code&gt; keys that correspond to dead points (&lt;code&gt;neighborCounts `M.withoutKeys` ps&lt;/code&gt;), but filtered to only counts that are exactly 3. And our result is the set union of both of those.&lt;/p&gt;
&lt;p&gt;So our part 1 becomes:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part1 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;V3&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part1 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; S.size &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;!!&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;6&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;iterate&lt;/span&gt; stepper&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And for part 2…notice that all of our code actually never does anything &lt;em&gt;specific&lt;/em&gt; to &lt;code&gt;V3&lt;/code&gt;! In fact, if we leave the type signatures of &lt;code&gt;neighbsSet&lt;/code&gt; and &lt;code&gt;neighborMap&lt;/code&gt; and &lt;code&gt;stepper&lt;/code&gt; off, GHC will actually suggest more general type signatures for us.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;neighbsSet&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Applicative&lt;/span&gt; f, &lt;span class=&quot;dt&quot;&gt;Num&lt;/span&gt; a, &lt;span class=&quot;dt&quot;&gt;Ord&lt;/span&gt; (f a), &lt;span class=&quot;dt&quot;&gt;Traversable&lt;/span&gt; f)&lt;/span&gt;
&lt;span id=&quot;cb5-3&quot;&gt;&lt;a href=&quot;#cb5-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; f a &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; (f a)&lt;/span&gt;
&lt;span id=&quot;cb5-4&quot;&gt;&lt;a href=&quot;#cb5-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-5&quot;&gt;&lt;a href=&quot;#cb5-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;neighborMap&lt;/span&gt;
&lt;span id=&quot;cb5-6&quot;&gt;&lt;a href=&quot;#cb5-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Applicative&lt;/span&gt; f, &lt;span class=&quot;dt&quot;&gt;Num&lt;/span&gt; a, &lt;span class=&quot;dt&quot;&gt;Ord&lt;/span&gt; (f a), &lt;span class=&quot;dt&quot;&gt;Traversable&lt;/span&gt; f)&lt;/span&gt;
&lt;span id=&quot;cb5-7&quot;&gt;&lt;a href=&quot;#cb5-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; (f a)&lt;/span&gt;
&lt;span id=&quot;cb5-8&quot;&gt;&lt;a href=&quot;#cb5-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; (f a) &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-9&quot;&gt;&lt;a href=&quot;#cb5-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-10&quot;&gt;&lt;a href=&quot;#cb5-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;stepper&lt;/span&gt;
&lt;span id=&quot;cb5-11&quot;&gt;&lt;a href=&quot;#cb5-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Applicative&lt;/span&gt; f, &lt;span class=&quot;dt&quot;&gt;Num&lt;/span&gt; a, &lt;span class=&quot;dt&quot;&gt;Ord&lt;/span&gt; (f a), &lt;span class=&quot;dt&quot;&gt;Traversable&lt;/span&gt; f)&lt;/span&gt;
&lt;span id=&quot;cb5-12&quot;&gt;&lt;a href=&quot;#cb5-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; (f a)&lt;/span&gt;
&lt;span id=&quot;cb5-13&quot;&gt;&lt;a href=&quot;#cb5-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; (f a)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Neat! This means that our code &lt;em&gt;already works&lt;/em&gt; for any other fixed-sized &lt;code&gt;Vector&lt;/code&gt; type with a &lt;code&gt;Num&lt;/code&gt; instance. Like, say…&lt;code&gt;V4&lt;/code&gt;, also from &lt;em&gt;linear&lt;/em&gt;?&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb6&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb6-1&quot;&gt;&lt;a href=&quot;#cb6-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- also from the Linear library, with all the same instances&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-2&quot;&gt;&lt;a href=&quot;#cb6-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V4&lt;/span&gt; a &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V4&lt;/span&gt; a a a a&lt;/span&gt;
&lt;span id=&quot;cb6-3&quot;&gt;&lt;a href=&quot;#cb6-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-4&quot;&gt;&lt;a href=&quot;#cb6-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part1 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;V3&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-5&quot;&gt;&lt;a href=&quot;#cb6-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part1 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; S.size &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;!!&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;6&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;iterate&lt;/span&gt; stepper&lt;/span&gt;
&lt;span id=&quot;cb6-6&quot;&gt;&lt;a href=&quot;#cb6-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-7&quot;&gt;&lt;a href=&quot;#cb6-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part2 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;V4&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-8&quot;&gt;&lt;a href=&quot;#cb6-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; S.size &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;!!&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;6&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;iterate&lt;/span&gt; stepper&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And that’s it — code that should work for both parts :)&lt;/p&gt;
&lt;h3 id=&quot;day-17-benchmarks&quot;&gt;Day 17 Benchmarks&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; Day 17a
benchmarking...
time                 1.346 ms   (1.294 ms .. 1.425 ms)
                     0.983 R²   (0.965 R² .. 0.998 R²)
mean                 1.344 ms   (1.316 ms .. 1.422 ms)
std dev              134.9 μs   (64.10 μs .. 243.8 μs)
variance introduced by outliers: 71% (severely inflated)

* parsing and formatting times excluded

&amp;gt;&amp;gt; Day 17b
benchmarking...
time                 1.982 ms   (1.914 ms .. 2.100 ms)
                     0.989 R²   (0.980 R² .. 0.999 R²)
mean                 1.943 ms   (1.921 ms .. 1.995 ms)
std dev              122.6 μs   (72.82 μs .. 220.0 μs)
variance introduced by outliers: 47% (moderately inflated)

* parsing and formatting times excluded&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md#day-17</link>
      <pubDate>Thu, 17 Dec 2020 01:00:00 EST</pubDate>
    </item>

    <item>
      <title>Day 16</title>
      <description>&lt;h2 id=&quot;day-16&quot;&gt;Day 16&lt;/h2&gt;
&lt;!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day16.md`.  If you want to edit this, edit
that file instead!
--&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://adventofcode.com/2020/day/16&quot;&gt;Prompt&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day16.hs&quot;&gt;Code&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://mstksg.github.io/advent-of-code-2020/src/AOC.Challenge.Day16.html&quot;&gt;Rendered&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day16.md&quot;&gt;Standalone Reflection Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Today was a nice little self-contained constraint satisfaction problem! Well, it didn’t have to be (apparently), but it was fun as one :)&lt;/p&gt;
&lt;p&gt;First, our data type:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Info&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Info&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      {&lt;span class=&quot;ot&quot;&gt; iFields ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IntervalMap&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Text&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      ,&lt;span class=&quot;ot&quot;&gt; iYours  ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      ,&lt;span class=&quot;ot&quot;&gt; iTheirs ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here we’re using &lt;code&gt;IntervalMap&lt;/code&gt; from the &lt;em&gt;&lt;a href=&quot;https://hackage.haskell.org/package/data-interval&quot;&gt;data-interval&lt;/a&gt;&lt;/em&gt; package, which makes it easy to store data at different intervals with easy lookups. For example, if we have &lt;code&gt;[&quot;class&quot;]&lt;/code&gt; at interval &lt;code&gt;(1,5)&lt;/code&gt;, and we had &lt;code&gt;[&quot;row&quot;]&lt;/code&gt; at interval &lt;code&gt;(3,7)&lt;/code&gt;, &lt;code&gt;IntervalMap&lt;/code&gt; will merge them together (with &lt;code&gt;&amp;lt;&amp;gt;&lt;/code&gt;, if we choose) to get &lt;code&gt;[&quot;class&quot;]&lt;/code&gt; at &lt;code&gt;(1,3)&lt;/code&gt;, &lt;code&gt;[&quot;class&quot;,&quot;row&quot;]&lt;/code&gt; at &lt;code&gt;(3,5)&lt;/code&gt;, and &lt;code&gt;[&quot;row&quot;]&lt;/code&gt; at &lt;code&gt;(5,7)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If we have this &lt;code&gt;IntervalMap&lt;/code&gt;, part 1 becomes straightforward enough with the efficient &lt;code&gt;IM.notMember&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;qualified&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Data.IntervalMap.Lazy&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IM&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part1 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Info&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part1 info &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;sum&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [ n&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; ns &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; iTheirs info&lt;/span&gt;
&lt;span id=&quot;cb2-7&quot;&gt;&lt;a href=&quot;#cb2-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , n  &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; ns&lt;/span&gt;
&lt;span id=&quot;cb2-8&quot;&gt;&lt;a href=&quot;#cb2-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , n &lt;span class=&quot;ot&quot;&gt;`IM.notMember`&lt;/span&gt; iFields info&lt;/span&gt;
&lt;span id=&quot;cb2-9&quot;&gt;&lt;a href=&quot;#cb2-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So now let’s move on to the search for part 2!&lt;/p&gt;
&lt;p&gt;Our goal is to get a list &lt;code&gt;[(Int, Set Text)]&lt;/code&gt; of a column number (in the passport) with the set of all valid field names for that position. And because we are going to be doing a search, we want this list in order of smallest to largest valid-name sets.&lt;/p&gt;
&lt;p&gt;First, we can replace the &lt;code&gt;Int&lt;/code&gt;s in each passport instead with the set of fields they are valid for&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;validate ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IntervalMap&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Text&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Text&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;validate flds &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;traverse&lt;/span&gt; (&lt;span class=&quot;ot&quot;&gt;`IM.lookup`&lt;/span&gt; flds)&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;validateAll ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IntervalMap&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Text&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [[&lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Text&lt;/span&gt;]]&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;validateAll flds &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; mapMaybe (validate flds)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here &lt;code&gt;(`IM.lookup` flds)&lt;/code&gt; is &lt;code&gt;Int -&amp;gt; Set Text&lt;/code&gt;: it’ll look up the &lt;code&gt;Set Text&lt;/code&gt; corresponding to the interval that the &lt;code&gt;Int&lt;/code&gt; falls under in the &lt;code&gt;IntervalMap&lt;/code&gt;. It’ll return &lt;code&gt;Nothing&lt;/code&gt; if &lt;em&gt;any&lt;/em&gt; of the &lt;code&gt;Int&lt;/code&gt;s are invalid, and &lt;code&gt;Just&lt;/code&gt; if &lt;em&gt;all&lt;/em&gt; of the &lt;code&gt;Int&lt;/code&gt;s are valid.&lt;/p&gt;
&lt;p&gt;Next we want to build our &lt;code&gt;[(Int, Set Text)]&lt;/code&gt;. The &lt;code&gt;Set Text&lt;/code&gt; is a set of what is valid for that column number, so to get the &lt;code&gt;Set Text&lt;/code&gt; for &lt;code&gt;0&lt;/code&gt;, for instance, we need to &lt;code&gt;S.intersection&lt;/code&gt; all of the first &lt;code&gt;Set Text&lt;/code&gt;s in our list,; to get the &lt;code&gt;Set Text&lt;/code&gt; for &lt;code&gt;1&lt;/code&gt;, we need to &lt;code&gt;S.intersection&lt;/code&gt; all of the second &lt;code&gt;Set Text&lt;/code&gt;s in our lists, etc. This can be done succinctly with a &lt;code&gt;transpose&lt;/code&gt; (&lt;code&gt;transpose [[1,2,3],[4,5,6]] == [[1,4],[2,5],[3,6]]&lt;/code&gt;). Then we can use &lt;code&gt;sortOn&lt;/code&gt; to sort by the size of the valids set.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;columnSets ::&lt;/span&gt; [[&lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Text&lt;/span&gt;]] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [(&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Text&lt;/span&gt;)]&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;columnSets &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; sortOn (S.size &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;snd&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb4-3&quot;&gt;&lt;a href=&quot;#cb4-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;           &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;zip&lt;/span&gt; [&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;..&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb4-4&quot;&gt;&lt;a href=&quot;#cb4-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;           &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;map&lt;/span&gt; (foldl1&amp;#39; S.intersection)&lt;/span&gt;
&lt;span id=&quot;cb4-5&quot;&gt;&lt;a href=&quot;#cb4-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;           &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; transpose&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we’re ready for our search! We’ll be using &lt;code&gt;StateT&lt;/code&gt; over list, to get a backtracking search with backtracking state (I described this technique in &lt;a href=&quot;https://blog.jle.im/entry/unique-sample-drawing-searches-with-list-and-statet.html&quot;&gt;a constraint solving blog post&lt;/a&gt;). Our state will be the &lt;code&gt;Set Text&lt;/code&gt; of all the “committed” fields so far.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;search ::&lt;/span&gt; [(&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Text&lt;/span&gt;)] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; [(&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Text&lt;/span&gt;)]&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;search candidateMap &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; listToMaybe &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;flip&lt;/span&gt; evalStateT S.empty &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-3&quot;&gt;&lt;a href=&quot;#cb5-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    for candidates &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; \(i, cands) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;              &lt;span class=&quot;co&quot;&gt;-- for each (Int, Set Text):&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-4&quot;&gt;&lt;a href=&quot;#cb5-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      soFar &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; get                                  &lt;span class=&quot;co&quot;&gt;-- get the seen candidates&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-5&quot;&gt;&lt;a href=&quot;#cb5-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      pick  &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; lift &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; toList &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; cands &lt;span class=&quot;dt&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;\\ soFar     &lt;span class=&quot;co&quot;&gt;-- pick from the Set Text not including seens&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-6&quot;&gt;&lt;a href=&quot;#cb5-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      (i, pick) &lt;span class=&quot;op&quot;&gt;&amp;lt;$&lt;/span&gt; modify (S.insert pick)           &lt;span class=&quot;co&quot;&gt;-- propose this index/pick, inserting into seens&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And that should be it for our search! In the end this gets the first &lt;code&gt;[(Int, Text)]&lt;/code&gt; that is valid, matching a column ID to the field at that column. Our search supports backtracking through the list monad, but it should be noted that we actually don’t end up needing it for the way the puzzle input is structured. But, because we sort our lists first from smallest to largest valid-sets, our solution ends up being equivalent to the non-backtracking method and backtracking is never actually triggered.&lt;/p&gt;
&lt;p&gt;And we can wrap it all up:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb6&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb6-1&quot;&gt;&lt;a href=&quot;#cb6-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part2 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Info&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-2&quot;&gt;&lt;a href=&quot;#cb6-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;product&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-3&quot;&gt;&lt;a href=&quot;#cb6-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [ iYours info &lt;span class=&quot;op&quot;&gt;!!&lt;/span&gt; i&lt;/span&gt;
&lt;span id=&quot;cb6-4&quot;&gt;&lt;a href=&quot;#cb6-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; (i, fld) &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; res&lt;/span&gt;
&lt;span id=&quot;cb6-5&quot;&gt;&lt;a href=&quot;#cb6-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , &lt;span class=&quot;st&quot;&gt;&amp;quot;departure&amp;quot;&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;`isPrefixOf`&lt;/span&gt; fld&lt;/span&gt;
&lt;span id=&quot;cb6-6&quot;&gt;&lt;a href=&quot;#cb6-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ]&lt;/span&gt;
&lt;span id=&quot;cb6-7&quot;&gt;&lt;a href=&quot;#cb6-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-8&quot;&gt;&lt;a href=&quot;#cb6-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    cSets    &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; columnSets &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; validateAll (iFields info) (iTheirs info)&lt;/span&gt;
&lt;span id=&quot;cb6-9&quot;&gt;&lt;a href=&quot;#cb6-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; res &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; search cSets&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;day-16-benchmarks&quot;&gt;Day 16 Benchmarks&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; Day 16a
benchmarking...
time                 819.9 μs   (816.9 μs .. 823.7 μs)
                     0.999 R²   (0.999 R² .. 1.000 R²)
mean                 811.0 μs   (807.4 μs .. 819.9 μs)
std dev              16.97 μs   (9.577 μs .. 31.05 μs)
variance introduced by outliers: 11% (moderately inflated)

* parsing and formatting times excluded

&amp;gt;&amp;gt; Day 16b
benchmarking...
time                 3.517 ms   (3.485 ms .. 3.580 ms)
                     0.998 R²   (0.994 R² .. 1.000 R²)
mean                 3.508 ms   (3.493 ms .. 3.554 ms)
std dev              79.20 μs   (23.71 μs .. 158.8 μs)

* parsing and formatting times excluded&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md#day-16</link>
      <pubDate>Wed, 16 Dec 2020 01:00:00 EST</pubDate>
    </item>

    <item>
      <title>Day 15</title>
      <description>&lt;h2 id=&quot;day-15&quot;&gt;Day 15&lt;/h2&gt;
&lt;!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day15.md`.  If you want to edit this, edit
that file instead!
--&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://adventofcode.com/2020/day/15&quot;&gt;Prompt&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day15.hs&quot;&gt;Code&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://mstksg.github.io/advent-of-code-2020/src/AOC.Challenge.Day15.html&quot;&gt;Rendered&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day15.md&quot;&gt;Standalone Reflection Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So it is yet another “here’s the algorithm, implement it” days again! Only the challenge this time is…you should probably implement it to be really fast!&lt;/p&gt;
&lt;p&gt;I don’t think there is &lt;em&gt;too&lt;/em&gt; much wiggle room in how to implement things here; my original solution basically kept an &lt;code&gt;IntMap&lt;/code&gt; to the last seen time of any value, and just repeatedly looked things up and modified the (current time, last said) tuple.&lt;/p&gt;
&lt;p&gt;My original solution took around 70 seconds to run, and that was what I used to submit things originally. But let’s see if we can get it down to something a little less…perceptible :) This reflection can be a deep dive into writing tight, performant Haskell.&lt;/p&gt;
&lt;p&gt;The data type we’ll be using is an &lt;em&gt;&lt;a href=&quot;https://hackage.haskell.org/package/vector/docs/Data-Vector-Unboxed-Mutable.html&quot;&gt;unboxed mutable array&lt;/a&gt;&lt;/em&gt;. There’s a trick we can use because we have a map from integers to values, we can just use the integer keys as the index to an array. This is usually a bad idea but for the fact that the keys we’ll be using are bounded within a decently small range (we won’t ever say a number that is greater than 30 million), so we can definitely accumulate 30 million-item array into memory without any major problems. We’ll also store our last-said times as &lt;code&gt;Int32&lt;/code&gt; to be a little bit more efficient since we’re trying to eek out every last bit of perf.&lt;/p&gt;
&lt;p&gt;So overall we still keep some state: the current time and the last said item. Since those are just integers, we can keep that as pure in memory using &lt;code&gt;StateT&lt;/code&gt; running over &lt;code&gt;ST s&lt;/code&gt; (the mutable state monad, where our mutable vectors will live).&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt;           &lt;span class=&quot;dt&quot;&gt;Control.Monad.ST&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt;           &lt;span class=&quot;dt&quot;&gt;Control.Monad.State&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt;           &lt;span class=&quot;dt&quot;&gt;GHC.Int&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Int32&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;qualified&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Data.Vector.Unboxed.Mutable&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;MV&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;LoopState&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;LS&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    {&lt;span class=&quot;ot&quot;&gt; lsLastSaid ::&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-8&quot;&gt;&lt;a href=&quot;#cb1-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; lsCurrTime ::&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;Int32&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-9&quot;&gt;&lt;a href=&quot;#cb1-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    }&lt;/span&gt;
&lt;span id=&quot;cb1-10&quot;&gt;&lt;a href=&quot;#cb1-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-11&quot;&gt;&lt;a href=&quot;#cb1-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;sayNext&lt;/span&gt;
&lt;span id=&quot;cb1-12&quot;&gt;&lt;a href=&quot;#cb1-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;MV.MVector&lt;/span&gt; s &lt;span class=&quot;dt&quot;&gt;Int32&lt;/span&gt;                   &lt;span class=&quot;co&quot;&gt;-- ^ the mutable vector of last-seen times&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-13&quot;&gt;&lt;a href=&quot;#cb1-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;StateT&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;T2&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int32&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;) (&lt;span class=&quot;dt&quot;&gt;ST&lt;/span&gt; s) ()      &lt;span class=&quot;co&quot;&gt;-- ^ an &amp;#39;ST s&amp;#39; action with some pure (T2 Int32 Int) state&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-14&quot;&gt;&lt;a href=&quot;#cb1-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;sayNext v &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-15&quot;&gt;&lt;a href=&quot;#cb1-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;L&lt;/span&gt; s i &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; get                        &lt;span class=&quot;co&quot;&gt;-- get the current pure state&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-16&quot;&gt;&lt;a href=&quot;#cb1-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    lst &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; MV.read v x                  &lt;span class=&quot;co&quot;&gt;-- our last said is x, so look up the last time we saw it&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-17&quot;&gt;&lt;a href=&quot;#cb1-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    MV.write v x i                      &lt;span class=&quot;co&quot;&gt;-- update the last-time-seen&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-18&quot;&gt;&lt;a href=&quot;#cb1-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; j &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; lst &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;  &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;               &lt;span class=&quot;co&quot;&gt;-- we haven&amp;#39;t seen it&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-19&quot;&gt;&lt;a href=&quot;#cb1-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;          &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;otherwise&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; i &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt; lst         &lt;span class=&quot;co&quot;&gt;-- we have seen it&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-20&quot;&gt;&lt;a href=&quot;#cb1-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    put (&lt;span class=&quot;dt&quot;&gt;LS&lt;/span&gt; (&lt;span class=&quot;fu&quot;&gt;fromIntegral&lt;/span&gt; j) (i &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;))   &lt;span class=&quot;co&quot;&gt;-- update last seen and current time&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-21&quot;&gt;&lt;a href=&quot;#cb1-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;{-# INLINE sayNext #-}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We will want to INLINE this so that it gets inlined directly into our main loop code.&lt;/p&gt;
&lt;p&gt;Oh, let’s also write a function to initialize our sequence with starting inputs:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;saySomething&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;MV.MVector&lt;/span&gt; s &lt;span class=&quot;dt&quot;&gt;Int32&lt;/span&gt;                   &lt;span class=&quot;co&quot;&gt;-- ^ the mutable vector of last-seen times&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;                                  &lt;span class=&quot;co&quot;&gt;-- ^ a number to &amp;quot;say&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;StateT&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;T2&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int32&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;) (&lt;span class=&quot;dt&quot;&gt;ST&lt;/span&gt; s) ()      &lt;span class=&quot;co&quot;&gt;-- ^ an &amp;#39;ST s&amp;#39; action with some pure (T2 Int32 Int) state&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;saySomething v y &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;LS&lt;/span&gt; x i &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; get&lt;/span&gt;
&lt;span id=&quot;cb2-7&quot;&gt;&lt;a href=&quot;#cb2-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    MV.unsafeWrite v x i          &lt;span class=&quot;co&quot;&gt;-- write the last seen number with the right time&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-8&quot;&gt;&lt;a href=&quot;#cb2-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    put (&lt;span class=&quot;dt&quot;&gt;LS&lt;/span&gt; y (i &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;))            &lt;span class=&quot;co&quot;&gt;-- queue up the write of the number to say&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-9&quot;&gt;&lt;a href=&quot;#cb2-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;{-# INLINE saySomething #-}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And now we’re good to go to put it all together! We can use &lt;code&gt;whileM_&lt;/code&gt; from &lt;em&gt;&lt;a href=&quot;https://hackage.haskell.org/package/monad-loops/docs/Control-Monad-Loops.html&quot;&gt;Control.Monad.Loops&lt;/a&gt;&lt;/em&gt; to emulate a while loop, where our condition is whenever &lt;code&gt;lsCurrTime&lt;/code&gt; reaches the maximum value.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | Returns &amp;#39;True&amp;#39; until we need to stop&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;stopCond ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int32&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;StateT&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;T2&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int32&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;) m &lt;span class=&quot;dt&quot;&gt;Bool&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;stopCond n &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; gets &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; \(&lt;span class=&quot;dt&quot;&gt;LS&lt;/span&gt; _ i) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; i &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt; n&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;{-# INLINE stopCond #-}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- gets f = f &amp;lt;$&amp;gt; get, it maps a function on top of a get&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;looper ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-8&quot;&gt;&lt;a href=&quot;#cb3-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;looper n xs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; runST &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;flip&lt;/span&gt; evalStateT (&lt;span class=&quot;dt&quot;&gt;LS&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-9&quot;&gt;&lt;a href=&quot;#cb3-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    v &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; MV.replicate n &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;       &lt;span class=&quot;co&quot;&gt;-- initialize our vector with zeros&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-10&quot;&gt;&lt;a href=&quot;#cb3-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    traverse_ (saySomething v) xs&lt;/span&gt;
&lt;span id=&quot;cb3-11&quot;&gt;&lt;a href=&quot;#cb3-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    whileM_ (stopCond n) (sayNext v)&lt;/span&gt;
&lt;span id=&quot;cb3-12&quot;&gt;&lt;a href=&quot;#cb3-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    gets lsLastSaid&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;On my machine (with some minor optimizations, like using &lt;code&gt;unsafeRead&lt;/code&gt;/&lt;code&gt;unsafeWrite&lt;/code&gt;), this runs in 230ms for part 2…a much more reasonable improvement over my original 70 seconds! :)&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part1 ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part1 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; looper &lt;span class=&quot;dv&quot;&gt;2020&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-3&quot;&gt;&lt;a href=&quot;#cb4-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-4&quot;&gt;&lt;a href=&quot;#cb4-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part2 ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-5&quot;&gt;&lt;a href=&quot;#cb4-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; looper &lt;span class=&quot;dv&quot;&gt;30000000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;day-15-benchmarks&quot;&gt;Day 15 Benchmarks&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; Day 15a
benchmarking...
time                 2.523 μs   (2.390 μs .. 2.614 μs)
                     0.986 R²   (0.986 R² .. 0.989 R²)
mean                 2.320 μs   (2.266 μs .. 2.409 μs)
std dev              203.6 ns   (138.6 ns .. 256.9 ns)
variance introduced by outliers: 85% (severely inflated)

* parsing and formatting times excluded

&amp;gt;&amp;gt; Day 15b
benchmarking...
time                 291.7 ms   (281.8 ms .. 304.4 ms)
                     0.999 R²   (0.999 R² .. 1.000 R²)
mean                 302.0 ms   (296.4 ms .. 312.7 ms)
std dev              9.904 ms   (3.637 ms .. 13.04 ms)
variance introduced by outliers: 16% (moderately inflated)

* parsing and formatting times excluded&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md#day-15</link>
      <pubDate>Tue, 15 Dec 2020 01:00:00 EST</pubDate>
    </item>

    <item>
      <title>Day 14</title>
      <description>&lt;h2 id=&quot;day-14&quot;&gt;Day 14&lt;/h2&gt;
&lt;!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day14.md`.  If you want to edit this, edit
that file instead!
--&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://adventofcode.com/2020/day/14&quot;&gt;Prompt&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day14.hs&quot;&gt;Code&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://mstksg.github.io/advent-of-code-2020/src/AOC.Challenge.Day14.html&quot;&gt;Rendered&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day14.md&quot;&gt;Standalone Reflection Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I guess today is a “here’s the algorithm, now implement it” puzzle, to contrast/take a break from yesterday’s “here’s the goal, figure out the algorithm” :)&lt;/p&gt;
&lt;p&gt;First, let’s start with an intermediate data type representing the actions possible on each line:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Instr&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;dt&quot;&gt;Mask&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Bool&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Write&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The mask will be a list of &lt;code&gt;Maybe Bool&lt;/code&gt;, where &lt;code&gt;X&lt;/code&gt; is &lt;code&gt;Nothing&lt;/code&gt;, &lt;code&gt;0&lt;/code&gt; is &lt;code&gt;Just False&lt;/code&gt;, and &lt;code&gt;1&lt;/code&gt; is &lt;code&gt;Just True&lt;/code&gt;. However, it’s important to reverse the string when parsing it from the input, because we want index &lt;code&gt;0&lt;/code&gt; to correspond to bit &lt;code&gt;0&lt;/code&gt;, index &lt;code&gt;1&lt;/code&gt; to correspond to bit &lt;code&gt;1&lt;/code&gt;, etc., to make our lives easier.&lt;/p&gt;
&lt;p&gt;That’s because we can implement the application of a mask (for part 1) using &lt;a href=&quot;https://hackage.haskell.org/package/lens-4.19.2/docs/Control-Lens-Indexed.html#v:ifoldl-39-&quot;&gt;&lt;code&gt;ifoldl&#39;&lt;/code&gt;&lt;/a&gt;, a version of &lt;code&gt;foldl&#39;&lt;/code&gt; that gives you an item’s index as you are folding it:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt;           &lt;span class=&quot;dt&quot;&gt;Data.Bits&lt;/span&gt; (clearBit, setBit)&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt;           &lt;span class=&quot;dt&quot;&gt;Control.Lens.Indexed&lt;/span&gt; (ifoldl&amp;#39;)&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;applyMask1 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Bool&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;applyMask1 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; ifoldl&amp;#39; &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; \i x &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; x&lt;/span&gt;
&lt;span id=&quot;cb2-7&quot;&gt;&lt;a href=&quot;#cb2-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;False&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; clearBit x i&lt;/span&gt;
&lt;span id=&quot;cb2-8&quot;&gt;&lt;a href=&quot;#cb2-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;True&lt;/span&gt;  &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; setBit   x i&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If the bit list contains a &lt;code&gt;Nothing&lt;/code&gt; in a given index, leave the item unchanged. If it contains a &lt;code&gt;Just False&lt;/code&gt;, clear that index’s bit (set it to zero). If it contains a &lt;code&gt;Just Nothing&lt;/code&gt;, set that index’s bit (set it to one).&lt;/p&gt;
&lt;p&gt;And that leaves part 1 as a foldl through all the instructions, keeping the current map and mask as state:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt;           &lt;span class=&quot;dt&quot;&gt;Data.IntMap&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;IntMap&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;qualified&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Data.IntMap&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IM&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part1 ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Instr&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;IntMap&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;, [&lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Bool&lt;/span&gt;])&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part1 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; foldl&amp;#39; go (IM.empty, [])&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    go ::&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;IntMap&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;, [&lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Bool&lt;/span&gt;]) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Instr&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;IntMap&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;, [&lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Bool&lt;/span&gt;])&lt;/span&gt;
&lt;span id=&quot;cb3-8&quot;&gt;&lt;a href=&quot;#cb3-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    go (&lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;mp, &lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;msk) &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-9&quot;&gt;&lt;a href=&quot;#cb3-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;dt&quot;&gt;Mask&lt;/span&gt;  msk&amp;#39;   &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (mp, msk&amp;#39;)&lt;/span&gt;
&lt;span id=&quot;cb3-10&quot;&gt;&lt;a href=&quot;#cb3-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;dt&quot;&gt;Write&lt;/span&gt; addr n &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-11&quot;&gt;&lt;a href=&quot;#cb3-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; mp&amp;#39; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; IM.insert addr (applyMask1 n msk) mp&lt;/span&gt;
&lt;span id=&quot;cb3-12&quot;&gt;&lt;a href=&quot;#cb3-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;in&lt;/span&gt;  (mp&amp;#39;, msk)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Part 2’s mask application is interesting, because it lives in “non-determinancy”. Basically, each bit mask bit application could potentially yield multiple possibilities. We have to accumulate every nested possibility. This feature is given to us by list’s &lt;code&gt;Monad&lt;/code&gt; instance, so we can swap &lt;code&gt;ifoldl&#39;&lt;/code&gt; for &lt;a href=&quot;https://hackage.haskell.org/package/lens-4.19.2/docs/Control-Lens-Indexed.html#v:ifoldlM&quot;&gt;&lt;code&gt;ifoldM&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;ifoldl&amp;#39; ::&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; b &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; a &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt;   b) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; b &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [a] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt;   b&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;ifoldlM ::&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; b &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; a &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; m b) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; b &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [a] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; m b&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For &lt;code&gt;ifoldlM&lt;/code&gt;, each result lives in monad &lt;code&gt;m&lt;/code&gt;, so the semantics of “proceeding along the fold” are deferred to the &lt;code&gt;Monad&lt;/code&gt; instance for &lt;code&gt;m&lt;/code&gt;. If &lt;code&gt;m&lt;/code&gt; is &lt;code&gt;Maybe&lt;/code&gt;, it means that you only proceed if you get a &lt;code&gt;Just&lt;/code&gt;, or else short-circuit with &lt;code&gt;Nothing&lt;/code&gt;. If &lt;code&gt;m&lt;/code&gt; is &lt;code&gt;IO&lt;/code&gt;, it means that proceeding involves chaining the IO action’s execution and binding the result to give it to the function’s next iteration. If &lt;code&gt;m&lt;/code&gt; is &lt;code&gt;[]&lt;/code&gt; (list), it means that subsequent chaining will run the function on every &lt;em&gt;possibility&lt;/em&gt; returned by the function’s previous call, accumulating every possible way of choosing every possible choice. (I talked about this in more depth in &lt;a href=&quot;https://blog.jle.im/entries/series/+monadplus-success-failure-monads.html&quot;&gt;one of my first ever Haskell blog posts&lt;/a&gt;).&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt;           &lt;span class=&quot;dt&quot;&gt;Control.Lens.Indexed&lt;/span&gt; (ifoldlM)&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-3&quot;&gt;&lt;a href=&quot;#cb5-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;applyMask2 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Bool&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb5-4&quot;&gt;&lt;a href=&quot;#cb5-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;applyMask2 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; ifoldlM &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; \i x &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-5&quot;&gt;&lt;a href=&quot;#cb5-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [clearBit x i, setBit x i]&lt;/span&gt;
&lt;span id=&quot;cb5-6&quot;&gt;&lt;a href=&quot;#cb5-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;False&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [x]&lt;/span&gt;
&lt;span id=&quot;cb5-7&quot;&gt;&lt;a href=&quot;#cb5-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;True&lt;/span&gt;  &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [setBit x i]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For these, we return a list of every possible change from a given bit mask bit. For the &lt;code&gt;Nothing&lt;/code&gt; “floating” case, there are two possibilities; for the other two, there is only one. We trust list’s &lt;code&gt;Monad&lt;/code&gt; instance to properly thread over all possible results into a list of all possible changes that that &lt;code&gt;Int&lt;/code&gt; could have been subjected to.&lt;/p&gt;
&lt;p&gt;And so, part 2 looks a lot like part 1!&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb6&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb6-1&quot;&gt;&lt;a href=&quot;#cb6-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part2 ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Instr&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;IntMap&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;, [&lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Bool&lt;/span&gt;])&lt;/span&gt;
&lt;span id=&quot;cb6-2&quot;&gt;&lt;a href=&quot;#cb6-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; foldl&amp;#39; go (IM.empty, [])&lt;/span&gt;
&lt;span id=&quot;cb6-3&quot;&gt;&lt;a href=&quot;#cb6-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-4&quot;&gt;&lt;a href=&quot;#cb6-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    go ::&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;IntMap&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;, [&lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Bool&lt;/span&gt;]) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Instr&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;IntMap&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;, [&lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Bool&lt;/span&gt;])&lt;/span&gt;
&lt;span id=&quot;cb6-5&quot;&gt;&lt;a href=&quot;#cb6-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    go (&lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;mp, &lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;msk) &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-6&quot;&gt;&lt;a href=&quot;#cb6-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;dt&quot;&gt;Mask&lt;/span&gt;  msk&amp;#39;   &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (mp, msk&amp;#39;)&lt;/span&gt;
&lt;span id=&quot;cb6-7&quot;&gt;&lt;a href=&quot;#cb6-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;dt&quot;&gt;Write&lt;/span&gt; addr n &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-8&quot;&gt;&lt;a href=&quot;#cb6-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; newMp &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; IM.fromList ((,n) &lt;span class=&quot;op&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; applyMask2 addr msk)&lt;/span&gt;
&lt;span id=&quot;cb6-9&quot;&gt;&lt;a href=&quot;#cb6-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;in&lt;/span&gt;  (newMp &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt; mp, msk)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;(&amp;lt;&amp;gt;)&lt;/code&gt; here is a left-biased merger, so it merges in all of the newly seen indices into the existing ones.&lt;/p&gt;
&lt;h3 id=&quot;day-14-benchmarks&quot;&gt;Day 14 Benchmarks&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; Day 14a
benchmarking...
time                 158.7 μs   (158.0 μs .. 159.4 μs)
                     0.999 R²   (0.997 R² .. 1.000 R²)
mean                 157.9 μs   (157.6 μs .. 158.6 μs)
std dev              1.293 μs   (845.8 ns .. 2.372 μs)

* parsing and formatting times excluded

&amp;gt;&amp;gt; Day 14b
benchmarking...
time                 25.76 ms   (24.66 ms .. 27.04 ms)
                     0.990 R²   (0.979 R² .. 0.998 R²)
mean                 25.49 ms   (25.02 ms .. 26.27 ms)
std dev              1.358 ms   (982.2 μs .. 1.914 ms)
variance introduced by outliers: 20% (moderately inflated)

* parsing and formatting times excluded&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md#day-14</link>
      <pubDate>Mon, 14 Dec 2020 01:00:00 EST</pubDate>
    </item>

    <item>
      <title>Day 13</title>
      <description>&lt;h2 id=&quot;day-13&quot;&gt;Day 13&lt;/h2&gt;
&lt;!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day13.md`.  If you want to edit this, edit
that file instead!
--&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://adventofcode.com/2020/day/13&quot;&gt;Prompt&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day13.hs&quot;&gt;Code&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://mstksg.github.io/advent-of-code-2020/src/AOC.Challenge.Day13.html&quot;&gt;Rendered&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day13.md&quot;&gt;Standalone Reflection Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Aw man, I feel like I would have leaderboarded today had I not been busy :’( These type of number theory problems are the ones I usually do well on.&lt;/p&gt;
&lt;p&gt;Oh well! Silly internet points, right?&lt;/p&gt;
&lt;p&gt;For part 1, you just need to minimize a function on each bus ID:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part1 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part1 t0 xs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; minimumBy (comparing &lt;span class=&quot;fu&quot;&gt;snd&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [ (x, waitTime)&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; x &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; xs&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; waitTime &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; x &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt; (t0 &lt;span class=&quot;ot&quot;&gt;`mod`&lt;/span&gt; x)&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Part 2 is where things get interesting! Let’s try to think of things inductively: start with small lists, and see how we would “add one more”.&lt;/p&gt;
&lt;p&gt;Let’s say we had &lt;code&gt;(offset, id)&lt;/code&gt; pairs &lt;code&gt;(0,7)&lt;/code&gt; and &lt;code&gt;(1,13)&lt;/code&gt;, like in the example. This means that we want to find times where &lt;code&gt;t `mod` 7 == 0&lt;/code&gt; and &lt;code&gt;(t + 1) `mod` 13 == 0&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can sort of do a manual search by hand to get &lt;code&gt;14&lt;/code&gt; as our lowest candidate. But also, note that &lt;code&gt;14 + (7*13)n&lt;/code&gt; for any integer &lt;code&gt;n&lt;/code&gt; would preserve the offset property. &lt;code&gt;14&lt;/code&gt;, &lt;code&gt;14 + 91&lt;/code&gt;, &lt;code&gt;14 + 182&lt;/code&gt;, etc. So the family of all “valid” numbers are &lt;code&gt;14 + (7*13)n&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Next, what if we wanted to find the situation for pairs &lt;code&gt;(0,7)&lt;/code&gt;, &lt;code&gt;(1,13)&lt;/code&gt;, and &lt;code&gt;(4,15)&lt;/code&gt;? Well, we already know that any solution that includes &lt;code&gt;(0,7)&lt;/code&gt; and &lt;code&gt;(1,13)&lt;/code&gt; will be of the form &lt;code&gt;14 + (7*13)n&lt;/code&gt;. So now we just need to find the &lt;em&gt;first&lt;/em&gt; one of those that also matches &lt;code&gt;(4,15)&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- &amp;#39;until&amp;#39; repeatedly applies a function until it finds a value that matches a&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- predicate&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;ghci&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;until&lt;/span&gt; (\t &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (t &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;4&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;`mod`&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;15&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;) (&lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; (&lt;span class=&quot;dv&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;13&lt;/span&gt;)) &lt;span class=&quot;dv&quot;&gt;14&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dv&quot;&gt;1106&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ah hah, good ol’ &lt;code&gt;1106&lt;/code&gt;. Well, &lt;code&gt;1106&lt;/code&gt; isn’t the only number that works. We can see that &lt;code&gt;1106 + (7*13*15)n&lt;/code&gt; for any integer n would &lt;em&gt;also&lt;/em&gt; work, since it preserves that mod property.&lt;/p&gt;
&lt;p&gt;And so, we can repeat this process over and over again for each new number we see.&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Keep track of the current “lowest match” (&lt;code&gt;14&lt;/code&gt;) and the current “search step” (&lt;code&gt;7*13&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;When you see a number, search that family until you find a new lowest match that includes the new number.&lt;/li&gt;
&lt;li&gt;Use that new number as the next lowest match, and multiply it to get the new search step.&lt;/li&gt;
&lt;li&gt;Rinse and repeat.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Overall, this works pretty well as a &lt;code&gt;foldl&lt;/code&gt;, where we keep this &lt;code&gt;(lowest match, search step)&lt;/code&gt; pair as an accumulator, and update it as we see each new value in our list.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part2 ::&lt;/span&gt; [(&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;)] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;fst&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; foldl&amp;#39; go (&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    go (&lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;base, &lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;step) (offset, i) &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; (base&amp;#39;, step &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt; i)&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        base&amp;#39; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;until&lt;/span&gt; (\n &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (n &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; offset) &lt;span class=&quot;ot&quot;&gt;`mod`&lt;/span&gt; i &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                      (&lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; step)&lt;/span&gt;
&lt;span id=&quot;cb3-8&quot;&gt;&lt;a href=&quot;#cb3-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                      base&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;day-13-benchmarks&quot;&gt;Day 13 Benchmarks&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; Day 13a
benchmarking...
time                 189.4 ns   (184.7 ns .. 198.3 ns)
                     0.992 R²   (0.985 R² .. 1.000 R²)
mean                 189.8 ns   (186.2 ns .. 199.6 ns)
std dev              19.00 ns   (7.817 ns .. 34.74 ns)
variance introduced by outliers: 90% (severely inflated)

* parsing and formatting times excluded

&amp;gt;&amp;gt; Day 13b
benchmarking...
time                 3.868 μs   (3.865 μs .. 3.872 μs)
                     1.000 R²   (1.000 R² .. 1.000 R²)
mean                 3.868 μs   (3.865 μs .. 3.876 μs)
std dev              14.47 ns   (9.762 ns .. 24.35 ns)

* parsing and formatting times excluded&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md#day-13</link>
      <pubDate>Sun, 13 Dec 2020 01:00:00 EST</pubDate>
    </item>

    <item>
      <title>Day 12</title>
      <description>&lt;h2 id=&quot;day-12&quot;&gt;Day 12&lt;/h2&gt;
&lt;!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day12.md`.  If you want to edit this, edit
that file instead!
--&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://adventofcode.com/2020/day/12&quot;&gt;Prompt&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day12.hs&quot;&gt;Code&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://mstksg.github.io/advent-of-code-2020/src/AOC.Challenge.Day12.html&quot;&gt;Rendered&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day12.md&quot;&gt;Standalone Reflection Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Hello! Today’s puzzle for me ended up a neat exercise in fitting together simple parts into something fun.&lt;/p&gt;
&lt;p&gt;To preface this, I do usually represent all my coordinates using &lt;code&gt;V2 Int&lt;/code&gt; from the &lt;em&gt;&lt;a href=&quot;https://hackage.haskell.org/package/linear&quot;&gt;linear&lt;/a&gt;&lt;/em&gt; library, which supports addition and scaling:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; a &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;a &lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;a&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | You can add points using the Num instance&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;(+) ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-8&quot;&gt;&lt;a href=&quot;#cb1-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | You can do scaling&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-9&quot;&gt;&lt;a href=&quot;#cb1-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;(*^) ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And I have a utility type that represents a compass direction:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Dir&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;North&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;East&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;South&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;West&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;dirPoint ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Dir&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;dirPoint &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;North&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt;   &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;   &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;East&lt;/span&gt;  &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt;   &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;   &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-7&quot;&gt;&lt;a href=&quot;#cb2-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;South&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt;   &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb2-8&quot;&gt;&lt;a href=&quot;#cb2-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;West&lt;/span&gt;  &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;)  &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-9&quot;&gt;&lt;a href=&quot;#cb2-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-10&quot;&gt;&lt;a href=&quot;#cb2-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;rotPoint ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Num&lt;/span&gt; a &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Dir&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; a &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; a&lt;/span&gt;
&lt;span id=&quot;cb2-11&quot;&gt;&lt;a href=&quot;#cb2-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;rotPoint &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-12&quot;&gt;&lt;a href=&quot;#cb2-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;North&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;id&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-13&quot;&gt;&lt;a href=&quot;#cb2-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;East&lt;/span&gt;  &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; \(&lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; x y) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt;   y  (&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;x)&lt;/span&gt;
&lt;span id=&quot;cb2-14&quot;&gt;&lt;a href=&quot;#cb2-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;West&lt;/span&gt;  &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; \(&lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; x y) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;y)   x&lt;/span&gt;
&lt;span id=&quot;cb2-15&quot;&gt;&lt;a href=&quot;#cb2-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;South&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;negate&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And I do like to define a &lt;code&gt;Group&lt;/code&gt; interface for my &lt;code&gt;Dir&lt;/code&gt; type, just for fun.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | If you consider a Dir as a turn, then `mulDir a b` is like turning a, then&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- turning b.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;mulDir ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Dir&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Dir&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Dir&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;mulDir &lt;span class=&quot;dt&quot;&gt;North&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;id&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;mulDir &lt;span class=&quot;dt&quot;&gt;East&lt;/span&gt;  &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;North&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;East&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                     &lt;span class=&quot;dt&quot;&gt;East&lt;/span&gt;  &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;South&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                     &lt;span class=&quot;dt&quot;&gt;South&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;West&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-8&quot;&gt;&lt;a href=&quot;#cb3-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                     &lt;span class=&quot;dt&quot;&gt;West&lt;/span&gt;  &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;North&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-9&quot;&gt;&lt;a href=&quot;#cb3-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;mulDir &lt;span class=&quot;dt&quot;&gt;South&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;North&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;South&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-10&quot;&gt;&lt;a href=&quot;#cb3-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                     &lt;span class=&quot;dt&quot;&gt;East&lt;/span&gt;  &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;West&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-11&quot;&gt;&lt;a href=&quot;#cb3-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                     &lt;span class=&quot;dt&quot;&gt;South&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;North&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-12&quot;&gt;&lt;a href=&quot;#cb3-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                     &lt;span class=&quot;dt&quot;&gt;West&lt;/span&gt;  &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;East&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-13&quot;&gt;&lt;a href=&quot;#cb3-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;mulDir &lt;span class=&quot;dt&quot;&gt;West&lt;/span&gt;  &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;North&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;West&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-14&quot;&gt;&lt;a href=&quot;#cb3-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                     &lt;span class=&quot;dt&quot;&gt;East&lt;/span&gt;  &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;North&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-15&quot;&gt;&lt;a href=&quot;#cb3-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                     &lt;span class=&quot;dt&quot;&gt;South&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;East&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-16&quot;&gt;&lt;a href=&quot;#cb3-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                     &lt;span class=&quot;dt&quot;&gt;West&lt;/span&gt;  &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;South&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-17&quot;&gt;&lt;a href=&quot;#cb3-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-18&quot;&gt;&lt;a href=&quot;#cb3-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | &amp;#39;&amp;lt;&amp;gt;&amp;#39; is &amp;#39;mulDir&amp;#39;.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-19&quot;&gt;&lt;a href=&quot;#cb3-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Semigroup&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Dir&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-20&quot;&gt;&lt;a href=&quot;#cb3-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    (&lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; mulDir&lt;/span&gt;
&lt;span id=&quot;cb3-21&quot;&gt;&lt;a href=&quot;#cb3-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-22&quot;&gt;&lt;a href=&quot;#cb3-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | If you consider Dir as a turn, then turning by North is the same as not&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-23&quot;&gt;&lt;a href=&quot;#cb3-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- turning at all.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-24&quot;&gt;&lt;a href=&quot;#cb3-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Monoid&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Dir&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-25&quot;&gt;&lt;a href=&quot;#cb3-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;fu&quot;&gt;mempty&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;North&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-26&quot;&gt;&lt;a href=&quot;#cb3-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-27&quot;&gt;&lt;a href=&quot;#cb3-27&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | Reverse a turn.  Not needed for this puzzle, but still useful in general.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-28&quot;&gt;&lt;a href=&quot;#cb3-28&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Group&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Dir&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-29&quot;&gt;&lt;a href=&quot;#cb3-29&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    invert &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;North&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;South&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-30&quot;&gt;&lt;a href=&quot;#cb3-30&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                   &lt;span class=&quot;dt&quot;&gt;East&lt;/span&gt;  &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;West&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-31&quot;&gt;&lt;a href=&quot;#cb3-31&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                   &lt;span class=&quot;dt&quot;&gt;South&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;North&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-32&quot;&gt;&lt;a href=&quot;#cb3-32&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                   &lt;span class=&quot;dt&quot;&gt;West&lt;/span&gt;  &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;East&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I did not write any of this for the puzzle — this is just a nice way I like to think about directions and points in my head :)&lt;/p&gt;
&lt;p&gt;One major advantage of defining a &lt;code&gt;Semigroup&lt;/code&gt; instance for &lt;code&gt;Dir&lt;/code&gt; is that you can take advantage of the &lt;code&gt;pow&lt;/code&gt; function from &lt;a href=&quot;https://hackage.haskell.org/package/groups-0.5.2/docs/Data-Group.html&quot;&gt;Data.Group&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;pow ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Group&lt;/span&gt; m &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; m &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; m&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;which is like &lt;code&gt;stimes&lt;/code&gt;, but supporting negative numbers. &lt;code&gt;pow x 3&lt;/code&gt; is &lt;code&gt;x &amp;lt;&amp;gt; x &amp;lt;&amp;gt; x&lt;/code&gt;, and &lt;code&gt;pow x (-3)&lt;/code&gt; is &lt;code&gt;invert x &amp;lt;&amp;gt; invert x &amp;lt;&amp;gt; invert x&lt;/code&gt;, or &lt;code&gt;invert (x &amp;lt;&amp;gt; x &amp;lt;&amp;gt; x)&lt;/code&gt; (same thing, ’cause Group theory). We don’t actually need the support for negative numbers in this puzzle, so we could just use &lt;code&gt;stimes&lt;/code&gt;, but it’s nice that we can just use &lt;code&gt;pow&lt;/code&gt; and not think about our input range. And, though it doesn’t matter for this challenge, it also uses &lt;a href=&quot;https://en.wikipedia.org/wiki/Exponentiation_by_squaring&quot;&gt;repeated squaring&lt;/a&gt; so it can do these operations in log-n time (&lt;code&gt;pow x 1000000000&lt;/code&gt; only takes 30 operations), which is pretty neat for a lot of different applications (like &lt;a href=&quot;https://blog.jle.im/entry/shuffling-things-up.html&quot;&gt;in my writeup for 2019 Day 22&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Anyway I think that’s enough preamble…now let’s use it! :D Each instruction seems to be one of three forms: “go forward”, “turn”, or “move an absolute vector”. So I represented these three as a data type, parameterized by the amount to go forward, the direction to turn, and the vector to move by, respectively.&lt;/p&gt;
&lt;p&gt;And each first character gives us a different way to process the &lt;code&gt;Int&lt;/code&gt; argument, so I stored those instructions in a &lt;code&gt;Map&lt;/code&gt;. Then we can parse it by just using &lt;code&gt;readMaybe :: Read a =&amp;gt; String -&amp;gt; Maybe a&lt;/code&gt; on a pattern match.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Instr&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Forward&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;           &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Turn&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Dir&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-3&quot;&gt;&lt;a href=&quot;#cb5-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;           &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Move&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-4&quot;&gt;&lt;a href=&quot;#cb5-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Show&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-5&quot;&gt;&lt;a href=&quot;#cb5-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-6&quot;&gt;&lt;a href=&quot;#cb5-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | A map of a Char to the way to interpret the Int argument&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-7&quot;&gt;&lt;a href=&quot;#cb5-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;mkInstr ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Char&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Instr&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb5-8&quot;&gt;&lt;a href=&quot;#cb5-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;mkInstr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; M.fromList&lt;/span&gt;
&lt;span id=&quot;cb5-9&quot;&gt;&lt;a href=&quot;#cb5-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [ (&lt;span class=&quot;ch&quot;&gt;&amp;#39;F&amp;#39;&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Forward&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb5-10&quot;&gt;&lt;a href=&quot;#cb5-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , (&lt;span class=&quot;ch&quot;&gt;&amp;#39;L&amp;#39;&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Turn&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; pow &lt;span class=&quot;dt&quot;&gt;West&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; (&lt;span class=&quot;ot&quot;&gt;`div`&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;90&lt;/span&gt;))&lt;/span&gt;
&lt;span id=&quot;cb5-11&quot;&gt;&lt;a href=&quot;#cb5-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , (&lt;span class=&quot;ch&quot;&gt;&amp;#39;R&amp;#39;&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Turn&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; pow &lt;span class=&quot;dt&quot;&gt;East&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; (&lt;span class=&quot;ot&quot;&gt;`div`&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;90&lt;/span&gt;))&lt;/span&gt;
&lt;span id=&quot;cb5-12&quot;&gt;&lt;a href=&quot;#cb5-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , (&lt;span class=&quot;ch&quot;&gt;&amp;#39;N&amp;#39;&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Move&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;*^&lt;/span&gt; dirPoint &lt;span class=&quot;dt&quot;&gt;North&lt;/span&gt;))&lt;/span&gt;
&lt;span id=&quot;cb5-13&quot;&gt;&lt;a href=&quot;#cb5-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , (&lt;span class=&quot;ch&quot;&gt;&amp;#39;S&amp;#39;&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Move&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;*^&lt;/span&gt; dirPoint &lt;span class=&quot;dt&quot;&gt;South&lt;/span&gt;))&lt;/span&gt;
&lt;span id=&quot;cb5-14&quot;&gt;&lt;a href=&quot;#cb5-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , (&lt;span class=&quot;ch&quot;&gt;&amp;#39;E&amp;#39;&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Move&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;*^&lt;/span&gt; dirPoint &lt;span class=&quot;dt&quot;&gt;East&lt;/span&gt; ))&lt;/span&gt;
&lt;span id=&quot;cb5-15&quot;&gt;&lt;a href=&quot;#cb5-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , (&lt;span class=&quot;ch&quot;&gt;&amp;#39;W&amp;#39;&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Move&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;*^&lt;/span&gt; dirPoint &lt;span class=&quot;dt&quot;&gt;West&lt;/span&gt; ))&lt;/span&gt;
&lt;span id=&quot;cb5-16&quot;&gt;&lt;a href=&quot;#cb5-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ]&lt;/span&gt;
&lt;span id=&quot;cb5-17&quot;&gt;&lt;a href=&quot;#cb5-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-18&quot;&gt;&lt;a href=&quot;#cb5-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;parseInstr ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Instr&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-19&quot;&gt;&lt;a href=&quot;#cb5-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;parseInstr []    &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-20&quot;&gt;&lt;a href=&quot;#cb5-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;parseInstr (c&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;n) &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; M.lookup c mkInstr &lt;span class=&quot;op&quot;&gt;&amp;lt;*&amp;gt;&lt;/span&gt; readMaybe n&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb6&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb6-1&quot;&gt;&lt;a href=&quot;#cb6-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;ghci&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; parseInstr &lt;span class=&quot;st&quot;&gt;&amp;quot;F30&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-2&quot;&gt;&lt;a href=&quot;#cb6-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;Forward&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;30&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-3&quot;&gt;&lt;a href=&quot;#cb6-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;ghci&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; parseInstr &lt;span class=&quot;st&quot;&gt;&amp;quot;L270&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-4&quot;&gt;&lt;a href=&quot;#cb6-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;Turn&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;East&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-5&quot;&gt;&lt;a href=&quot;#cb6-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;ghci&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; parseInstr &lt;span class=&quot;st&quot;&gt;&amp;quot;N15&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-6&quot;&gt;&lt;a href=&quot;#cb6-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;Move&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;15&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And now part 1, part 2 are basically just different ways of folding through a list of instructions:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb7&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb7-1&quot;&gt;&lt;a href=&quot;#cb7-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;toInstrs ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Instr&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb7-2&quot;&gt;&lt;a href=&quot;#cb7-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;toInstrs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;traverse&lt;/span&gt; parseInstr &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;lines&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-3&quot;&gt;&lt;a href=&quot;#cb7-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-4&quot;&gt;&lt;a href=&quot;#cb7-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | Use (ship heading, position) as the state&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-5&quot;&gt;&lt;a href=&quot;#cb7-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part1 ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Instr&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Dir&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb7-6&quot;&gt;&lt;a href=&quot;#cb7-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part1 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; foldl&amp;#39; go (&lt;span class=&quot;dt&quot;&gt;East&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb7-7&quot;&gt;&lt;a href=&quot;#cb7-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-8&quot;&gt;&lt;a href=&quot;#cb7-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    go ::&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Dir&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Instr&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Dir&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb7-9&quot;&gt;&lt;a href=&quot;#cb7-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    go (&lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;dir, &lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;p) &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-10&quot;&gt;&lt;a href=&quot;#cb7-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;dt&quot;&gt;Forward&lt;/span&gt; n &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (dir     , p &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; n &lt;span class=&quot;op&quot;&gt;*^&lt;/span&gt; dirPoint dir)&lt;/span&gt;
&lt;span id=&quot;cb7-11&quot;&gt;&lt;a href=&quot;#cb7-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;dt&quot;&gt;Turn&lt;/span&gt; d    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (dir &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt; d, p                    )&lt;/span&gt;
&lt;span id=&quot;cb7-12&quot;&gt;&lt;a href=&quot;#cb7-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;dt&quot;&gt;Move&lt;/span&gt; r    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (dir     , p &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; r                )&lt;/span&gt;
&lt;span id=&quot;cb7-13&quot;&gt;&lt;a href=&quot;#cb7-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-14&quot;&gt;&lt;a href=&quot;#cb7-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | Use (ship position, waypoint vector from ship) as the state&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-15&quot;&gt;&lt;a href=&quot;#cb7-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part2 ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Instr&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb7-16&quot;&gt;&lt;a href=&quot;#cb7-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; foldl&amp;#39; go (&lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb7-17&quot;&gt;&lt;a href=&quot;#cb7-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-18&quot;&gt;&lt;a href=&quot;#cb7-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    go ::&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Instr&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb7-19&quot;&gt;&lt;a href=&quot;#cb7-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    go (&lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;shp, &lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;wp) &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-20&quot;&gt;&lt;a href=&quot;#cb7-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;dt&quot;&gt;Forward&lt;/span&gt; n &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (shp &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; n &lt;span class=&quot;op&quot;&gt;*^&lt;/span&gt; wp, wp           )&lt;/span&gt;
&lt;span id=&quot;cb7-21&quot;&gt;&lt;a href=&quot;#cb7-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;dt&quot;&gt;Turn&lt;/span&gt; d    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (shp          , rotPoint d wp)&lt;/span&gt;
&lt;span id=&quot;cb7-22&quot;&gt;&lt;a href=&quot;#cb7-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;dt&quot;&gt;Move&lt;/span&gt; r    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (shp          , wp &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; r       )&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And that’s it! For &lt;code&gt;part1&lt;/code&gt;, we want the mannhattan distance of the ship’s final position (the second item in the tuple), and for part2, we want the manhattan distance of the ship’s final position (the first item in the tuple).&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb8&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb8-1&quot;&gt;&lt;a href=&quot;#cb8-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;mannDist ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb8-2&quot;&gt;&lt;a href=&quot;#cb8-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;mannDist (&lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; x y) &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;abs&lt;/span&gt; x &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;abs&lt;/span&gt; y&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;day-12-benchmarks&quot;&gt;Day 12 Benchmarks&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; Day 12a
benchmarking...
time                 3.218 μs   (3.088 μs .. 3.351 μs)
                     0.985 R²   (0.970 R² .. 0.992 R²)
mean                 2.910 μs   (2.819 μs .. 3.080 μs)
std dev              371.3 ns   (282.6 ns .. 558.0 ns)
variance introduced by outliers: 92% (severely inflated)

* parsing and formatting times excluded

&amp;gt;&amp;gt; Day 12b
benchmarking...
time                 7.870 μs   (7.667 μs .. 8.341 μs)
                     0.984 R²   (0.964 R² .. 1.000 R²)
mean                 8.189 μs   (7.772 μs .. 9.812 μs)
std dev              2.715 μs   (100.2 ns .. 5.679 μs)
variance introduced by outliers: 99% (severely inflated)

* parsing and formatting times excluded&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md#day-12</link>
      <pubDate>Sat, 12 Dec 2020 01:00:00 EST</pubDate>
    </item>

    <item>
      <title>Day 11</title>
      <description>&lt;h2 id=&quot;day-11&quot;&gt;Day 11&lt;/h2&gt;
&lt;!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day11.md`.  If you want to edit this, edit
that file instead!
--&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://adventofcode.com/2020/day/11&quot;&gt;Prompt&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day11.hs&quot;&gt;Code&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://mstksg.github.io/advent-of-code-2020/src/AOC.Challenge.Day11.html&quot;&gt;Rendered&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day11.md&quot;&gt;Standalone Reflection Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;My first day on the leaderboard! :D 21 / 352. Had a big dip on my second part because I had some silly typos that were difficult to catch in the moment D:&lt;/p&gt;
&lt;p&gt;After refactoring things, I realized that part 1 and part 2 are really the same, with only two differences:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Each point as a different neighborhood set (in part 1, it’s the immediate neighbors; in part 2, it’s all of the line-of-sights in each direction).&lt;/li&gt;
&lt;li&gt;Threshold for seats unseating is 4 for part 1 and 5 for part 2.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So let’s write our function parameterized on those two. We’ll be storing our world as a &lt;code&gt;Map Point Bool&lt;/code&gt;, where &lt;code&gt;False&lt;/code&gt; represents an empty seat and &lt;code&gt;True&lt;/code&gt; represents a full one. Floor points are not included in the map.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | A 2-vector type from the linear library, with a very convenient Num&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- instance.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; a &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; a a&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | A useful utility function I keep around that counts the number of items in&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-8&quot;&gt;&lt;a href=&quot;#cb1-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- a container matching a predicate&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-9&quot;&gt;&lt;a href=&quot;#cb1-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;countTrue ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Foldable&lt;/span&gt; f &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; (a &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Bool&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; f a &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-10&quot;&gt;&lt;a href=&quot;#cb1-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;countTrue p &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;filter&lt;/span&gt; p &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; toList&lt;/span&gt;
&lt;span id=&quot;cb1-11&quot;&gt;&lt;a href=&quot;#cb1-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-12&quot;&gt;&lt;a href=&quot;#cb1-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;seatRule&lt;/span&gt;
&lt;span id=&quot;cb1-13&quot;&gt;&lt;a href=&quot;#cb1-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;                       &lt;span class=&quot;co&quot;&gt;-- ^ exit seat threshold&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-14&quot;&gt;&lt;a href=&quot;#cb1-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;)     &lt;span class=&quot;co&quot;&gt;-- ^ neighbors for each point&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-15&quot;&gt;&lt;a href=&quot;#cb1-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Bool&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-16&quot;&gt;&lt;a href=&quot;#cb1-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Bool&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-17&quot;&gt;&lt;a href=&quot;#cb1-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;seatRule thr nmp mp &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; M.intersectionWith go nmp mp&lt;/span&gt;
&lt;span id=&quot;cb1-18&quot;&gt;&lt;a href=&quot;#cb1-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-19&quot;&gt;&lt;a href=&quot;#cb1-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    go neighbs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-20&quot;&gt;&lt;a href=&quot;#cb1-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;dt&quot;&gt;Empty&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;not&lt;/span&gt; (&lt;span class=&quot;fu&quot;&gt;all&lt;/span&gt; (mp &lt;span class=&quot;op&quot;&gt;M.!&lt;/span&gt;) neighbs)&lt;/span&gt;
&lt;span id=&quot;cb1-21&quot;&gt;&lt;a href=&quot;#cb1-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;dt&quot;&gt;Full&lt;/span&gt;  &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-22&quot;&gt;&lt;a href=&quot;#cb1-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; onNeighbs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; countTrue (mp &lt;span class=&quot;op&quot;&gt;M.!&lt;/span&gt;) neighbs&lt;/span&gt;
&lt;span id=&quot;cb1-23&quot;&gt;&lt;a href=&quot;#cb1-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;in&lt;/span&gt;  &lt;span class=&quot;fu&quot;&gt;not&lt;/span&gt; (onNeighbs &lt;span class=&quot;op&quot;&gt;&amp;gt;=&lt;/span&gt; thr)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we just need to create our neighborhood maps.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | The eight immediate neighbors around 0,0&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;immediateNeighbs ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;immediateNeighbs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [ &lt;span class=&quot;dt&quot;&gt;V2&lt;/span&gt; dx dy&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; dx &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; [&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , dy &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;if&lt;/span&gt; dx &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;then&lt;/span&gt; [&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;] &lt;span class=&quot;kw&quot;&gt;else&lt;/span&gt; [&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb2-7&quot;&gt;&lt;a href=&quot;#cb2-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ]&lt;/span&gt;
&lt;span id=&quot;cb2-8&quot;&gt;&lt;a href=&quot;#cb2-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-9&quot;&gt;&lt;a href=&quot;#cb2-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | From a set of seat locations, get a map of points to all of those points&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-10&quot;&gt;&lt;a href=&quot;#cb2-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- neighbors where there is a seat. Should only need to be computed once.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-11&quot;&gt;&lt;a href=&quot;#cb2-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;lineOfSights1&lt;/span&gt;
&lt;span id=&quot;cb2-12&quot;&gt;&lt;a href=&quot;#cb2-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-13&quot;&gt;&lt;a href=&quot;#cb2-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb2-14&quot;&gt;&lt;a href=&quot;#cb2-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;lineOfSeights1 pts &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; M.fromSet go mp&lt;/span&gt;
&lt;span id=&quot;cb2-15&quot;&gt;&lt;a href=&quot;#cb2-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-16&quot;&gt;&lt;a href=&quot;#cb2-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    go p _ &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; S.fromList&lt;/span&gt;
&lt;span id=&quot;cb2-17&quot;&gt;&lt;a href=&quot;#cb2-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;           &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;filter&lt;/span&gt; (&lt;span class=&quot;ot&quot;&gt;`S.member`&lt;/span&gt; pts)&lt;/span&gt;
&lt;span id=&quot;cb2-18&quot;&gt;&lt;a href=&quot;#cb2-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;           &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; p)&lt;/span&gt;
&lt;span id=&quot;cb2-19&quot;&gt;&lt;a href=&quot;#cb2-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;           &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; immediateNeighbs&lt;/span&gt;
&lt;span id=&quot;cb2-20&quot;&gt;&lt;a href=&quot;#cb2-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-21&quot;&gt;&lt;a href=&quot;#cb2-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | From a set of seat locations, Get a map of points to all of those points&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-22&quot;&gt;&lt;a href=&quot;#cb2-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- visible neighbors. Should only need to be computed once.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-23&quot;&gt;&lt;a href=&quot;#cb2-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;lineOfSights2&lt;/span&gt;
&lt;span id=&quot;cb2-24&quot;&gt;&lt;a href=&quot;#cb2-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-25&quot;&gt;&lt;a href=&quot;#cb2-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb2-26&quot;&gt;&lt;a href=&quot;#cb2-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;lineOfSights2 bb pts &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; M.mapWithKey go pts&lt;/span&gt;
&lt;span id=&quot;cb2-27&quot;&gt;&lt;a href=&quot;#cb2-27&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-28&quot;&gt;&lt;a href=&quot;#cb2-28&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    go p _ &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; S.fromList&lt;/span&gt;
&lt;span id=&quot;cb2-29&quot;&gt;&lt;a href=&quot;#cb2-29&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;           &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; mapMaybe (los p)&lt;/span&gt;
&lt;span id=&quot;cb2-30&quot;&gt;&lt;a href=&quot;#cb2-30&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;           &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; immediateNeighbs&lt;/span&gt;
&lt;span id=&quot;cb2-31&quot;&gt;&lt;a href=&quot;#cb2-31&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    los p d &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; find (&lt;span class=&quot;ot&quot;&gt;`S.member`&lt;/span&gt; pts)&lt;/span&gt;
&lt;span id=&quot;cb2-32&quot;&gt;&lt;a href=&quot;#cb2-32&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;takeWhile&lt;/span&gt; inBoundingBox&lt;/span&gt;
&lt;span id=&quot;cb2-33&quot;&gt;&lt;a href=&quot;#cb2-33&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;tail&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-34&quot;&gt;&lt;a href=&quot;#cb2-34&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;iterate&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; d) p&lt;/span&gt;
&lt;span id=&quot;cb2-35&quot;&gt;&lt;a href=&quot;#cb2-35&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    inBoundingBox &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;all&lt;/span&gt; (&lt;span class=&quot;fu&quot;&gt;inRange&lt;/span&gt; (&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;dv&quot;&gt;99&lt;/span&gt;))&lt;/span&gt;
&lt;span id=&quot;cb2-36&quot;&gt;&lt;a href=&quot;#cb2-36&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;co&quot;&gt;-- inRange from Data.Ix&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-37&quot;&gt;&lt;a href=&quot;#cb2-37&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;co&quot;&gt;-- all from Data.Foldable and V2&amp;#39;s Foldable instance&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;(I hard-coded the bounds here, but in my actual solution I inferred it from the input.)&lt;/p&gt;
&lt;p&gt;Now to solve!&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | Handy utility function I have; repeat a function until you get the same&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- result twice.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;fixedPoint ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Eq&lt;/span&gt; a &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; (a &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; a) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; a &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; a&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;fixedPoint f &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; go&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    go &lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;x&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; x &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; y    &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; x&lt;/span&gt;
&lt;span id=&quot;cb3-8&quot;&gt;&lt;a href=&quot;#cb3-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;otherwise&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; go y&lt;/span&gt;
&lt;span id=&quot;cb3-9&quot;&gt;&lt;a href=&quot;#cb3-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-10&quot;&gt;&lt;a href=&quot;#cb3-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        y &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; f x&lt;/span&gt;
&lt;span id=&quot;cb3-11&quot;&gt;&lt;a href=&quot;#cb3-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-12&quot;&gt;&lt;a href=&quot;#cb3-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;solveWith&lt;/span&gt;
&lt;span id=&quot;cb3-13&quot;&gt;&lt;a href=&quot;#cb3-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;                      &lt;span class=&quot;co&quot;&gt;-- ^ exit seat threshold&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-14&quot;&gt;&lt;a href=&quot;#cb3-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt;)    &lt;span class=&quot;co&quot;&gt;-- ^ neighbors for each point&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-15&quot;&gt;&lt;a href=&quot;#cb3-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Bool&lt;/span&gt;           &lt;span class=&quot;co&quot;&gt;-- ^ initial state&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-16&quot;&gt;&lt;a href=&quot;#cb3-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;                      &lt;span class=&quot;co&quot;&gt;-- ^ equilibrium size&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-17&quot;&gt;&lt;a href=&quot;#cb3-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;solveWith thr neighbs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; countTrue &lt;span class=&quot;fu&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; fixedPoint (seatRule thr neighbs)&lt;/span&gt;
&lt;span id=&quot;cb3-18&quot;&gt;&lt;a href=&quot;#cb3-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-19&quot;&gt;&lt;a href=&quot;#cb3-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part1&lt;/span&gt;
&lt;span id=&quot;cb3-20&quot;&gt;&lt;a href=&quot;#cb3-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Bool&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-21&quot;&gt;&lt;a href=&quot;#cb3-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-22&quot;&gt;&lt;a href=&quot;#cb3-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part1 mp &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; solveWith &lt;span class=&quot;dv&quot;&gt;4&lt;/span&gt; los mp&lt;/span&gt;
&lt;span id=&quot;cb3-23&quot;&gt;&lt;a href=&quot;#cb3-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-24&quot;&gt;&lt;a href=&quot;#cb3-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    los &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; lineOfSight1 (M.keysSet mp)&lt;/span&gt;
&lt;span id=&quot;cb3-25&quot;&gt;&lt;a href=&quot;#cb3-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-26&quot;&gt;&lt;a href=&quot;#cb3-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2&lt;/span&gt;
&lt;span id=&quot;cb3-27&quot;&gt;&lt;a href=&quot;#cb3-27&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Bool&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-28&quot;&gt;&lt;a href=&quot;#cb3-28&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-29&quot;&gt;&lt;a href=&quot;#cb3-29&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2 mp &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; solveWith &lt;span class=&quot;dv&quot;&gt;5&lt;/span&gt; los mp&lt;/span&gt;
&lt;span id=&quot;cb3-30&quot;&gt;&lt;a href=&quot;#cb3-30&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-31&quot;&gt;&lt;a href=&quot;#cb3-31&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    los &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; lineOfSight2 (M.keysSet mp)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;day-11-benchmarks&quot;&gt;Day 11 Benchmarks&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; Day 11a
benchmarking...
time                 133.7 ms   (125.9 ms .. 142.4 ms)
                     0.994 R²   (0.982 R² .. 0.999 R²)
mean                 133.6 ms   (128.6 ms .. 138.2 ms)
std dev              7.158 ms   (4.642 ms .. 10.49 ms)
variance introduced by outliers: 11% (moderately inflated)

* parsing and formatting times excluded

&amp;gt;&amp;gt; Day 11b
benchmarking...
time                 128.9 ms   (115.0 ms .. 142.0 ms)
                     0.985 R²   (0.962 R² .. 0.998 R²)
mean                 129.8 ms   (125.0 ms .. 137.1 ms)
std dev              9.339 ms   (5.576 ms .. 12.80 ms)
variance introduced by outliers: 23% (moderately inflated)

* parsing and formatting times excluded&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md#day-11</link>
      <pubDate>Fri, 11 Dec 2020 01:00:00 EST</pubDate>
    </item>

    <item>
      <title>Day 10</title>
      <description>&lt;h2 id=&quot;day-10&quot;&gt;Day 10&lt;/h2&gt;
&lt;!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day10.md`.  If you want to edit this, edit
that file instead!
--&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://adventofcode.com/2020/day/10&quot;&gt;Prompt&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day10.hs&quot;&gt;Code&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://mstksg.github.io/advent-of-code-2020/src/AOC.Challenge.Day10.html&quot;&gt;Rendered&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day10.md&quot;&gt;Standalone Reflection Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Today is another day where the “automatically build a memoized recursive map” in Haskell really shines :) It’s essentially the same problem as Day 7.&lt;/p&gt;
&lt;p&gt;For the first part, once you sort the list, you can compute the differences and then build a frequency map&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | Build a frequency map&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;freqs ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Ord&lt;/span&gt; a &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; [a] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; a &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;freqs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; M.fromListWith (&lt;span class=&quot;op&quot;&gt;+&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;map&lt;/span&gt; (,&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; toList&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;diffs ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;diffs xs&lt;span class=&quot;op&quot;&gt;@&lt;/span&gt;(_&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;ys) &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;zipWith&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;) ys xs&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;ghci&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; diffs [&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;4&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;7&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;[&lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And so part 1 can be done with:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part1 ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part1 xs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; (stepFreqs &lt;span class=&quot;op&quot;&gt;M.!&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt; (stepFreqs &lt;span class=&quot;op&quot;&gt;M.!&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    xs&amp;#39; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; xs &lt;span class=&quot;op&quot;&gt;++&lt;/span&gt; [&lt;span class=&quot;fu&quot;&gt;maximum&lt;/span&gt; xs &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    stepFreqs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; freqs (diffs (&lt;span class=&quot;fu&quot;&gt;sort&lt;/span&gt; xs&amp;#39;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For part 2, if we get an &lt;code&gt;IntSet&lt;/code&gt; of all of your numbers (and adding the zero, and the goal, the maximum + 3), then we can use it to build our &lt;code&gt;IntMap&lt;/code&gt; of all the number of paths from a given number.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt;           &lt;span class=&quot;dt&quot;&gt;Data.IntMap&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;IntMap&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt;           &lt;span class=&quot;dt&quot;&gt;Data.IntSet&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;IntSet&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb4-3&quot;&gt;&lt;a href=&quot;#cb4-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;qualified&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Data.IntMap&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IM&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-4&quot;&gt;&lt;a href=&quot;#cb4-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;qualified&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Data.IntSet&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IS&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-5&quot;&gt;&lt;a href=&quot;#cb4-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-6&quot;&gt;&lt;a href=&quot;#cb4-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | A map of numbers to the count of how many paths from that number to&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-7&quot;&gt;&lt;a href=&quot;#cb4-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- the goal&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-8&quot;&gt;&lt;a href=&quot;#cb4-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;pathsToGoal ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IntSet&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IntMap&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-9&quot;&gt;&lt;a href=&quot;#cb4-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;pathsToGoal xs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; res&lt;/span&gt;
&lt;span id=&quot;cb4-10&quot;&gt;&lt;a href=&quot;#cb4-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-11&quot;&gt;&lt;a href=&quot;#cb4-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    res &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;flip&lt;/span&gt; IM.fromSet xs &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; \i &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-12&quot;&gt;&lt;a href=&quot;#cb4-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;kw&quot;&gt;if&lt;/span&gt; i &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; goal&lt;/span&gt;
&lt;span id=&quot;cb4-13&quot;&gt;&lt;a href=&quot;#cb4-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-14&quot;&gt;&lt;a href=&quot;#cb4-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;sum&lt;/span&gt; [ IM.findWithDefault &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; (i &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; j) res&lt;/span&gt;
&lt;span id=&quot;cb4-15&quot;&gt;&lt;a href=&quot;#cb4-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                 &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; j &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; [&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb4-16&quot;&gt;&lt;a href=&quot;#cb4-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                 ]&lt;/span&gt;
&lt;span id=&quot;cb4-17&quot;&gt;&lt;a href=&quot;#cb4-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    goal &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; IS.findMax is&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Our answer is &lt;code&gt;res&lt;/code&gt;, the map of numbers to the count of how many paths exist from that number to the goal. To generate the count for a given number &lt;code&gt;i&lt;/code&gt;, we add the number of paths from &lt;code&gt;i+1&lt;/code&gt;, &lt;code&gt;i+2&lt;/code&gt;, and &lt;code&gt;i+3&lt;/code&gt;. We get that count by looking it up in &lt;code&gt;res&lt;/code&gt;!&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part2 ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2 xs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; pathsToGoal xs &lt;span class=&quot;op&quot;&gt;IM.!&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-3&quot;&gt;&lt;a href=&quot;#cb5-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-4&quot;&gt;&lt;a href=&quot;#cb5-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    xs&amp;#39; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; IS.fromList (&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; xs &lt;span class=&quot;op&quot;&gt;++&lt;/span&gt; [&lt;span class=&quot;fu&quot;&gt;maximum&lt;/span&gt; xs &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A quick note — after some discussion on the irc, we did &lt;a href=&quot;https://www.reddit.com/r/adventofcode/comments/kabi91/2020_day_10_closedform_mathematical_solution/&quot;&gt;find a closed-form solution&lt;/a&gt;…I might be editing this to implement it in Haskell eventually :)&lt;/p&gt;
&lt;h3 id=&quot;day-10-benchmarks&quot;&gt;Day 10 Benchmarks&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; Day 10a
benchmarking...
time                 6.240 μs   (6.090 μs .. 6.639 μs)
                     0.985 R²   (0.964 R² .. 0.999 R²)
mean                 6.843 μs   (6.274 μs .. 7.805 μs)
std dev              2.589 μs   (1.164 μs .. 3.977 μs)
variance introduced by outliers: 99% (severely inflated)

* parsing and formatting times excluded

&amp;gt;&amp;gt; Day 10b
benchmarking...
time                 9.300 μs   (8.801 μs .. 10.10 μs)
                     0.979 R²   (0.961 R² .. 1.000 R²)
mean                 9.003 μs   (8.778 μs .. 9.453 μs)
std dev              1.001 μs   (176.6 ns .. 1.635 μs)
variance introduced by outliers: 89% (severely inflated)

* parsing and formatting times excluded&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md#day-10</link>
      <pubDate>Thu, 10 Dec 2020 01:00:00 EST</pubDate>
    </item>

    <item>
      <title>Day 9</title>
      <description>&lt;h2 id=&quot;day-9&quot;&gt;Day 9&lt;/h2&gt;
&lt;!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day09.md`.  If you want to edit this, edit
that file instead!
--&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://adventofcode.com/2020/day/9&quot;&gt;Prompt&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day09.hs&quot;&gt;Code&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://mstksg.github.io/advent-of-code-2020/src/AOC.Challenge.Day09.html&quot;&gt;Rendered&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day09.md&quot;&gt;Standalone Reflection Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Let’s tackle day 9!&lt;/p&gt;
&lt;p&gt;A good way to check if a sequence of 25 numbers can add to the 26th number is to just iterate over everything, like we might have done in day 1:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | check if, for ([x,y,z] ++ [a]), no pair in xyz can add to &amp;#39;a&amp;#39;.  If it&amp;#39;s&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- bad, it returns &amp;#39;Just a&amp;#39;.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;isBad ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;isBad xs0 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    x &lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; xs &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;reverse&lt;/span&gt; xs0&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; badCheck &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;          y&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;ys &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; tails (toList xs)&lt;/span&gt;
&lt;span id=&quot;cb1-8&quot;&gt;&lt;a href=&quot;#cb1-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;          z    &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; ys&lt;/span&gt;
&lt;span id=&quot;cb1-9&quot;&gt;&lt;a href=&quot;#cb1-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;          guard &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; (y &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; z) &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; x&lt;/span&gt;
&lt;span id=&quot;cb1-10&quot;&gt;&lt;a href=&quot;#cb1-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    x &lt;span class=&quot;op&quot;&gt;&amp;lt;$&lt;/span&gt; guard badCheck&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I use my favorite &lt;code&gt;Maybe&lt;/code&gt; do-notation trick of pattern matching within the block to take advantage of do block short circuiting for &lt;code&gt;Maybe&lt;/code&gt; with its &lt;code&gt;MonadFail&lt;/code&gt; instance. If you reverse &lt;code&gt;xs0&lt;/code&gt; then you can get the last item as the head, and the rest as the tail :)&lt;/p&gt;
&lt;p&gt;In &lt;code&gt;badCheck&lt;/code&gt; we do a list-monad powered search (see my &lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day01.md&quot;&gt;Day 1 Reflections&lt;/a&gt;) for more details on how it works. &lt;code&gt;badCheck&lt;/code&gt; will return &lt;code&gt;True&lt;/code&gt; if the search is empty (with &lt;code&gt;null&lt;/code&gt;). &lt;code&gt;guard badCheck&lt;/code&gt; will be Nothing if &lt;code&gt;badCheck&lt;/code&gt; fails (and our list is good) and &lt;code&gt;Just x&lt;/code&gt; if &lt;code&gt;badCheck&lt;/code&gt; succeeds (and our list is bad).&lt;/p&gt;
&lt;p&gt;Part 1 is then just finding the first bad sequence:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part1 ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part1 xs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; listToMaybe&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [ y&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; ys     &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; tails xs&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; y &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; [isBad (&lt;span class=&quot;fu&quot;&gt;take&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;26&lt;/span&gt; ys)]&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For part 2, there’s a nice-ish way to do it in constant-time. First, we can generate a cumulative sum &lt;code&gt;cumSum&lt;/code&gt; for the &lt;em&gt;entire&lt;/em&gt; list. Then we know that &lt;code&gt;sumFrom(i,j)&lt;/code&gt; in our original list is just &lt;code&gt;cumSum(j) - cumSum(i)&lt;/code&gt;. This is similar to how definite integrals work, or also how you can find the area under a probability density function by subtracting two points from its cumulative distribution function.&lt;/p&gt;
&lt;p&gt;So now the problem just becomes finding &lt;code&gt;i,j&lt;/code&gt; where &lt;code&gt;cumSum(j) - cumSum(i) == goal&lt;/code&gt;. There’s a clean imperative-ish way to do this that involves just “sliding” your window &lt;code&gt;i,j&lt;/code&gt; up from &lt;code&gt;0,1&lt;/code&gt;. If &lt;code&gt;cumSum(j) - cumSum(i)&lt;/code&gt; is too small, increase &lt;code&gt;j&lt;/code&gt; by 1 to open the window up a bit. If it’s too big, increase &lt;code&gt;i&lt;/code&gt; by 1 to close the window up a bit.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;findBounds ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;V.Vector&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;findBounds ns goal &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; go &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    go &lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;i &lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;j &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      x &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; ns &lt;span class=&quot;op&quot;&gt;V.!?&lt;/span&gt; i&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      y &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; ns &lt;span class=&quot;op&quot;&gt;V.!?&lt;/span&gt; j&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;compare&lt;/span&gt; (y &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt; x) goal &lt;span class=&quot;kw&quot;&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-8&quot;&gt;&lt;a href=&quot;#cb3-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;dt&quot;&gt;LT&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; go i (j &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb3-9&quot;&gt;&lt;a href=&quot;#cb3-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;dt&quot;&gt;EQ&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; (i, j)&lt;/span&gt;
&lt;span id=&quot;cb3-10&quot;&gt;&lt;a href=&quot;#cb3-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;dt&quot;&gt;GT&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; go (i &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;) j&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And there you go!&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part2 ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2 xs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-3&quot;&gt;&lt;a href=&quot;#cb4-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    goal &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; part1 xs&lt;/span&gt;
&lt;span id=&quot;cb4-4&quot;&gt;&lt;a href=&quot;#cb4-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; cumSum &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; V.fromList (scanl&amp;#39; (&lt;span class=&quot;op&quot;&gt;+&lt;/span&gt;) &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; xs)       &lt;span class=&quot;co&quot;&gt;-- cumulative sum&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-5&quot;&gt;&lt;a href=&quot;#cb4-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    (i, j) &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; findBounds cumSum goal&lt;/span&gt;
&lt;span id=&quot;cb4-6&quot;&gt;&lt;a href=&quot;#cb4-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; xs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;take&lt;/span&gt; (j &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt; i) &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;drop&lt;/span&gt; i &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; ns&lt;/span&gt;
&lt;span id=&quot;cb4-7&quot;&gt;&lt;a href=&quot;#cb4-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;minimum&lt;/span&gt; xs &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;maximum&lt;/span&gt; xs&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If anything, maybe the implementation of &lt;code&gt;findBounds&lt;/code&gt; shows how one might directly translate a tight mutable loop in an imperative language into a tail-recursive function in Haskell!&lt;/p&gt;
&lt;p&gt;We do often like to avoid explicitly writing recursive functions when we can, but in this case I’m not sure if there’s a way to get around it other than switching to a full on mutable answer, or in a very complex way that is extremely specific to the situation. If you think of one, let me know! :D&lt;/p&gt;
&lt;h3 id=&quot;day-9-benchmarks&quot;&gt;Day 9 Benchmarks&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; Day 09a
benchmarking...
time                 153.6 μs   (148.1 μs .. 162.6 μs)
                     0.988 R²   (0.980 R² .. 1.000 R²)
mean                 151.5 μs   (149.0 μs .. 156.8 μs)
std dev              12.69 μs   (5.899 μs .. 21.86 μs)
variance introduced by outliers: 74% (severely inflated)

* parsing and formatting times excluded

&amp;gt;&amp;gt; Day 09b
benchmarking...
time                 172.0 μs   (169.9 μs .. 175.0 μs)
                     0.998 R²   (0.994 R² .. 1.000 R²)
mean                 170.4 μs   (169.5 μs .. 174.1 μs)
std dev              5.863 μs   (3.130 μs .. 10.90 μs)
variance introduced by outliers: 32% (moderately inflated)

* parsing and formatting times excluded&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md#day-9</link>
      <pubDate>Wed,  9 Dec 2020 01:00:00 EST</pubDate>
    </item>

    <item>
      <title>Day 8</title>
      <description>&lt;h2 id=&quot;day-8&quot;&gt;Day 8&lt;/h2&gt;
&lt;!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day08.md`.  If you want to edit this, edit
that file instead!
--&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://adventofcode.com/2020/day/8&quot;&gt;Prompt&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day08.hs&quot;&gt;Code&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://mstksg.github.io/advent-of-code-2020/src/AOC.Challenge.Day08.html&quot;&gt;Rendered&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day08.md&quot;&gt;Standalone Reflection Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Nothing tooooo complicated about today’s, I feel: it is another staple of AoC — simulating a virtual machine! :) Only this time our program is separate from our memory, so we don’t have any actual self-modifying code. However, my guard is up: this might turn into one of those soon in another day.&lt;/p&gt;
&lt;p&gt;At least, there are some interesting things we can do to prepare for a potential switch to different requirements in a later day (with the &lt;code&gt;Ixed&lt;/code&gt;) typeclass, and also a nice way to handle the perturbations in Part 2 using &lt;code&gt;holesOf&lt;/code&gt; and lens traversal composition.&lt;/p&gt;
&lt;p&gt;My main program was a sequence of &lt;code&gt;Command&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Instr&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;NOP&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;ACC&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Command&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Instr&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But, what container should we use for these?&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;code&gt;[Command]&lt;/code&gt;: Nope, bad, literally no reason to ever use this except for O(1) push and pop. The main operation here is indexing, and it’s O(i) on the index.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Vector Command&lt;/code&gt;: Very fast indexing (O(1) on the index), but very bad for any sort of addition of new instructions in-flight if that comes up in the future. But good enough for now.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Seq Command&lt;/code&gt;: Efficient indexing (O(1) on the index), and very good for adding new instructions to either end (or even in the middle) in-flight if it comes to that.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;IntMap Command&lt;/code&gt;: Efficient indexing (O(1) on the index), very good for adding new instructions to either end, and also good for a sparse program bank if it ever comes to that.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;Luckily&lt;/em&gt;, we can get a common interface for all four of these options by using the &lt;code&gt;Ixed&lt;/code&gt; typeclass from the &lt;em&gt;lens&lt;/em&gt; library, which abstracts over different “indexable” things. You’d get a safe index with &lt;code&gt;xs ^? ix i&lt;/code&gt;. So whenever possible, I’ve written all my code to work generally over all four of these in case I have to swap quickly in the future.&lt;/p&gt;
&lt;p&gt;One theoretical nice container would actually be the &lt;code&gt;PointedList&lt;/code&gt; data type (one implementation is in the &lt;em&gt;&lt;a href=&quot;https://hackage.haskell.org/package/pointedlist-0.6.1/docs/Data-List-PointedList.html&quot;&gt;pointedlist&lt;/a&gt;&lt;/em&gt; library). This is because all of our addressing is relative, so instead of storing a “current index”, we could just always point towards the focus of the tape, and shift the tape left or right for &lt;code&gt;JMP&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;However, this is kind of difficult to adapt to work in a uniform interface to the other four types…so, goodbye theoretical nicety, sacrificed in the name of adaptivity :’(&lt;/p&gt;
&lt;p&gt;So for my solution I used &lt;code&gt;Vector&lt;/code&gt;, which has just the API necessary without the extra flexibility that &lt;code&gt;Seq&lt;/code&gt; and &lt;code&gt;IntMap&lt;/code&gt; offer, since we don’t need it! But, just know that things could be swapped at any time, thanks to the magic (or horror, depending on your point of view) of typeclasses.&lt;/p&gt;
&lt;p&gt;On the other hand, if we separate out the index from a fixed container, it does make the state a lot simpler. It means that our state is really only the current pointer and the accumulator:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;CState&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;CS&lt;/span&gt; {&lt;span class=&quot;ot&quot;&gt; csPtr ::&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;,&lt;span class=&quot;ot&quot;&gt; csAcc ::&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; }&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;initialCS ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;CState&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;initialCS &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;CS&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;runCommand ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Command&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;CState&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;CState&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So our actual program becomes a very tight &lt;code&gt;CState -&amp;gt; Maybe CState&lt;/code&gt; loop – very efficient because the state is only a tuple! That means that we can simply chain things using &lt;code&gt;iterateMaybe&lt;/code&gt; go get a list of all successive states:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | A handy utility function I keep around&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;iterateMaybe ::&lt;/span&gt; (a &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; a) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; a &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [a]&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;iterateMaybe f &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; go&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    go x &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; x &lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt; f x &lt;span class=&quot;kw&quot;&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; []&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; y  &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; go y&lt;/span&gt;
&lt;span id=&quot;cb3-8&quot;&gt;&lt;a href=&quot;#cb3-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-9&quot;&gt;&lt;a href=&quot;#cb3-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;allStates ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Command&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;CState&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb3-10&quot;&gt;&lt;a href=&quot;#cb3-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;allStates cmd &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; iterateMaybe (runCommand cmd) initialCS&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So now we have a generator of all the states a given program bank will ever output. For part 1, we just need to find a loop. Luckily I have another handy utility function that scans a list and reports the first time a projection function’s result is repeated&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | Lazily find the first repeated projection.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;firstRepeatedBy ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Ord&lt;/span&gt; a &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; (b &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; a) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [b] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; b&lt;/span&gt;
&lt;span id=&quot;cb4-3&quot;&gt;&lt;a href=&quot;#cb4-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;firstRepeatedBy f &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; go S.empty&lt;/span&gt;
&lt;span id=&quot;cb4-4&quot;&gt;&lt;a href=&quot;#cb4-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-5&quot;&gt;&lt;a href=&quot;#cb4-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    go seen (x&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;xs)&lt;/span&gt;
&lt;span id=&quot;cb4-6&quot;&gt;&lt;a href=&quot;#cb4-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; f x &lt;span class=&quot;ot&quot;&gt;`S.member`&lt;/span&gt; seen &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; x&lt;/span&gt;
&lt;span id=&quot;cb4-7&quot;&gt;&lt;a href=&quot;#cb4-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;otherwise&lt;/span&gt;           &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; go (f x &lt;span class=&quot;ot&quot;&gt;`S.insert`&lt;/span&gt; seen) xs&lt;/span&gt;
&lt;span id=&quot;cb4-8&quot;&gt;&lt;a href=&quot;#cb4-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    go _ []     &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-9&quot;&gt;&lt;a href=&quot;#cb4-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-10&quot;&gt;&lt;a href=&quot;#cb4-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part1 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Command&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;CState&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-11&quot;&gt;&lt;a href=&quot;#cb4-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part1 cmd &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; firstRepititionBy csPtr states&lt;/span&gt;
&lt;span id=&quot;cb4-12&quot;&gt;&lt;a href=&quot;#cb4-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-13&quot;&gt;&lt;a href=&quot;#cb4-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    states &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; iterateMaybe (runCommand cmd) inititialCS&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now all that’s left is to actually implement &lt;code&gt;runCommand&lt;/code&gt;!&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;runCommand&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Command&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-3&quot;&gt;&lt;a href=&quot;#cb5-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;CState&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-4&quot;&gt;&lt;a href=&quot;#cb5-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;CState&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-5&quot;&gt;&lt;a href=&quot;#cb5-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;runCommand cmds cs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; (cmds &lt;span class=&quot;op&quot;&gt;^?&lt;/span&gt; ix (csPtr cs)) &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;amp;&amp;gt;&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-6&quot;&gt;&lt;a href=&quot;#cb5-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    (&lt;span class=&quot;dt&quot;&gt;NOP&lt;/span&gt;, _) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; cs { csPtr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; csPtr cs &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt; }&lt;/span&gt;
&lt;span id=&quot;cb5-7&quot;&gt;&lt;a href=&quot;#cb5-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    (&lt;span class=&quot;dt&quot;&gt;ACC&lt;/span&gt;, i) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; cs { csPtr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; csPtr cs &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;, csAcc &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; csAcc cs &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; i }&lt;/span&gt;
&lt;span id=&quot;cb5-8&quot;&gt;&lt;a href=&quot;#cb5-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    (&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;, i) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; cs { csPtr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; csPtr cs &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; i }&lt;/span&gt;
&lt;span id=&quot;cb5-9&quot;&gt;&lt;a href=&quot;#cb5-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-10&quot;&gt;&lt;a href=&quot;#cb5-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- note: &amp;lt;&amp;amp;&amp;gt; is flip fmap&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And the nice thing about it is that if we leave off the type annotation of &lt;code&gt;runCommand&lt;/code&gt;, we actually get a really nice polymorphic type if we ask GHC what it expects:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb6&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb6-1&quot;&gt;&lt;a href=&quot;#cb6-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;runCommand&lt;/span&gt;
&lt;span id=&quot;cb6-2&quot;&gt;&lt;a href=&quot;#cb6-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Ixed&lt;/span&gt; t, &lt;span class=&quot;dt&quot;&gt;Index&lt;/span&gt; t &lt;span class=&quot;op&quot;&gt;~&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;IxValue&lt;/span&gt; t &lt;span class=&quot;op&quot;&gt;~&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Instr&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;))&lt;/span&gt;
&lt;span id=&quot;cb6-3&quot;&gt;&lt;a href=&quot;#cb6-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; t&lt;/span&gt;
&lt;span id=&quot;cb6-4&quot;&gt;&lt;a href=&quot;#cb6-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;CState&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-5&quot;&gt;&lt;a href=&quot;#cb6-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;CState&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is the fully polymorphic signature that you get just from using &lt;code&gt;cmds ^? ix (csPtr cs)&lt;/code&gt;. It says that you can use this on &lt;em&gt;any&lt;/em&gt; program bank &lt;code&gt;t&lt;/code&gt; that’s an instance of &lt;code&gt;Ixed&lt;/code&gt;, as long as its index type is &lt;code&gt;Int&lt;/code&gt; and the value at that index is a &lt;code&gt;(Instr, Int)&lt;/code&gt;. Nothing about the typeclasses here is inherently lensy, it’s just a typeclass (like any other) to abstract over common interfaces that many types might have. In this fully polymorphic signature, we can use this on &lt;code&gt;Vector Command&lt;/code&gt;, &lt;code&gt;[Command]&lt;/code&gt;, &lt;code&gt;Seq Command&lt;/code&gt;, and &lt;code&gt;IntMap Command&lt;/code&gt;, as we wish to in the future if the need comes up.&lt;/p&gt;
&lt;p&gt;For part 2 we can take advantage of some &lt;em&gt;actual&lt;/em&gt; lens/optics magic, by using &lt;code&gt;holesOf&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb7&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb7-1&quot;&gt;&lt;a href=&quot;#cb7-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;holesOf&lt;/span&gt;
&lt;span id=&quot;cb7-2&quot;&gt;&lt;a href=&quot;#cb7-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Traversal&amp;#39;&lt;/span&gt; s a&lt;/span&gt;
&lt;span id=&quot;cb7-3&quot;&gt;&lt;a href=&quot;#cb7-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; s&lt;/span&gt;
&lt;span id=&quot;cb7-4&quot;&gt;&lt;a href=&quot;#cb7-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Pretext&lt;/span&gt; (&lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt;) a a s]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The type is definitely scary, but &lt;code&gt;holesOf&lt;/code&gt; is saying:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Give me a specification of which holes you want to poke (&lt;code&gt;Traversal&#39; s a&lt;/code&gt;, a value &lt;code&gt;s&lt;/code&gt; with holes &lt;code&gt;a&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;… and an item you want to poke the holes in (&lt;code&gt;s&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;… and I’ll return to you a list of continuations (&lt;code&gt;Pretext (-&amp;gt;) a a (t     a)&lt;/code&gt;), each one allowing you to edit a different hole in &lt;code&gt;s&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;Pretext&lt;/code&gt; is a bit of a complicated type, but the main interface you would use it with is:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb8&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb8-1&quot;&gt;&lt;a href=&quot;#cb8-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;peeks ::&lt;/span&gt; (a &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; a) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Pretext&lt;/span&gt; (&lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt;) a a s &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; s&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;peeks&lt;/code&gt; as for a function you would want to run on a hole (the &lt;code&gt;a -&amp;gt; a&lt;/code&gt;), the continuation you got from &lt;code&gt;holesOf&lt;/code&gt;, and then returns the “modified” &lt;code&gt;s&lt;/code&gt;, modified according to that transformation you ran on that hole.&lt;/p&gt;
&lt;p&gt;(thanks to &lt;em&gt;mniip&lt;/em&gt; on freenode IRC for pointing out how these two work together to me!)&lt;/p&gt;
&lt;p&gt;Every item in the list returned by &lt;code&gt;holesOf&lt;/code&gt; corresponds to a different hole, so for example:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb9&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb9-1&quot;&gt;&lt;a href=&quot;#cb9-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;ghci&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;map&lt;/span&gt; (peeks &lt;span class=&quot;fu&quot;&gt;negate&lt;/span&gt;) (holesOf &lt;span class=&quot;fu&quot;&gt;traverse&lt;/span&gt; [&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;])&lt;/span&gt;
&lt;span id=&quot;cb9-2&quot;&gt;&lt;a href=&quot;#cb9-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  [ [&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb9-3&quot;&gt;&lt;a href=&quot;#cb9-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , [ &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb9-4&quot;&gt;&lt;a href=&quot;#cb9-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , [ &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb9-5&quot;&gt;&lt;a href=&quot;#cb9-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;traverse :: Traversal&#39; [a] a&lt;/code&gt; is a &lt;code&gt;Traversal&lt;/code&gt; that specifies the “holes” of a list &lt;code&gt;[a]&lt;/code&gt; to be each item &lt;code&gt;a&lt;/code&gt; in that list. And so &lt;code&gt;holesOf traverse [1,2,3]&lt;/code&gt; will return three &lt;code&gt;Pretext&lt;/code&gt;s: one corresponding to modifying each item in the list individually.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;peeks negate&lt;/code&gt; on each of the three items returned by &lt;code&gt;holesOf traverse [1,2,3]&lt;/code&gt; will return the modified list, each with a single hole edited by &lt;code&gt;negate&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In our case, instead of &lt;code&gt;negate&lt;/code&gt;, we can use a &lt;code&gt;flipInstr&lt;/code&gt; that flips &lt;code&gt;NOP&lt;/code&gt; to &lt;code&gt;JMP&lt;/code&gt; and &lt;code&gt;JMP&lt;/code&gt; to &lt;code&gt;NOP&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb10&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb10-1&quot;&gt;&lt;a href=&quot;#cb10-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;flipInstr ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Command&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Command&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb10-2&quot;&gt;&lt;a href=&quot;#cb10-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;flipInstr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb10-3&quot;&gt;&lt;a href=&quot;#cb10-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;NOP&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb10-4&quot;&gt;&lt;a href=&quot;#cb10-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;ACC&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;ACC&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb10-5&quot;&gt;&lt;a href=&quot;#cb10-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;NOP&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And now &lt;code&gt;peeks flipInstr&lt;/code&gt; will do the right thing:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb11&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb11-1&quot;&gt;&lt;a href=&quot;#cb11-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;ghci&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;map&lt;/span&gt; (peeks flipInstr) (holesOf &lt;span class=&quot;fu&quot;&gt;traverse&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;NOP&lt;/span&gt;,&lt;span class=&quot;dt&quot;&gt;ACC&lt;/span&gt;,&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;,&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;])&lt;/span&gt;
&lt;span id=&quot;cb11-2&quot;&gt;&lt;a href=&quot;#cb11-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;[ [&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;,&lt;span class=&quot;dt&quot;&gt;ACC&lt;/span&gt;,&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;,&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb11-3&quot;&gt;&lt;a href=&quot;#cb11-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;, [&lt;span class=&quot;dt&quot;&gt;NOP&lt;/span&gt;,&lt;span class=&quot;dt&quot;&gt;ACC&lt;/span&gt;,&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;,&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb11-4&quot;&gt;&lt;a href=&quot;#cb11-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;, [&lt;span class=&quot;dt&quot;&gt;NOP&lt;/span&gt;,&lt;span class=&quot;dt&quot;&gt;ACC&lt;/span&gt;,&lt;span class=&quot;dt&quot;&gt;NOP&lt;/span&gt;,&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb11-5&quot;&gt;&lt;a href=&quot;#cb11-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;, [&lt;span class=&quot;dt&quot;&gt;NOP&lt;/span&gt;,&lt;span class=&quot;dt&quot;&gt;ACC&lt;/span&gt;,&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;,&lt;span class=&quot;dt&quot;&gt;NOP&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb11-6&quot;&gt;&lt;a href=&quot;#cb11-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;An extra coolio thing is that traversals compose with &lt;code&gt;.&lt;/code&gt;, so we can actually use a traversal &lt;code&gt;_1&lt;/code&gt; (here, &lt;code&gt;Traversal&#39; (a,b) a&lt;/code&gt;, which says the single “hole” in an &lt;code&gt;(a,b)&lt;/code&gt; is the first item in the tuple) to be more nuanced with our hole selection:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb12&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb12-1&quot;&gt;&lt;a href=&quot;#cb12-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;ghci&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;map&lt;/span&gt; (peeks flipInstr)&lt;/span&gt;
&lt;span id=&quot;cb12-2&quot;&gt;&lt;a href=&quot;#cb12-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        (holesOf (&lt;span class=&quot;fu&quot;&gt;traverse&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; _1) [(&lt;span class=&quot;dt&quot;&gt;NOP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;ACC&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;4&lt;/span&gt;)])&lt;/span&gt;
&lt;span id=&quot;cb12-3&quot;&gt;&lt;a href=&quot;#cb12-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  [ [(&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;ACC&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;4&lt;/span&gt;)]&lt;/span&gt;
&lt;span id=&quot;cb12-4&quot;&gt;&lt;a href=&quot;#cb12-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , [(&lt;span class=&quot;dt&quot;&gt;NOP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;ACC&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;4&lt;/span&gt;)]&lt;/span&gt;
&lt;span id=&quot;cb12-5&quot;&gt;&lt;a href=&quot;#cb12-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , [(&lt;span class=&quot;dt&quot;&gt;NOP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;ACC&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;NOP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;4&lt;/span&gt;)]&lt;/span&gt;
&lt;span id=&quot;cb12-6&quot;&gt;&lt;a href=&quot;#cb12-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , [(&lt;span class=&quot;dt&quot;&gt;NOP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;ACC&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;NOP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;4&lt;/span&gt;)]&lt;/span&gt;
&lt;span id=&quot;cb12-7&quot;&gt;&lt;a href=&quot;#cb12-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Neat!&lt;/p&gt;
&lt;p&gt;With that we can fully write &lt;code&gt;part2&lt;/code&gt;: for each perturbation, check if there is a loop. If there is a loop, this ain’t it. If there isn’t a loop, then we hit the jackpot: return the last item in our list of seen states, as that’s the last state before termination.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb13&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb13-1&quot;&gt;&lt;a href=&quot;#cb13-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part2 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Command&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;CState&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb13-2&quot;&gt;&lt;a href=&quot;#cb13-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2 cmds0 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; listToMaybe&lt;/span&gt;
&lt;span id=&quot;cb13-3&quot;&gt;&lt;a href=&quot;#cb13-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [ res&lt;/span&gt;
&lt;span id=&quot;cb13-4&quot;&gt;&lt;a href=&quot;#cb13-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; cmds &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; peeks flipInstr &lt;span class=&quot;op&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; holesOf (&lt;span class=&quot;fu&quot;&gt;traverse&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; _1) cmds0&lt;/span&gt;
&lt;span id=&quot;cb13-5&quot;&gt;&lt;a href=&quot;#cb13-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; states &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; iterateMaybe (runCommand cmds) initialCS&lt;/span&gt;
&lt;span id=&quot;cb13-6&quot;&gt;&lt;a href=&quot;#cb13-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , res  &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt; firstRepeatedBy csPtr stats &lt;span class=&quot;kw&quot;&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb13-7&quot;&gt;&lt;a href=&quot;#cb13-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;fu&quot;&gt;last&lt;/span&gt; states]    &lt;span class=&quot;co&quot;&gt;-- loop found&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb13-8&quot;&gt;&lt;a href=&quot;#cb13-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; _  &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; []               &lt;span class=&quot;co&quot;&gt;-- no loop found&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb13-9&quot;&gt;&lt;a href=&quot;#cb13-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In my actual code, I actually use the &lt;code&gt;experiment&lt;/code&gt; function instead of &lt;code&gt;peeks&lt;/code&gt; – it’s like a “peeksM”, in a way:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb14&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb14-1&quot;&gt;&lt;a href=&quot;#cb14-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;peeks      ::&lt;/span&gt; (a &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt;   a) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Pretext&lt;/span&gt; (&lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt;) a a s &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt;   a&lt;/span&gt;
&lt;span id=&quot;cb14-2&quot;&gt;&lt;a href=&quot;#cb14-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;experiment ::&lt;/span&gt; (a &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; f a) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Pretext&lt;/span&gt; (&lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt;) a a s &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; f a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So instead of giving it a &lt;code&gt;Instr -&amp;gt; Instr&lt;/code&gt;, you could give it an &lt;code&gt;Instr -&amp;gt; Maybe Instr&lt;/code&gt;, and “cancel out” any branches that don’t need to be addressed:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb15&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb15-1&quot;&gt;&lt;a href=&quot;#cb15-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;experiment ::&lt;/span&gt; (a &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; a) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Pretext&lt;/span&gt; (&lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt;) a a s &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; a   &lt;span class=&quot;co&quot;&gt;-- in our case&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb15-2&quot;&gt;&lt;a href=&quot;#cb15-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb15-3&quot;&gt;&lt;a href=&quot;#cb15-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;flipInstrs ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Command&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Command&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb15-4&quot;&gt;&lt;a href=&quot;#cb15-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;flipInstrs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb15-5&quot;&gt;&lt;a href=&quot;#cb15-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;NOP&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb15-6&quot;&gt;&lt;a href=&quot;#cb15-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;ACC&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;  &lt;span class=&quot;co&quot;&gt;-- for ACC indices, don&amp;#39;t do anything&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb15-7&quot;&gt;&lt;a href=&quot;#cb15-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb16&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb16-1&quot;&gt;&lt;a href=&quot;#cb16-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;ghci&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;map&lt;/span&gt; (experiment flipInstrs)&lt;/span&gt;
&lt;span id=&quot;cb16-2&quot;&gt;&lt;a href=&quot;#cb16-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        (holesOf (&lt;span class=&quot;fu&quot;&gt;traverse&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; _1) [(&lt;span class=&quot;dt&quot;&gt;NOP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;ACC&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;4&lt;/span&gt;)])&lt;/span&gt;
&lt;span id=&quot;cb16-3&quot;&gt;&lt;a href=&quot;#cb16-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;[ &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; [(&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;ACC&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;4&lt;/span&gt;)]&lt;/span&gt;
&lt;span id=&quot;cb16-4&quot;&gt;&lt;a href=&quot;#cb16-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;, &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb16-5&quot;&gt;&lt;a href=&quot;#cb16-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;, &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; [(&lt;span class=&quot;dt&quot;&gt;NOP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;ACC&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;NOP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;4&lt;/span&gt;)]&lt;/span&gt;
&lt;span id=&quot;cb16-6&quot;&gt;&lt;a href=&quot;#cb16-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;, &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; [(&lt;span class=&quot;dt&quot;&gt;NOP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;ACC&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;JMP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;),(&lt;span class=&quot;dt&quot;&gt;NOP&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;4&lt;/span&gt;)]&lt;/span&gt;
&lt;span id=&quot;cb16-7&quot;&gt;&lt;a href=&quot;#cb16-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb17&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb17-1&quot;&gt;&lt;a href=&quot;#cb17-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part2 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Vector&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Command&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;CState&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb17-2&quot;&gt;&lt;a href=&quot;#cb17-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2 cmds0 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; listToMaybe&lt;/span&gt;
&lt;span id=&quot;cb17-3&quot;&gt;&lt;a href=&quot;#cb17-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [ res&lt;/span&gt;
&lt;span id=&quot;cb17-4&quot;&gt;&lt;a href=&quot;#cb17-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; cmds &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; experiment flipInstr &lt;span class=&quot;op&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; holesOf (&lt;span class=&quot;fu&quot;&gt;traverse&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; _1) cmds0&lt;/span&gt;
&lt;span id=&quot;cb17-5&quot;&gt;&lt;a href=&quot;#cb17-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; states &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; iterateMaybe (runCommand cmds) initialCS&lt;/span&gt;
&lt;span id=&quot;cb17-6&quot;&gt;&lt;a href=&quot;#cb17-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , res  &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt; firstRepeatedBy csPtr stats &lt;span class=&quot;kw&quot;&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb17-7&quot;&gt;&lt;a href=&quot;#cb17-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;fu&quot;&gt;last&lt;/span&gt; states]    &lt;span class=&quot;co&quot;&gt;-- loop found&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb17-8&quot;&gt;&lt;a href=&quot;#cb17-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; _  &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; []               &lt;span class=&quot;co&quot;&gt;-- no loop found&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb17-9&quot;&gt;&lt;a href=&quot;#cb17-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Not a super huge improvement, but maybe more theoretically nice because we can skip over the possible trials where we are permuting an &lt;code&gt;ACC&lt;/code&gt;. By my reckoning, 52% of my input file instructions were ACC instructions, so this small thing actually shaves off a decent amount of time.&lt;/p&gt;
&lt;h3 id=&quot;day-8-benchmarks&quot;&gt;Day 8 Benchmarks&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; Day 08a
benchmarking...
time                 6.243 μs   (6.182 μs .. 6.346 μs)
                     0.998 R²   (0.996 R² .. 1.000 R²)
mean                 6.210 μs   (6.180 μs .. 6.325 μs)
std dev              192.8 ns   (60.82 ns .. 390.0 ns)
variance introduced by outliers: 38% (moderately inflated)

* parsing and formatting times excluded

&amp;gt;&amp;gt; Day 08b
benchmarking...
time                 2.473 ms   (2.298 ms .. 2.654 ms)
                     0.967 R²   (0.953 R² .. 0.984 R²)
mean                 2.485 ms   (2.401 ms .. 2.589 ms)
std dev              298.9 μs   (248.6 μs .. 339.1 μs)
variance introduced by outliers: 74% (severely inflated)

* parsing and formatting times excluded&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md#day-8</link>
      <pubDate>Tue,  8 Dec 2020 01:00:00 EST</pubDate>
    </item>

    <item>
      <title>Day 7</title>
      <description>&lt;h2 id=&quot;day-7&quot;&gt;Day 7&lt;/h2&gt;
&lt;!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day07.md`.  If you want to edit this, edit
that file instead!
--&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://adventofcode.com/2020/day/7&quot;&gt;Prompt&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day07.hs&quot;&gt;Code&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://mstksg.github.io/advent-of-code-2020/src/AOC.Challenge.Day07.html&quot;&gt;Rendered&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day07.md&quot;&gt;Standalone Reflection Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Another AoC staple, a graph search that can be solved with recursive knot tying! The last one I remember off the top of my head was &lt;a href=&quot;https://github.com/mstksg/advent-of-code-2019/blob/master/reflections.md#day-6&quot;&gt;2019 Day 6&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here we can represent a graph as a map of vertices to other vertices, with an edge value:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Graph&lt;/span&gt; v e &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; v (&lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; v e)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Exercise is left to the reader to parse our dataset into a &lt;code&gt;Graph String Int&lt;/code&gt;, a graph of bags to bags with &lt;code&gt;Int&lt;/code&gt; edges.&lt;/p&gt;
&lt;p&gt;Because our map has no cycles, we can take advantage of recursive knot tying to “fold up” all children and sub-children.&lt;/p&gt;
&lt;p&gt;For example, part 1 can be written as:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;allDescendants ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Ord&lt;/span&gt; v &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Graph&lt;/span&gt; v e &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; v (&lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; v)&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;allDescendants gr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; descendantMap&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    descendantMap &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; gr &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;amp;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      M.foldMapWithKey (\v _ &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; S.insert v (M.findWithDefault S.empty v descendantMap))&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-7&quot;&gt;&lt;a href=&quot;#cb2-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- note: (&amp;lt;&amp;amp;&amp;gt;) is flip fmap&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here we “assume” we already have a fully-featured &lt;code&gt;Map v (Set v)&lt;/code&gt; map of vertices to all their descendants, and then build &lt;code&gt;descendantMap&lt;/code&gt; in terms of it. For every vertex &lt;code&gt;v&lt;/code&gt; in the &lt;code&gt;Map v e&lt;/code&gt; directly underneath a given vertex, &lt;code&gt;v&lt;/code&gt; is a descendant, and also all of &lt;code&gt;v&lt;/code&gt;’s descendants (which we find by looking things up in &lt;code&gt;descendantMap&lt;/code&gt;, the map of all descendants).&lt;/p&gt;
&lt;p&gt;Oh, um…oops, this found all the descendants, but we want all of the ancestors. So we have to flip the graph if we want to use this.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;flipGraph ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Ord&lt;/span&gt; v &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Graph&lt;/span&gt; v e &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Graph&lt;/span&gt; v e&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;flipGraph mp &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; M.fromListWith M.union&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [ (m, M.singleton n e)&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; (n, ms) &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; M.toList mp&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , (m, e ) &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; M.toList ms&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ]&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-8&quot;&gt;&lt;a href=&quot;#cb3-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;allAncestors ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Ord&lt;/span&gt; v &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Graph&lt;/span&gt; v e &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; v (&lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; v)&lt;/span&gt;
&lt;span id=&quot;cb3-9&quot;&gt;&lt;a href=&quot;#cb3-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;allAncestors &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; allDescendants &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; flipGraph&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And so that leaves Part 1 as:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part1 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Graph&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part1 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; M.lookup &lt;span class=&quot;st&quot;&gt;&amp;quot;shiny gold&amp;quot;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; allAncestors&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Part 2 we can do a similar way, by “assuming” we have a map of all vertices to their “usage count”, and looking things up to build it:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;usageCounts ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Ord&lt;/span&gt; v &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Graph&lt;/span&gt; v &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; v &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;usageCounts gr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; usageMap&lt;/span&gt;
&lt;span id=&quot;cb5-3&quot;&gt;&lt;a href=&quot;#cb5-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-4&quot;&gt;&lt;a href=&quot;#cb5-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    usageMap &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; gr &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;amp;&amp;gt;&lt;/span&gt; \neighbors &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;sum&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-5&quot;&gt;&lt;a href=&quot;#cb5-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      [ n &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt; (M.findWithDefault &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; v usageMap &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb5-6&quot;&gt;&lt;a href=&quot;#cb5-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; (v, n) &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; M.toList neighbors&lt;/span&gt;
&lt;span id=&quot;cb5-7&quot;&gt;&lt;a href=&quot;#cb5-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So to find the total usage of each bag, we look under each &lt;code&gt;(v, Int)&lt;/code&gt; pair in the &lt;code&gt;Map v Int&lt;/code&gt; underneath a given vertex, look up the usage of that &lt;code&gt;v&lt;/code&gt; (by looking it up in &lt;code&gt;usageMap&lt;/code&gt;), add 1 (because the bag itself is used), and multiply by &lt;code&gt;n&lt;/code&gt;, the number of times the full contents of the bag is used.&lt;/p&gt;
&lt;p&gt;And so Part 2 is:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb6&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb6-1&quot;&gt;&lt;a href=&quot;#cb6-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part2 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Graph&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-2&quot;&gt;&lt;a href=&quot;#cb6-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; M.lookup &lt;span class=&quot;st&quot;&gt;&amp;quot;shiny gold&amp;quot;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; usageCounts&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If we stare at the two implementations, we note that both are pretty much the same overall structure: we are accumulating some sort of fold over all descendants of a given node. If we “outsource” this accumulation as a monoidal one (for part 1, it’s &lt;code&gt;Set&lt;/code&gt; union, and for part 2, it’s &lt;code&gt;Sum Int&lt;/code&gt; addition), we can needlessly hyper-generalize this to fold over any &lt;code&gt;Monoid&lt;/code&gt; instance.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb7&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb7-1&quot;&gt;&lt;a href=&quot;#cb7-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | Recursively fold up a monoid value for each vertex and all of its&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-2&quot;&gt;&lt;a href=&quot;#cb7-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- children&amp;#39;s monoid values.  You can transform the value in-transit before it&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-3&quot;&gt;&lt;a href=&quot;#cb7-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- is accumulated if you want.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-4&quot;&gt;&lt;a href=&quot;#cb7-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;foldMapGraph&lt;/span&gt;
&lt;span id=&quot;cb7-5&quot;&gt;&lt;a href=&quot;#cb7-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Ord&lt;/span&gt; v, &lt;span class=&quot;dt&quot;&gt;Monoid&lt;/span&gt; m)&lt;/span&gt;
&lt;span id=&quot;cb7-6&quot;&gt;&lt;a href=&quot;#cb7-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; (v &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; m)         &lt;span class=&quot;co&quot;&gt;-- ^ embed the vertex&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-7&quot;&gt;&lt;a href=&quot;#cb7-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (e &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; m &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; m)    &lt;span class=&quot;co&quot;&gt;-- ^ transform with edge before it is accumulated&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-8&quot;&gt;&lt;a href=&quot;#cb7-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Graph&lt;/span&gt; v e&lt;/span&gt;
&lt;span id=&quot;cb7-9&quot;&gt;&lt;a href=&quot;#cb7-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; v m&lt;/span&gt;
&lt;span id=&quot;cb7-10&quot;&gt;&lt;a href=&quot;#cb7-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;foldMapGraph f g gr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; res&lt;/span&gt;
&lt;span id=&quot;cb7-11&quot;&gt;&lt;a href=&quot;#cb7-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-12&quot;&gt;&lt;a href=&quot;#cb7-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    res &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; gr &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;amp;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-13&quot;&gt;&lt;a href=&quot;#cb7-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      M.foldMapWithKey (\s v &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; f s &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;foldMap&lt;/span&gt; (g v) (M.lookup s res))&lt;/span&gt;
&lt;span id=&quot;cb7-14&quot;&gt;&lt;a href=&quot;#cb7-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-15&quot;&gt;&lt;a href=&quot;#cb7-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;allDescendants ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Ord&lt;/span&gt; v &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Graph&lt;/span&gt; v e &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; v (&lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; v)&lt;/span&gt;
&lt;span id=&quot;cb7-16&quot;&gt;&lt;a href=&quot;#cb7-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;allDescendants &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; foldMapGraph&lt;/span&gt;
&lt;span id=&quot;cb7-17&quot;&gt;&lt;a href=&quot;#cb7-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    S.singleton     &lt;span class=&quot;co&quot;&gt;-- the node is embedded as itself&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-18&quot;&gt;&lt;a href=&quot;#cb7-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    (\_ &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;id&lt;/span&gt;)      &lt;span class=&quot;co&quot;&gt;-- ignore the edge&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-19&quot;&gt;&lt;a href=&quot;#cb7-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-20&quot;&gt;&lt;a href=&quot;#cb7-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;usageCounts ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Ord&lt;/span&gt; v &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Graph&lt;/span&gt; v &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Map&lt;/span&gt; v (&lt;span class=&quot;dt&quot;&gt;Sum&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb7-21&quot;&gt;&lt;a href=&quot;#cb7-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;usageCounts &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; foldMapGraph&lt;/span&gt;
&lt;span id=&quot;cb7-22&quot;&gt;&lt;a href=&quot;#cb7-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    (&lt;span class=&quot;fu&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;)                   &lt;span class=&quot;co&quot;&gt;-- ignore the nodes&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-23&quot;&gt;&lt;a href=&quot;#cb7-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    (\n x &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Sum&lt;/span&gt; n &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt; (x &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;))   &lt;span class=&quot;co&quot;&gt;-- the edge multiplies the accumulator plus one&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That’s the curse of Haskell, I guess? If you write these things you can’t help but notice the common patterns, and you somehow wind up trying to figure out the higher-order function that can abstract over them, even though you know you don’t need to :)&lt;/p&gt;
&lt;h3 id=&quot;day-7-benchmarks&quot;&gt;Day 7 Benchmarks&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; Day 07a
benchmarking...
time                 2.423 ms   (2.265 ms .. 2.631 ms)
                     0.980 R²   (0.967 R² .. 1.000 R²)
mean                 2.271 ms   (2.245 ms .. 2.334 ms)
std dev              136.8 μs   (48.17 μs .. 231.7 μs)
variance introduced by outliers: 42% (moderately inflated)

* parsing and formatting times excluded

&amp;gt;&amp;gt; Day 07b
benchmarking...
time                 12.11 μs   (11.77 μs .. 12.51 μs)
                     0.991 R²   (0.987 R² .. 0.995 R²)
mean                 12.23 μs   (11.88 μs .. 12.69 μs)
std dev              1.266 μs   (913.5 ns .. 1.695 μs)
variance introduced by outliers: 87% (severely inflated)

* parsing and formatting times excluded&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md#day-7</link>
      <pubDate>Mon,  7 Dec 2020 01:00:00 EST</pubDate>
    </item>

    <item>
      <title>Day 6</title>
      <description>&lt;h2 id=&quot;day-6&quot;&gt;Day 6&lt;/h2&gt;
&lt;!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day06.md`.  If you want to edit this, edit
that file instead!
--&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://adventofcode.com/2020/day/6&quot;&gt;Prompt&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day06.hs&quot;&gt;Code&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://mstksg.github.io/advent-of-code-2020/src/AOC.Challenge.Day06.html&quot;&gt;Rendered&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day06.md&quot;&gt;Standalone Reflection Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Another day that is fairly straightforward in Haskell, I feel! But in other languages that support functional approaches, it should be straightforward as well.&lt;/p&gt;
&lt;p&gt;The answer involves lists of groups of responses:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt;           &lt;span class=&quot;dt&quot;&gt;Data.List.NonEmpty&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt;           &lt;span class=&quot;dt&quot;&gt;Data.Set&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;qualified&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Data.List.NonEmpty&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;NE&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;qualified&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Data.Set&lt;/span&gt;           &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;S&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Response&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Char&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Group&lt;/span&gt;    &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;NonEmpty&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Response&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-8&quot;&gt;&lt;a href=&quot;#cb1-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-9&quot;&gt;&lt;a href=&quot;#cb1-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;parseAnswers ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Char&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Group&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb1-10&quot;&gt;&lt;a href=&quot;#cb1-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;parseAnswers &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; mapMaybe ((&lt;span class=&quot;fu&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;fmap&lt;/span&gt;) S.fromList &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; NE.nonEmpty &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;lines&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb1-11&quot;&gt;&lt;a href=&quot;#cb1-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;             &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; splitOn &lt;span class=&quot;st&quot;&gt;&amp;quot;\n\n&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And now we just need to decide how to aggregate each group. For part 1, this requires a set union between every &lt;code&gt;Response&lt;/code&gt; in a &lt;code&gt;Group&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part1 ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Group&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part1 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;map&lt;/span&gt; (S.size &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;foldr1&lt;/span&gt; S.union)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;(&lt;code&gt;foldr1&lt;/code&gt; here is safe because we have a non-empty container)&lt;/p&gt;
&lt;p&gt;And for part 2, this requires a set intersection between every &lt;code&gt;Response&lt;/code&gt; in a &lt;code&gt;Group&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part2 ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Group&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;map&lt;/span&gt; (S.size &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;foldr1&lt;/span&gt; S.intersection)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That’s it!&lt;/p&gt;
&lt;h3 id=&quot;day-6-benchmarks&quot;&gt;Day 6 Benchmarks&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; Day 06a
benchmarking...
time                 124.2 μs   (122.7 μs .. 127.3 μs)
                     0.990 R²   (0.970 R² .. 1.000 R²)
mean                 125.7 μs   (123.1 μs .. 130.8 μs)
std dev              13.18 μs   (4.807 μs .. 23.01 μs)
variance introduced by outliers: 82% (severely inflated)

* parsing and formatting times excluded

&amp;gt;&amp;gt; Day 06b
benchmarking...
time                 124.8 μs   (123.9 μs .. 126.4 μs)
                     0.997 R²   (0.991 R² .. 1.000 R²)
mean                 125.4 μs   (124.1 μs .. 127.8 μs)
std dev              6.333 μs   (790.0 ns .. 11.65 μs)
variance introduced by outliers: 51% (severely inflated)

* parsing and formatting times excluded&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md#day-6</link>
      <pubDate>Sun,  6 Dec 2020 01:00:00 EST</pubDate>
    </item>

    <item>
      <title>Day 5</title>
      <description>&lt;h2 id=&quot;day-5&quot;&gt;Day 5&lt;/h2&gt;
&lt;!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day05.md`.  If you want to edit this, edit
that file instead!
--&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://adventofcode.com/2020/day/5&quot;&gt;Prompt&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day05.hs&quot;&gt;Code&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://mstksg.github.io/advent-of-code-2020/src/AOC.Challenge.Day05.html&quot;&gt;Rendered&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day05.md&quot;&gt;Standalone Reflection Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So, compared to yesterday’s, this was decently chill :)&lt;/p&gt;
&lt;p&gt;The main insight here probably is that the puzzle is just describing that the seat ID’s are straight up binary notation for numerals, with F/L representing what is traditionally 0, and B/R representing what is traditionally 1. So we can use any of our binary parsers from the standard libraries, or we can just directly pull it into binary.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;seatId ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;seatId &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; foldl&amp;#39; iGuessWe&amp;#39;reDoingThis &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    iGuessWe&amp;#39;reDoingThis n &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;ch&quot;&gt;&amp;#39;B&amp;#39;&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;n&lt;span class=&quot;op&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;ch&quot;&gt;&amp;#39;R&amp;#39;&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;n&lt;span class=&quot;op&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      _   &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;n&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A nice one-pass way to find the missing seat ID is to realize that if we sum all the numbers from min to max, and sum all of our lists’s seat id’s, then the difference is the missing number. Luckily there’s a nice closed-form solution for the sum of all numbers in a given range (the sum of numbers from &lt;code&gt;a&lt;/code&gt; to &lt;code&gt;b&lt;/code&gt; is &lt;code&gt;b*(b+1)`div`2 - a*(a-1)`div`2&lt;/code&gt;), so we can do all of this in a single pass using the &lt;em&gt;&lt;a href=&quot;https://hackage.haskell.org/package/foldl&quot;&gt;foldl&lt;/a&gt;&lt;/em&gt; library&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;{-# LANGUAGE ApplicativeDo #-}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;qualified&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Control.Foldl&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;F&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;findHole ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;F.Fold&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;findHole &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    mn &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; F.minimum&lt;/span&gt;
&lt;span id=&quot;cb2-7&quot;&gt;&lt;a href=&quot;#cb2-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    mx &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; F.maximum&lt;/span&gt;
&lt;span id=&quot;cb2-8&quot;&gt;&lt;a href=&quot;#cb2-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    sm &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; F.sum&lt;/span&gt;
&lt;span id=&quot;cb2-9&quot;&gt;&lt;a href=&quot;#cb2-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-10&quot;&gt;&lt;a href=&quot;#cb2-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      missingItem &lt;span class=&quot;op&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; mn &lt;span class=&quot;op&quot;&gt;&amp;lt;*&amp;gt;&lt;/span&gt; mx &lt;span class=&quot;op&quot;&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; sm&lt;/span&gt;
&lt;span id=&quot;cb2-11&quot;&gt;&lt;a href=&quot;#cb2-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-12&quot;&gt;&lt;a href=&quot;#cb2-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    missingItem mn mx sm &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; totalSum &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt; sm&lt;/span&gt;
&lt;span id=&quot;cb2-13&quot;&gt;&lt;a href=&quot;#cb2-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-14&quot;&gt;&lt;a href=&quot;#cb2-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        totalSum &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; mx&lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;(mx&lt;span class=&quot;op&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;)&lt;span class=&quot;ot&quot;&gt;`div`&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt; mn&lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;(mn&lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;)&lt;span class=&quot;ot&quot;&gt;`div`&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A &lt;code&gt;F.Fold Int (Maybe Int)&lt;/code&gt; folds a list of &lt;code&gt;Int&lt;/code&gt;s into a &lt;code&gt;Maybe Int&lt;/code&gt;. You can run it with &lt;code&gt;F.fold :: F.Fold a b -&amp;gt; [a] -&amp;gt; b&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I really like the &lt;em&gt;foldl&lt;/em&gt; library because it lets you build a complex single-pass fold by combining multiple simple single-pass folds (like &lt;code&gt;F.minimum&lt;/code&gt;, &lt;code&gt;F.maximum&lt;/code&gt;, &lt;code&gt;F.sum&lt;/code&gt;) using an Applicative interface. We need to do a bit of wrangling with the &lt;code&gt;Maybe&lt;/code&gt;s because &lt;code&gt;F.minimum&lt;/code&gt; and &lt;code&gt;F.maximum&lt;/code&gt; each return &lt;code&gt;Maybe Int&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;And that’s more or less it! We can actually represent the entire thing as a fold if we use &lt;code&gt;F.premap&lt;/code&gt;, to pre-map a fold…&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;F.premap&lt;span class=&quot;ot&quot;&gt;                 ::&lt;/span&gt; (c &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; a) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;F.Fold&lt;/span&gt; a b &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;F.Fold&lt;/span&gt; c b&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- &amp;quot;pre-apply&amp;quot; `setId` so we fold over a string instead&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;F.premap seatId&lt;span class=&quot;ot&quot;&gt; findHole ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;F.Fold&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And…that’s enough to do it all in a single pass!&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part1 ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part1 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; F.fold &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; F.premap seatId F.maximum&lt;/span&gt;
&lt;span id=&quot;cb4-3&quot;&gt;&lt;a href=&quot;#cb4-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-4&quot;&gt;&lt;a href=&quot;#cb4-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part2 ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-5&quot;&gt;&lt;a href=&quot;#cb4-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; F.fold &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; F.premap seatId findHole&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Bonus: I was tipped off that the 3rd from last digit of F/L are 1, while the same digit of B/R are 0:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;ghci&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;.&amp;amp;.&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; (&lt;span class=&quot;ot&quot;&gt;`shiftR`&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;ord&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;FLBR&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;[&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So we can actually use this for &lt;code&gt;seatId&lt;/code&gt; to get a slight speed boost and help out the branch predictor maybe:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb6&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb6-1&quot;&gt;&lt;a href=&quot;#cb6-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Data.Bits&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-2&quot;&gt;&lt;a href=&quot;#cb6-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-3&quot;&gt;&lt;a href=&quot;#cb6-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;seatId ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-4&quot;&gt;&lt;a href=&quot;#cb6-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;seatId &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; foldl&amp;#39; iGuessWe&amp;#39;reDoingThis &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-5&quot;&gt;&lt;a href=&quot;#cb6-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-6&quot;&gt;&lt;a href=&quot;#cb6-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    iGuessWe&amp;#39;reDoingThis n c &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-7&quot;&gt;&lt;a href=&quot;#cb6-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt; n &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; (complement (&lt;span class=&quot;fu&quot;&gt;ord&lt;/span&gt; c) &lt;span class=&quot;ot&quot;&gt;`shiftR`&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;.&amp;amp;.&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;day-5-benchmarks&quot;&gt;Day 5 Benchmarks&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; Day 05a
benchmarking...
time                 17.30 μs   (17.28 μs .. 17.35 μs)
                     1.000 R²   (1.000 R² .. 1.000 R²)
mean                 17.32 μs   (17.30 μs .. 17.37 μs)
std dev              89.27 ns   (48.81 ns .. 150.8 ns)

* parsing and formatting times excluded

&amp;gt;&amp;gt; Day 05b
benchmarking...
time                 18.84 μs   (18.82 μs .. 18.85 μs)
                     1.000 R²   (1.000 R² .. 1.000 R²)
mean                 18.84 μs   (18.83 μs .. 18.86 μs)
std dev              56.33 ns   (44.68 ns .. 77.97 ns)

* parsing and formatting times excluded&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md#day-5</link>
      <pubDate>Sat,  5 Dec 2020 01:00:00 EST</pubDate>
    </item>

    <item>
      <title>Day 4</title>
      <description>&lt;h2 id=&quot;day-4&quot;&gt;Day 4&lt;/h2&gt;
&lt;!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day04.md`.  If you want to edit this, edit
that file instead!
--&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://adventofcode.com/2020/day/4&quot;&gt;Prompt&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day04.hs&quot;&gt;Code&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://mstksg.github.io/advent-of-code-2020/src/AOC.Challenge.Day04.html&quot;&gt;Rendered&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day04.md&quot;&gt;Standalone Reflection Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I almost hit the leaderboard today, but hit the 1 minute timeout because I didn’t read carefully enough to treat &lt;code&gt;cid&lt;/code&gt; as optional ;_;&lt;/p&gt;
&lt;p&gt;Ah well, that’s life!&lt;/p&gt;
&lt;p&gt;Anyway, there are a lot of great Haskell solutions out there involving parser combinators and validation of different fields, stuff like that. My original solution parsed a map of fields to values, and then validated those values according to their keys.&lt;/p&gt;
&lt;p&gt;But taking a step back from it all, I thought it would be a nice opportunity to try out the principal of &lt;a href=&quot;https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/&quot;&gt;Parse, Don’t Validate&lt;/a&gt; and see if I can take it its extremes! And implementing this in a nice way lead me also to refinement types with the &lt;em&gt;&lt;a href=&quot;https://hackage.haskell.org/package/refined&quot;&gt;refined&lt;/a&gt;&lt;/em&gt; library, and also and the &lt;a href=&quot;https://reasonablypolymorphic.com/blog/higher-kinded-data/&quot;&gt;higher-kinded data&lt;/a&gt; pattern, supported by the &lt;em&gt;&lt;a href=&quot;https://hackage.haskell.org/package/barbies&quot;&gt;barbies&lt;/a&gt;&lt;/em&gt; library.&lt;/p&gt;
&lt;p&gt;So, what is “Parse, Don’t Validate”? It means: instead of parsing your data into some structure and then checking if the structure is valid (like my original parse-a-map-then-check-it), try instead to represent your data in a structure where it is &lt;em&gt;imposssible&lt;/em&gt; to represent or create an invalid instance in the first place. And so what was originally “validation” is now simply parsing your data into that correct-by-construction structure.&lt;/p&gt;
&lt;p&gt;This seemed like a good candidate for the &lt;em&gt;&lt;a href=&quot;https://hackage.haskell.org/package/refined&quot;&gt;refined&lt;/a&gt;&lt;/em&gt; library, which gives us data types that are “literally” impossible to construct unless they are in the right shape.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | (a &amp;lt;-&amp;gt; b) will represent the type of an integer between a and b&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;type&lt;/span&gt; a &lt;span class=&quot;op&quot;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; b  &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Refined&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;FromTo&lt;/span&gt; a b) &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | (n ** a) will represent the type of a list of a&amp;#39;s with exactly n elements&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;type&lt;/span&gt; n &lt;span class=&quot;op&quot;&gt;**&lt;/span&gt; a   &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Refined&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;SizeEqualTo&lt;/span&gt; n) [a]&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | These come included in the library&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;refineThrow ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; (a &lt;span class=&quot;op&quot;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; b)&lt;/span&gt;
&lt;span id=&quot;cb1-8&quot;&gt;&lt;a href=&quot;#cb1-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;refineThrow ::&lt;/span&gt; [a] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; (n &lt;span class=&quot;op&quot;&gt;**&lt;/span&gt; a)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Which gives us a good picture for the type of our “correct-by-construction” passport:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Height&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;HCm&lt;/span&gt; (&lt;span class=&quot;dv&quot;&gt;150&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;193&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;HIn&lt;/span&gt; ( &lt;span class=&quot;dv&quot;&gt;59&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;-&amp;gt;&lt;/span&gt;  &lt;span class=&quot;dv&quot;&gt;76&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Eye&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;AMB&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;BLU&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;BRN&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;GRY&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;GRN&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;HZL&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;OTH&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-7&quot;&gt;&lt;a href=&quot;#cb2-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-8&quot;&gt;&lt;a href=&quot;#cb2-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    {&lt;span class=&quot;ot&quot;&gt; pByr ::&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1920&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2002&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-9&quot;&gt;&lt;a href=&quot;#cb2-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pIyr ::&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2010&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2020&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-10&quot;&gt;&lt;a href=&quot;#cb2-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pEyr ::&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2020&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2030&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-11&quot;&gt;&lt;a href=&quot;#cb2-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pHgt ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Height&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-12&quot;&gt;&lt;a href=&quot;#cb2-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pHcl ::&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;**&lt;/span&gt; (&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;15&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb2-13&quot;&gt;&lt;a href=&quot;#cb2-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pEcl ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Eye&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-14&quot;&gt;&lt;a href=&quot;#cb2-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pPid ::&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;**&lt;/span&gt; (&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;9&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb2-15&quot;&gt;&lt;a href=&quot;#cb2-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Et voila! We now have a passport where it is impossible to construct unless you have all the correct components!&lt;/p&gt;
&lt;p&gt;That’s great and all, but…how do we actually parse our data type into this?&lt;/p&gt;
&lt;p&gt;One way that could work is to parse each key-value pair into a &lt;code&gt;Passport&lt;/code&gt; with all fields blank except for the field corresponding to that key-value pair, and then combining those optional-field passports into a “certain” passport.&lt;/p&gt;
&lt;p&gt;So we can imagine:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;PassportMaybe&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;PassportMaybe&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    {&lt;span class=&quot;ot&quot;&gt; pByrMaybe ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;dv&quot;&gt;1920&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2002&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pIyrMaybe ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;dv&quot;&gt;2010&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2020&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pEyrMaybe ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;dv&quot;&gt;2020&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2030&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pHgtMaybe ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Height&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pHclMaybe ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;dv&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;**&lt;/span&gt; (&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;15&lt;/span&gt;))&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pEclMaybe ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Eye&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-8&quot;&gt;&lt;a href=&quot;#cb3-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pPidMaybe ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;dv&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;**&lt;/span&gt; (&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;9&lt;/span&gt;))&lt;/span&gt;
&lt;span id=&quot;cb3-9&quot;&gt;&lt;a href=&quot;#cb3-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;with an appropriate &lt;code&gt;Monoid&lt;/code&gt; instance that merges known fields together, and a function like&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;fromPassportMaybe ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;PassportMaybe&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;that will only work if all the fields are &lt;code&gt;Just&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;And hey, we would also maybe like to keep a collection of all the parsers so we can dispatch them whenever we want…&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;PassportParser&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;PassportParser&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    {&lt;span class=&quot;ot&quot;&gt; pByrParser ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;dv&quot;&gt;1920&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2002&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb5-3&quot;&gt;&lt;a href=&quot;#cb5-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pIyrParser ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;dv&quot;&gt;2010&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2020&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb5-4&quot;&gt;&lt;a href=&quot;#cb5-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pEyrParser ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;dv&quot;&gt;2020&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2030&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb5-5&quot;&gt;&lt;a href=&quot;#cb5-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pHgtParser ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Height&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-6&quot;&gt;&lt;a href=&quot;#cb5-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pHclParser ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;dv&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;**&lt;/span&gt; (&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;15&lt;/span&gt;))&lt;/span&gt;
&lt;span id=&quot;cb5-7&quot;&gt;&lt;a href=&quot;#cb5-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pEclParser ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Eye&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-8&quot;&gt;&lt;a href=&quot;#cb5-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pPidParser ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;dv&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;**&lt;/span&gt; (&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;9&lt;/span&gt;))&lt;/span&gt;
&lt;span id=&quot;cb5-9&quot;&gt;&lt;a href=&quot;#cb5-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And wait a minute … doesn’t part 1 require us to create a passport &lt;em&gt;without&lt;/em&gt; validating the strings? So we also need to create&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb6&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb6-1&quot;&gt;&lt;a href=&quot;#cb6-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;PassportRaw&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;PassportRaw&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-2&quot;&gt;&lt;a href=&quot;#cb6-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    {&lt;span class=&quot;ot&quot;&gt; pByrRaw ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-3&quot;&gt;&lt;a href=&quot;#cb6-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pIyrRaw ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-4&quot;&gt;&lt;a href=&quot;#cb6-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pEyrRaw ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-5&quot;&gt;&lt;a href=&quot;#cb6-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pHgtRaw ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-6&quot;&gt;&lt;a href=&quot;#cb6-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pHclRaw ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-7&quot;&gt;&lt;a href=&quot;#cb6-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pEclRaw ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-8&quot;&gt;&lt;a href=&quot;#cb6-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pPidRaw ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-9&quot;&gt;&lt;a href=&quot;#cb6-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And also&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb7&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb7-1&quot;&gt;&lt;a href=&quot;#cb7-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;PassportRawMaybe&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;PassportRawMaybe&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-2&quot;&gt;&lt;a href=&quot;#cb7-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    {&lt;span class=&quot;ot&quot;&gt; pByrRaw ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-3&quot;&gt;&lt;a href=&quot;#cb7-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pIyrRaw ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-4&quot;&gt;&lt;a href=&quot;#cb7-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pEyrRaw ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-5&quot;&gt;&lt;a href=&quot;#cb7-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pHgtRaw ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-6&quot;&gt;&lt;a href=&quot;#cb7-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pHclRaw ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-7&quot;&gt;&lt;a href=&quot;#cb7-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pEclRaw ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-8&quot;&gt;&lt;a href=&quot;#cb7-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pPidRaw ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-9&quot;&gt;&lt;a href=&quot;#cb7-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;as well, for the accumulation part? Wow, this sounds like a horrible idea!&lt;/p&gt;
&lt;p&gt;Or…does it? What if we try the old &lt;a href=&quot;https://reasonablypolymorphic.com/blog/higher-kinded-data/&quot;&gt;higher-kinded data&lt;/a&gt; trick?&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb8&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb8-1&quot;&gt;&lt;a href=&quot;#cb8-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt; f &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb8-2&quot;&gt;&lt;a href=&quot;#cb8-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    {&lt;span class=&quot;ot&quot;&gt; pByr ::&lt;/span&gt; f (&lt;span class=&quot;dv&quot;&gt;1920&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2002&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb8-3&quot;&gt;&lt;a href=&quot;#cb8-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pIyr ::&lt;/span&gt; f (&lt;span class=&quot;dv&quot;&gt;2010&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2020&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb8-4&quot;&gt;&lt;a href=&quot;#cb8-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pEyr ::&lt;/span&gt; f (&lt;span class=&quot;dv&quot;&gt;2020&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2030&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb8-5&quot;&gt;&lt;a href=&quot;#cb8-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pHgt ::&lt;/span&gt; f &lt;span class=&quot;dt&quot;&gt;Height&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb8-6&quot;&gt;&lt;a href=&quot;#cb8-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pHcl ::&lt;/span&gt; f (&lt;span class=&quot;dv&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;**&lt;/span&gt; (&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;15&lt;/span&gt;))&lt;/span&gt;
&lt;span id=&quot;cb8-7&quot;&gt;&lt;a href=&quot;#cb8-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pEcl ::&lt;/span&gt; f &lt;span class=&quot;dt&quot;&gt;Eye&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb8-8&quot;&gt;&lt;a href=&quot;#cb8-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pPid ::&lt;/span&gt; f (&lt;span class=&quot;dv&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;**&lt;/span&gt; (&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;9&lt;/span&gt;))&lt;/span&gt;
&lt;span id=&quot;cb8-9&quot;&gt;&lt;a href=&quot;#cb8-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    }&lt;/span&gt;
&lt;span id=&quot;cb8-10&quot;&gt;&lt;a href=&quot;#cb8-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;deriving&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Generic&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Neat, huh? We now have a flexible data type that can account for all usage patterns! For example:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb9&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb9-1&quot;&gt;&lt;a href=&quot;#cb9-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | the original&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-2&quot;&gt;&lt;a href=&quot;#cb9-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;FullPassport&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Identity&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-3&quot;&gt;&lt;a href=&quot;#cb9-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-4&quot;&gt;&lt;a href=&quot;#cb9-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | the optional-field&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-5&quot;&gt;&lt;a href=&quot;#cb9-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;PassportMaybe&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-6&quot;&gt;&lt;a href=&quot;#cb9-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-7&quot;&gt;&lt;a href=&quot;#cb9-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | the parser collection&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-8&quot;&gt;&lt;a href=&quot;#cb9-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Parser&lt;/span&gt; a &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Parser&lt;/span&gt; {&lt;span class=&quot;ot&quot;&gt; runParser ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; a }&lt;/span&gt;
&lt;span id=&quot;cb9-9&quot;&gt;&lt;a href=&quot;#cb9-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;PassportParser&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Parser&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-10&quot;&gt;&lt;a href=&quot;#cb9-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-11&quot;&gt;&lt;a href=&quot;#cb9-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | the raw strings&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-12&quot;&gt;&lt;a href=&quot;#cb9-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Const&lt;/span&gt; w a &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Const&lt;/span&gt; {&lt;span class=&quot;ot&quot;&gt; getConst ::&lt;/span&gt; w }&lt;/span&gt;
&lt;span id=&quot;cb9-13&quot;&gt;&lt;a href=&quot;#cb9-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;PassportRaw&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb9-14&quot;&gt;&lt;a href=&quot;#cb9-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-15&quot;&gt;&lt;a href=&quot;#cb9-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt; &lt;span class=&quot;co&quot;&gt;-- | the optional raw strings&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-16&quot;&gt;&lt;a href=&quot;#cb9-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;PassportRaw&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Const&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We get all of our original desired types, all from a single type definition, by swapping out the functor &lt;code&gt;f&lt;/code&gt; we use! And then we can just use the &lt;em&gt;&lt;a href=&quot;https://hackage.haskell.org/package/barbies&quot;&gt;barbies&lt;/a&gt;&lt;/em&gt; library to convert between the different formats. Neat!&lt;/p&gt;
&lt;p&gt;Well, what are we waiting for?&lt;/p&gt;
&lt;p&gt;First, let’s derive all of the instances necessary for our parsing to work, given by the &lt;em&gt;barbies&lt;/em&gt; and &lt;em&gt;one-liner-instances&lt;/em&gt; packages.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb10&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb10-1&quot;&gt;&lt;a href=&quot;#cb10-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;FunctorB&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb10-2&quot;&gt;&lt;a href=&quot;#cb10-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;ApplicativeB&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb10-3&quot;&gt;&lt;a href=&quot;#cb10-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;TraversableB&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb10-4&quot;&gt;&lt;a href=&quot;#cb10-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;ConstraintsB&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb10-5&quot;&gt;&lt;a href=&quot;#cb10-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;deriving&lt;/span&gt; via &lt;span class=&quot;dt&quot;&gt;GMonoid&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt; f) &lt;span class=&quot;kw&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;AllBF&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Semigroup&lt;/span&gt; f &lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Semigroup&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt; f)&lt;/span&gt;
&lt;span id=&quot;cb10-6&quot;&gt;&lt;a href=&quot;#cb10-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;deriving&lt;/span&gt; via &lt;span class=&quot;dt&quot;&gt;GMonoid&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt; f) &lt;span class=&quot;kw&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;AllBF&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Monoid&lt;/span&gt; f &lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Monoid&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt; f)&lt;/span&gt;
&lt;span id=&quot;cb10-7&quot;&gt;&lt;a href=&quot;#cb10-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;AllBF&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Show&lt;/span&gt; f &lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Show&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt; f)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we can write our parsers:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb11&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb11-1&quot;&gt;&lt;a href=&quot;#cb11-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Parser&lt;/span&gt; a &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Parser&lt;/span&gt; {&lt;span class=&quot;ot&quot;&gt; runParser ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; a }&lt;/span&gt;
&lt;span id=&quot;cb11-2&quot;&gt;&lt;a href=&quot;#cb11-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-3&quot;&gt;&lt;a href=&quot;#cb11-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;passportParser ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Parser&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-4&quot;&gt;&lt;a href=&quot;#cb11-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;passportParser &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-5&quot;&gt;&lt;a href=&quot;#cb11-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    { pByr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; refineThrow &lt;span class=&quot;op&quot;&gt;&amp;lt;=&amp;lt;&lt;/span&gt; readMaybe&lt;/span&gt;
&lt;span id=&quot;cb11-6&quot;&gt;&lt;a href=&quot;#cb11-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , pIyr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; refineThrow &lt;span class=&quot;op&quot;&gt;&amp;lt;=&amp;lt;&lt;/span&gt; readMaybe&lt;/span&gt;
&lt;span id=&quot;cb11-7&quot;&gt;&lt;a href=&quot;#cb11-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , pEyr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; refineThrow &lt;span class=&quot;op&quot;&gt;&amp;lt;=&amp;lt;&lt;/span&gt; readMaybe&lt;/span&gt;
&lt;span id=&quot;cb11-8&quot;&gt;&lt;a href=&quot;#cb11-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , pHgt &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; \str &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-9&quot;&gt;&lt;a href=&quot;#cb11-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; (x, u) &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;span&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;isDigit&lt;/span&gt; str&lt;/span&gt;
&lt;span id=&quot;cb11-10&quot;&gt;&lt;a href=&quot;#cb11-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;kw&quot;&gt;in&lt;/span&gt;  &lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt; u &lt;span class=&quot;kw&quot;&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-11&quot;&gt;&lt;a href=&quot;#cb11-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                      &lt;span class=&quot;st&quot;&gt;&amp;quot;cm&amp;quot;&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;HCm&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; refineThrow &lt;span class=&quot;op&quot;&gt;=&amp;lt;&amp;lt;&lt;/span&gt; readMaybe x&lt;/span&gt;
&lt;span id=&quot;cb11-12&quot;&gt;&lt;a href=&quot;#cb11-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                      &lt;span class=&quot;st&quot;&gt;&amp;quot;in&amp;quot;&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;HIn&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; refineThrow &lt;span class=&quot;op&quot;&gt;=&amp;lt;&amp;lt;&lt;/span&gt; readMaybe x&lt;/span&gt;
&lt;span id=&quot;cb11-13&quot;&gt;&lt;a href=&quot;#cb11-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                      _    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-14&quot;&gt;&lt;a href=&quot;#cb11-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , pHcl &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; \&lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-15&quot;&gt;&lt;a href=&quot;#cb11-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;ch&quot;&gt;&amp;#39;#&amp;#39;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;n &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; refineThrow &lt;span class=&quot;op&quot;&gt;=&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;traverse&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;readHex&lt;/span&gt; n&lt;/span&gt;
&lt;span id=&quot;cb11-16&quot;&gt;&lt;a href=&quot;#cb11-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                _     &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-17&quot;&gt;&lt;a href=&quot;#cb11-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , pEcl &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; readMaybe &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;toUpper&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-18&quot;&gt;&lt;a href=&quot;#cb11-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , pPid &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; refineThrow &lt;span class=&quot;op&quot;&gt;&amp;lt;=&amp;lt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;traverse&lt;/span&gt; (refineThrow &lt;span class=&quot;op&quot;&gt;&amp;lt;=&amp;lt;&lt;/span&gt; readMaybe &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; (&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;[]))&lt;/span&gt;
&lt;span id=&quot;cb11-19&quot;&gt;&lt;a href=&quot;#cb11-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    }&lt;/span&gt;
&lt;span id=&quot;cb11-20&quot;&gt;&lt;a href=&quot;#cb11-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-21&quot;&gt;&lt;a href=&quot;#cb11-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;fu&quot;&gt;readHex&lt;/span&gt; c&lt;/span&gt;
&lt;span id=&quot;cb11-22&quot;&gt;&lt;a href=&quot;#cb11-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;isHexDigit&lt;/span&gt; c &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; refineThrow (&lt;span class=&quot;fu&quot;&gt;digitToInt&lt;/span&gt; c)&lt;/span&gt;
&lt;span id=&quot;cb11-23&quot;&gt;&lt;a href=&quot;#cb11-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;otherwise&lt;/span&gt;    &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The usage of &lt;code&gt;refineThrow&lt;/code&gt; means that we use the machinery already defined in the &lt;em&gt;&lt;a href=&quot;https://hackage.haskell.org/package/refined&quot;&gt;refined&lt;/a&gt;&lt;/em&gt; library to automatically check that our data is within the given ranges…no need for manual range checking!&lt;/p&gt;
&lt;p&gt;Now we can load a single &lt;code&gt;key:val&lt;/code&gt; token into a passport that is &lt;em&gt;empty&lt;/em&gt; (all fields are &lt;code&gt;Const Nothing&lt;/code&gt;) &lt;em&gt;except for&lt;/em&gt; the value at the seen key&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb12&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb12-1&quot;&gt;&lt;a href=&quot;#cb12-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | Load a single &amp;quot;key:val&amp;quot; token into a passport&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb12-2&quot;&gt;&lt;a href=&quot;#cb12-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;loadPassportField ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Const&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;))&lt;/span&gt;
&lt;span id=&quot;cb12-3&quot;&gt;&lt;a href=&quot;#cb12-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;loadPassportField str &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt; splitOn &lt;span class=&quot;st&quot;&gt;&amp;quot;:&amp;quot;&lt;/span&gt; str &lt;span class=&quot;kw&quot;&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb12-4&quot;&gt;&lt;a href=&quot;#cb12-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [k,v] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt; k &lt;span class=&quot;kw&quot;&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb12-5&quot;&gt;&lt;a href=&quot;#cb12-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;st&quot;&gt;&amp;quot;byr&amp;quot;&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;mempty&lt;/span&gt; { pByr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Const&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; v) }&lt;/span&gt;
&lt;span id=&quot;cb12-6&quot;&gt;&lt;a href=&quot;#cb12-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;st&quot;&gt;&amp;quot;iyr&amp;quot;&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;mempty&lt;/span&gt; { pIyr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Const&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; v) }&lt;/span&gt;
&lt;span id=&quot;cb12-7&quot;&gt;&lt;a href=&quot;#cb12-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;st&quot;&gt;&amp;quot;eyr&amp;quot;&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;mempty&lt;/span&gt; { pEyr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Const&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; v) }&lt;/span&gt;
&lt;span id=&quot;cb12-8&quot;&gt;&lt;a href=&quot;#cb12-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;st&quot;&gt;&amp;quot;hgt&amp;quot;&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;mempty&lt;/span&gt; { pHgt &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Const&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; v) }&lt;/span&gt;
&lt;span id=&quot;cb12-9&quot;&gt;&lt;a href=&quot;#cb12-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;st&quot;&gt;&amp;quot;hcl&amp;quot;&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;mempty&lt;/span&gt; { pHcl &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Const&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; v) }&lt;/span&gt;
&lt;span id=&quot;cb12-10&quot;&gt;&lt;a href=&quot;#cb12-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;st&quot;&gt;&amp;quot;ecl&amp;quot;&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;mempty&lt;/span&gt; { pEcl &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Const&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; v) }&lt;/span&gt;
&lt;span id=&quot;cb12-11&quot;&gt;&lt;a href=&quot;#cb12-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;st&quot;&gt;&amp;quot;pid&amp;quot;&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;mempty&lt;/span&gt; { pPid &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Const&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; v) }&lt;/span&gt;
&lt;span id=&quot;cb12-12&quot;&gt;&lt;a href=&quot;#cb12-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      _     &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;mempty&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb12-13&quot;&gt;&lt;a href=&quot;#cb12-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    _     &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;mempty&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb13&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb13-1&quot;&gt;&lt;a href=&quot;#cb13-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;ghci&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; loadPassportField &lt;span class=&quot;st&quot;&gt;&amp;quot;eyr:1234&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb13-2&quot;&gt;&lt;a href=&quot;#cb13-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb13-3&quot;&gt;&lt;a href=&quot;#cb13-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  { pByr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb13-4&quot;&gt;&lt;a href=&quot;#cb13-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , pIyr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb13-5&quot;&gt;&lt;a href=&quot;#cb13-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , pEyr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Const&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;1234&amp;quot;&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb13-6&quot;&gt;&lt;a href=&quot;#cb13-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , pHgt &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb13-7&quot;&gt;&lt;a href=&quot;#cb13-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , pHcl &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb13-8&quot;&gt;&lt;a href=&quot;#cb13-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , pEcl &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb13-9&quot;&gt;&lt;a href=&quot;#cb13-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , pPid &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb13-10&quot;&gt;&lt;a href=&quot;#cb13-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we can parse a field in its entirety by using &lt;code&gt;bzipWith&lt;/code&gt; (from &lt;em&gt;barbies&lt;/em&gt;), to “zip together” a &lt;code&gt;Passport Parser&lt;/code&gt; and &lt;code&gt;Passport (Const (Maybe String))&lt;/code&gt; with a given function that tells how to merge the values in any two fields.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb14&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb14-1&quot;&gt;&lt;a href=&quot;#cb14-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;parsePassportField ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb14-2&quot;&gt;&lt;a href=&quot;#cb14-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;parsePassportField &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; bzipWith go passportParser &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; loadPassportField&lt;/span&gt;
&lt;span id=&quot;cb14-3&quot;&gt;&lt;a href=&quot;#cb14-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb14-4&quot;&gt;&lt;a href=&quot;#cb14-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    go p (&lt;span class=&quot;dt&quot;&gt;Const&lt;/span&gt; x) &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; runParser p &lt;span class=&quot;op&quot;&gt;=&amp;lt;&amp;lt;&lt;/span&gt; x&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the above, &lt;code&gt;go&lt;/code&gt; is run between each matching field in the &lt;code&gt;Passport Parser&lt;/code&gt; and the &lt;code&gt;Passport (Const (Maybe String))&lt;/code&gt;, and the overall effect is that each string is run with the appropriate parser for its field.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb15&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb15-1&quot;&gt;&lt;a href=&quot;#cb15-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;ghci&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; parsePassportField &lt;span class=&quot;st&quot;&gt;&amp;quot;eyr:2025&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb15-2&quot;&gt;&lt;a href=&quot;#cb15-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb15-3&quot;&gt;&lt;a href=&quot;#cb15-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  { pByr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb15-4&quot;&gt;&lt;a href=&quot;#cb15-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , pIyr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb15-5&quot;&gt;&lt;a href=&quot;#cb15-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , pEyr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; (refined &lt;span class=&quot;dv&quot;&gt;2025&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb15-6&quot;&gt;&lt;a href=&quot;#cb15-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , pHgt &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb15-7&quot;&gt;&lt;a href=&quot;#cb15-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , pHcl &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb15-8&quot;&gt;&lt;a href=&quot;#cb15-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , pEcl &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb15-9&quot;&gt;&lt;a href=&quot;#cb15-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , pPid &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb15-10&quot;&gt;&lt;a href=&quot;#cb15-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  }&lt;/span&gt;
&lt;span id=&quot;cb15-11&quot;&gt;&lt;a href=&quot;#cb15-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;ghci&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; parsePassportField &lt;span class=&quot;st&quot;&gt;&amp;quot;eyr:2050&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb15-12&quot;&gt;&lt;a href=&quot;#cb15-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb15-13&quot;&gt;&lt;a href=&quot;#cb15-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  { pByr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb15-14&quot;&gt;&lt;a href=&quot;#cb15-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , pIyr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb15-15&quot;&gt;&lt;a href=&quot;#cb15-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , pEyr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb15-16&quot;&gt;&lt;a href=&quot;#cb15-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , pHgt &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb15-17&quot;&gt;&lt;a href=&quot;#cb15-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , pHcl &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb15-18&quot;&gt;&lt;a href=&quot;#cb15-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , pEcl &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb15-19&quot;&gt;&lt;a href=&quot;#cb15-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , pPid &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb15-20&quot;&gt;&lt;a href=&quot;#cb15-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And the way the &lt;code&gt;Monoid&lt;/code&gt; instance works, we can just combine two &lt;code&gt;Passport Maybe&lt;/code&gt;s with &lt;code&gt;&amp;lt;&amp;gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb16&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb16-1&quot;&gt;&lt;a href=&quot;#cb16-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;ghci&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; parsePassportField &lt;span class=&quot;st&quot;&gt;&amp;quot;eyr:2025&amp;quot;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt; parsePassportField &lt;span class=&quot;st&quot;&gt;&amp;quot;ecl:brn&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb16-2&quot;&gt;&lt;a href=&quot;#cb16-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb16-3&quot;&gt;&lt;a href=&quot;#cb16-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  { pByr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb16-4&quot;&gt;&lt;a href=&quot;#cb16-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , pIyr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb16-5&quot;&gt;&lt;a href=&quot;#cb16-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , pEyr &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; (refined &lt;span class=&quot;dv&quot;&gt;2025&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb16-6&quot;&gt;&lt;a href=&quot;#cb16-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , pHgt &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb16-7&quot;&gt;&lt;a href=&quot;#cb16-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , pHcl &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb16-8&quot;&gt;&lt;a href=&quot;#cb16-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , pEcl &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;BRN&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb16-9&quot;&gt;&lt;a href=&quot;#cb16-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  , pPid &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb16-10&quot;&gt;&lt;a href=&quot;#cb16-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Which gives us a nice function to parse a whole passport, with the help of &lt;code&gt;btraverse&lt;/code&gt; to flip a &lt;code&gt;Passport Maybe&lt;/code&gt; into a &lt;code&gt;Maybe (Passport Identity)&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb17&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb17-1&quot;&gt;&lt;a href=&quot;#cb17-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;parsePassport ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Identity&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb17-2&quot;&gt;&lt;a href=&quot;#cb17-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;parsePassport &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; btraverse (&lt;span class=&quot;fu&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Identity&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb17-3&quot;&gt;&lt;a href=&quot;#cb17-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;              &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;foldMap&lt;/span&gt; parsePassportField&lt;/span&gt;
&lt;span id=&quot;cb17-4&quot;&gt;&lt;a href=&quot;#cb17-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;              &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;words&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The result of &lt;code&gt;foldMap parsePassportField . words&lt;/code&gt; is a &lt;code&gt;Passport Maybe&lt;/code&gt;, and &lt;code&gt;btraverse&lt;/code&gt; “pulls out” all of the &lt;code&gt;Just&lt;/code&gt; fields and returns a &lt;code&gt;Passport Identity&lt;/code&gt; if all of the fields are &lt;code&gt;Just&lt;/code&gt;, failing with &lt;code&gt;Nothing&lt;/code&gt; if any of the fields are &lt;code&gt;Nothing&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;And…that’s it for part 2!&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb18&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb18-1&quot;&gt;&lt;a href=&quot;#cb18-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | Get a list of all valid passports.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb18-2&quot;&gt;&lt;a href=&quot;#cb18-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part2 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Identity&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb18-3&quot;&gt;&lt;a href=&quot;#cb18-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; mapMaybe parsePassport &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; splitOn &lt;span class=&quot;st&quot;&gt;&amp;quot;\n\n&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This works because we know that if we have a &lt;code&gt;Passport Identity&lt;/code&gt;, we &lt;em&gt;know&lt;/em&gt; it has to be a valid passport. It’s physically impossible to create one that isn’t valid!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;All hail “Parse, Don’t Validate”!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;And part 1 is a fun diversion: instead of a &lt;code&gt;Passport Identity&lt;/code&gt;, we want to parse into a &lt;code&gt;Passport (Const String)&lt;/code&gt; instead. The mechanics are pretty much the same:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb19&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb19-1&quot;&gt;&lt;a href=&quot;#cb19-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;loadPassport ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;))&lt;/span&gt;
&lt;span id=&quot;cb19-2&quot;&gt;&lt;a href=&quot;#cb19-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;loadPassport &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; btraverse (\(&lt;span class=&quot;dt&quot;&gt;Const&lt;/span&gt; x) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; x)&lt;/span&gt;
&lt;span id=&quot;cb19-3&quot;&gt;&lt;a href=&quot;#cb19-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;             &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;foldMap&lt;/span&gt; loadPassportField&lt;/span&gt;
&lt;span id=&quot;cb19-4&quot;&gt;&lt;a href=&quot;#cb19-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;             &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;words&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The result of &lt;code&gt;foldMap loadPassportField&lt;/code&gt; is a &lt;code&gt;Passport (Const (Maybe String))&lt;/code&gt;, and so &lt;code&gt;btraverse&lt;/code&gt; will pull out all the &lt;code&gt;Just&lt;/code&gt;s again, returning a &lt;code&gt;Passport (Const String)&lt;/code&gt; and failing if any of those values were &lt;code&gt;Nothing&lt;/code&gt;s. Note the sliiight abuse of the &lt;code&gt;Monoid&lt;/code&gt; instance for &lt;code&gt;Maybe&lt;/code&gt;, which combines strings by concatenation. But we’re more concerned about whether or not it is present than the actual contents of the string.&lt;/p&gt;
&lt;p&gt;Anyway, here’s wonderwall.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb20&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb20-1&quot;&gt;&lt;a href=&quot;#cb20-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | Get a list of all complete passports field string values.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb20-2&quot;&gt;&lt;a href=&quot;#cb20-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part1 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Passport&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Const&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;)]&lt;/span&gt;
&lt;span id=&quot;cb20-3&quot;&gt;&lt;a href=&quot;#cb20-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part1 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; mapMaybe loadPassport &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; splitOn &lt;span class=&quot;st&quot;&gt;&amp;quot;\n\n&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;day-4-benchmarks&quot;&gt;Day 4 Benchmarks&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; Day 04a
benchmarking...
time                 1.424 ms   (1.381 ms .. 1.491 ms)
                     0.987 R²   (0.972 R² .. 0.999 R²)
mean                 1.437 ms   (1.410 ms .. 1.496 ms)
std dev              141.4 μs   (52.48 μs .. 241.8 μs)
variance introduced by outliers: 71% (severely inflated)

* parsing and formatting times excluded

&amp;gt;&amp;gt; Day 04b
benchmarking...
time                 4.212 ms   (4.036 ms .. 4.512 ms)
                     0.985 R²   (0.974 R² .. 1.000 R²)
mean                 4.097 ms   (4.039 ms .. 4.222 ms)
std dev              253.3 μs   (50.40 μs .. 438.6 μs)
variance introduced by outliers: 39% (moderately inflated)

* parsing and formatting times excluded&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md#day-4</link>
      <pubDate>Fri,  4 Dec 2020 01:00:00 EST</pubDate>
    </item>

    <item>
      <title>Day 3</title>
      <description>&lt;h2 id=&quot;day-3&quot;&gt;Day 3&lt;/h2&gt;
&lt;!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day03.md`.  If you want to edit this, edit
that file instead!
--&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://adventofcode.com/2020/day/3&quot;&gt;Prompt&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day03.hs&quot;&gt;Code&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://mstksg.github.io/advent-of-code-2020/src/AOC.Challenge.Day03.html&quot;&gt;Rendered&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day03.md&quot;&gt;Standalone Reflection Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Here I’m going to list two methods — one that involves pre-building a set to check if a tree is at a given point, and the other involves just a single direct traversal checking all valid points for trees!&lt;/p&gt;
&lt;p&gt;First of all, I’m going to reveal one of my favorite secrets for parsing 2D ASCII maps!&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;asciiGrid ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IndexedFold&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;) &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Char&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;asciiGrid &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; reindexed swap (lined &lt;span class=&quot;op&quot;&gt;&amp;lt;.&amp;gt;&lt;/span&gt; folded)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This gives you an indexed fold (from the &lt;em&gt;&lt;a href=&quot;https://hackage.haskell.org/package/lens&quot;&gt;lens&lt;/a&gt;&lt;/em&gt; package) iterating over each character in a string, indexed by &lt;code&gt;(x,y)&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;This lets us parse today’s ASCII forest pretty easily into a &lt;code&gt;Set (Int, Int)&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;parseForest ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;parseForest &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; ifoldMapOf asciiGrid &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; \xy c &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt; c &lt;span class=&quot;kw&quot;&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ch&quot;&gt;&amp;#39;#&amp;#39;&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; S.singleton xy&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    _   &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; S.empty&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This folds over the input string, giving us the &lt;code&gt;(x,y)&lt;/code&gt; index and the character at that index. We accumulate with a monoid, so we can use a &lt;code&gt;Set (Int, Int)&lt;/code&gt; to collect the coordinates where the character is &lt;code&gt;&#39;#&#39;&lt;/code&gt; and ignore all other coordinates.&lt;/p&gt;
&lt;p&gt;Admittedly, &lt;code&gt;Set (Int, Int)&lt;/code&gt; is sliiiightly overkill, since you could probably use &lt;code&gt;Vector (Vector Bool)&lt;/code&gt; or something with &lt;code&gt;V.fromList . map (V.fromList . (== &#39;#&#39;)) . lines&lt;/code&gt;, and check for membership with double-indexing. But I was bracing for something a little more demanding, like having to iterate over all the trees or something. Still, sparse grids are usually my go-to data structure for Advent of Code ASCII maps.&lt;/p&gt;
&lt;p&gt;Anyway, now we need to be able to traverse the ray. We can write a function to check all points in our line, given the slope (delta x and delta y):&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;countTrue ::&lt;/span&gt; (a &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Bool&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [a] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;countTrue p &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;filter&lt;/span&gt; p&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;countLine ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;countLine dx dy pts &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; countTrue valid [&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;322&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    valid i &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; (x, y) &lt;span class=&quot;ot&quot;&gt;`S.member`&lt;/span&gt; pts&lt;/span&gt;
&lt;span id=&quot;cb3-8&quot;&gt;&lt;a href=&quot;#cb3-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-9&quot;&gt;&lt;a href=&quot;#cb3-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        x &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; (i &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt; dx) &lt;span class=&quot;ot&quot;&gt;`mod`&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;31&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-10&quot;&gt;&lt;a href=&quot;#cb3-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        y &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; i &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt; dy&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And there we go :)&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part1 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part1 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; countLine &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-3&quot;&gt;&lt;a href=&quot;#cb4-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-4&quot;&gt;&lt;a href=&quot;#cb4-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part2 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Set&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-5&quot;&gt;&lt;a href=&quot;#cb4-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2 pts &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;product&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-6&quot;&gt;&lt;a href=&quot;#cb4-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [ countLine &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-7&quot;&gt;&lt;a href=&quot;#cb4-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , countLine &lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-8&quot;&gt;&lt;a href=&quot;#cb4-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , countLine &lt;span class=&quot;dv&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-9&quot;&gt;&lt;a href=&quot;#cb4-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , countLine &lt;span class=&quot;dv&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-10&quot;&gt;&lt;a href=&quot;#cb4-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , countLine &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-11&quot;&gt;&lt;a href=&quot;#cb4-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ] &lt;span class=&quot;op&quot;&gt;&amp;lt;*&amp;gt;&lt;/span&gt; [pts]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that this checks a lot of points we wouldn’t normally need to check: any y points out of range (322) for &lt;code&gt;dy &amp;gt; 1&lt;/code&gt;. We could add a minor optimization to only check for membership if &lt;code&gt;y&lt;/code&gt; is in range, but because our check is a set lookup, it isn’t too inefficient and it always returns &lt;code&gt;False&lt;/code&gt; anyway. So a small price to pay for slightly more clean code :)&lt;/p&gt;
&lt;p&gt;So this was the solution I used to submit my original answers, but I started thinking the possible optimizations. I realized that we could actually do the whole thing in a single traversal…since we could associate each of the points with coordinates as we go along, and reject any coordinates that would not be on the line!&lt;/p&gt;
&lt;p&gt;We can write a function to check if a coordinate is on a line:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;validCoord&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;      &lt;span class=&quot;co&quot;&gt;-- ^ dx&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-3&quot;&gt;&lt;a href=&quot;#cb5-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;      &lt;span class=&quot;co&quot;&gt;-- ^ dy&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-4&quot;&gt;&lt;a href=&quot;#cb5-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; (&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;, &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb5-5&quot;&gt;&lt;a href=&quot;#cb5-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Bool&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-6&quot;&gt;&lt;a href=&quot;#cb5-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;validCoord dx dy &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; \(x,y) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-7&quot;&gt;&lt;a href=&quot;#cb5-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; (i,r) &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; y &lt;span class=&quot;ot&quot;&gt;`divMod`&lt;/span&gt; dy&lt;/span&gt;
&lt;span id=&quot;cb5-8&quot;&gt;&lt;a href=&quot;#cb5-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;in&lt;/span&gt;  r &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; (dx &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt; i) &lt;span class=&quot;ot&quot;&gt;`mod`&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;31&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; x&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And now we can use &lt;code&gt;lengthOf&lt;/code&gt; with the coordinate fold up there, which counts how many traversed items match our fold:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb6&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb6-1&quot;&gt;&lt;a href=&quot;#cb6-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;countLineDirect ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-2&quot;&gt;&lt;a href=&quot;#cb6-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;countLineDirect dx dy &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; lengthOf (asciiGrid &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; ifiltered tree)&lt;/span&gt;
&lt;span id=&quot;cb6-3&quot;&gt;&lt;a href=&quot;#cb6-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-4&quot;&gt;&lt;a href=&quot;#cb6-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    checkCoord &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; validCoord dx dy&lt;/span&gt;
&lt;span id=&quot;cb6-5&quot;&gt;&lt;a href=&quot;#cb6-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    tree pt c &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; c &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;&amp;#39;#&amp;#39;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; checkCoord pt&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And this gives the same answer, with the same interface!&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb7&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb7-1&quot;&gt;&lt;a href=&quot;#cb7-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part1 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-2&quot;&gt;&lt;a href=&quot;#cb7-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part1 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; countLineDirect &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-3&quot;&gt;&lt;a href=&quot;#cb7-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-4&quot;&gt;&lt;a href=&quot;#cb7-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part2 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-5&quot;&gt;&lt;a href=&quot;#cb7-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2 pts &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;product&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-6&quot;&gt;&lt;a href=&quot;#cb7-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [ countLineDirect &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-7&quot;&gt;&lt;a href=&quot;#cb7-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , countLineDirect &lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-8&quot;&gt;&lt;a href=&quot;#cb7-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , countLineDirect &lt;span class=&quot;dv&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-9&quot;&gt;&lt;a href=&quot;#cb7-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , countLineDirect &lt;span class=&quot;dv&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-10&quot;&gt;&lt;a href=&quot;#cb7-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    , countLineDirect &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-11&quot;&gt;&lt;a href=&quot;#cb7-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ] &lt;span class=&quot;op&quot;&gt;&amp;lt;*&amp;gt;&lt;/span&gt; [pts]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Is the direct single-traversal method any faster?&lt;/p&gt;
&lt;p&gt;Well, it’s complicated, slightly. There’s a clear benefit in the pre-built set method for part 2, since we essentially build up an efficient structure (&lt;code&gt;Set&lt;/code&gt;) that we re-use for all five lines. We get the most benefit if we build the set once and re-use it many times, since we only have to do the actual coordinate folding once.&lt;/p&gt;
&lt;p&gt;So, directly comparing the two methods, we see the single-traversal as faster for part 1 and slower for part 2.&lt;/p&gt;
&lt;p&gt;However, we can do a little better for the single-traversal method. As it turns out, the lens indexed fold is kind of slow. I was able to write the single-traversal one a much faster way by directly just using &lt;code&gt;zip [0..]&lt;/code&gt;, without losing too much readability. And with this &lt;em&gt;direct&lt;/em&gt; single traversal and computing the indices manually, we get a much faster time for part 1 (about ten times faster!) and a slightly faster time for part 2 (about 5 times faster). The benchmarks for this optimized version are what is presented below.&lt;/p&gt;
&lt;h3 id=&quot;day-3-benchmarks&quot;&gt;Day 3 Benchmarks&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; Day 03a
benchmarking...
time                 241.3 μs   (239.5 μs .. 244.2 μs)
                     0.998 R²   (0.996 R² .. 1.000 R²)
mean                 241.8 μs   (239.8 μs .. 245.7 μs)
std dev              8.800 μs   (3.364 μs .. 14.91 μs)
variance introduced by outliers: 33% (moderately inflated)

* parsing and formatting times excluded

&amp;gt;&amp;gt; Day 03b
benchmarking...
time                 1.155 ms   (1.124 ms .. 1.197 ms)
                     0.986 R²   (0.967 R² .. 0.997 R²)
mean                 1.235 ms   (1.156 ms .. 1.496 ms)
std dev              434.4 μs   (61.26 μs .. 910.6 μs)
variance introduced by outliers: 98% (severely inflated)

* parsing and formatting times excluded&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md#day-3</link>
      <pubDate>Thu,  3 Dec 2020 01:00:00 EST</pubDate>
    </item>

    <item>
      <title>Day 2</title>
      <description>&lt;h2 id=&quot;day-2&quot;&gt;Day 2&lt;/h2&gt;
&lt;!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day02.md`.  If you want to edit this, edit
that file instead!
--&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://adventofcode.com/2020/day/2&quot;&gt;Prompt&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day02.hs&quot;&gt;Code&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://mstksg.github.io/advent-of-code-2020/src/AOC.Challenge.Day02.html&quot;&gt;Rendered&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day02.md&quot;&gt;Standalone Reflection Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Day 2, not too bad for Haskell either :)&lt;/p&gt;
&lt;p&gt;There is some fun in parsing here:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Policy&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;P&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    {&lt;span class=&quot;ot&quot;&gt; pIx1  ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pIx2  ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pChar ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Char&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ,&lt;span class=&quot;ot&quot;&gt; pPass ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    }&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-8&quot;&gt;&lt;a href=&quot;#cb1-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;parsePolicy ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Policy&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-9&quot;&gt;&lt;a href=&quot;#cb1-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;parsePolicy str &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-10&quot;&gt;&lt;a href=&quot;#cb1-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [ixes,c&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;_,pwd] &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;words&lt;/span&gt; str&lt;/span&gt;
&lt;span id=&quot;cb1-11&quot;&gt;&lt;a href=&quot;#cb1-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [ix1,ix2]      &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; splitOn &lt;span class=&quot;st&quot;&gt;&amp;quot;-&amp;quot;&lt;/span&gt; ixes&lt;/span&gt;
&lt;span id=&quot;cb1-12&quot;&gt;&lt;a href=&quot;#cb1-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;P&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; readMaybe ix1&lt;/span&gt;
&lt;span id=&quot;cb1-13&quot;&gt;&lt;a href=&quot;#cb1-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;&amp;lt;*&amp;gt;&lt;/span&gt; readMaybe ix2&lt;/span&gt;
&lt;span id=&quot;cb1-14&quot;&gt;&lt;a href=&quot;#cb1-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; c&lt;/span&gt;
&lt;span id=&quot;cb1-15&quot;&gt;&lt;a href=&quot;#cb1-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; pwd&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I used one of my more regular do-block tricks: if you pattern match in a &lt;code&gt;Maybe&lt;/code&gt; do-block, then failed pattern matches will turn the whole thing into a &lt;code&gt;Nothing&lt;/code&gt;. So if any of those list literal pattern matches failed, the whole block will return &lt;code&gt;Nothing&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In any case, we just need to write a function to check if a given policy is valid for either criteria:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;countTrue ::&lt;/span&gt; (a &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Bool&lt;/span&gt;) &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; [a] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;countTrue p &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;filter&lt;/span&gt; p&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;validate1 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Policy&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Bool&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;validate1 &lt;span class=&quot;dt&quot;&gt;P&lt;/span&gt;{&lt;span class=&quot;op&quot;&gt;..&lt;/span&gt;} &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; n &lt;span class=&quot;op&quot;&gt;&amp;gt;=&lt;/span&gt; pIx1 &lt;span class=&quot;op&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; n &lt;span class=&quot;op&quot;&gt;&amp;lt;=&lt;/span&gt; pIx2&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-7&quot;&gt;&lt;a href=&quot;#cb2-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    n &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; countTrue (&lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; pChar) pPass&lt;/span&gt;
&lt;span id=&quot;cb2-8&quot;&gt;&lt;a href=&quot;#cb2-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-9&quot;&gt;&lt;a href=&quot;#cb2-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;validate2 ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Policy&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Bool&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-10&quot;&gt;&lt;a href=&quot;#cb2-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;validate2 &lt;span class=&quot;dt&quot;&gt;P&lt;/span&gt;{&lt;span class=&quot;op&quot;&gt;..&lt;/span&gt;} &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; n &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-11&quot;&gt;&lt;a href=&quot;#cb2-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-12&quot;&gt;&lt;a href=&quot;#cb2-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    n &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; countTrue (&lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; pChar) [pPass &lt;span class=&quot;op&quot;&gt;!!&lt;/span&gt; (pIx1 &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;), pPass &lt;span class=&quot;op&quot;&gt;!!&lt;/span&gt; (pIx2 &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;)]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And so parts 1 and 2 are just a count of how many policies are true :)&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part1 ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Policy&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part1 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; countTrue validate1&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part2 ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Policy&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; countTrue validate2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;day-2-benchmarks&quot;&gt;Day 2 Benchmarks&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; Day 02a
benchmarking...
time                 55.69 μs   (55.61 μs .. 55.78 μs)
                     1.000 R²   (1.000 R² .. 1.000 R²)
mean                 55.89 μs   (55.82 μs .. 56.03 μs)
std dev              323.1 ns   (232.5 ns .. 422.3 ns)

* parsing and formatting times excluded

&amp;gt;&amp;gt; Day 02b
benchmarking...
time                 42.96 μs   (42.88 μs .. 43.06 μs)
                     1.000 R²   (1.000 R² .. 1.000 R²)
mean                 43.11 μs   (43.07 μs .. 43.19 μs)
std dev              196.8 ns   (94.94 ns .. 332.4 ns)

* parsing and formatting times excluded&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md#day-2</link>
      <pubDate>Wed,  2 Dec 2020 01:00:00 EST</pubDate>
    </item>

    <item>
      <title>Day 1</title>
      <description>&lt;h2 id=&quot;day-1&quot;&gt;Day 1&lt;/h2&gt;
&lt;!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day01.md`.  If you want to edit this, edit
that file instead!
--&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://adventofcode.com/2020/day/1&quot;&gt;Prompt&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/src/AOC/Challenge/Day01.hs&quot;&gt;Code&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://mstksg.github.io/advent-of-code-2020/src/AOC.Challenge.Day01.html&quot;&gt;Rendered&lt;/a&gt;&lt;/em&gt; / &lt;em&gt;&lt;a href=&quot;https://github.com/mstksg/advent-of-code-2020/blob/master/reflections-out/day01.md&quot;&gt;Standalone Reflection Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So there’s a simple-ish Haskell solution for these problems,&lt;/p&gt;
&lt;p&gt;&lt;code&gt;tails&lt;/code&gt; lets you separate out each item in a list with the list of items after it:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;ghci&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; tails [&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;4&lt;/span&gt;]&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;[&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;[&lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;4&lt;/span&gt;], &lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;[&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;,&lt;span class=&quot;dv&quot;&gt;4&lt;/span&gt;], &lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;[&lt;span class=&quot;dv&quot;&gt;4&lt;/span&gt;], &lt;span class=&quot;dv&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;[]]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;findPair ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;findPair xs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; listToMaybe &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    x&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;ys &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; tails xs&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    y    &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; ys&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    guard (x &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; y &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2020&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; (x&lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;y)&lt;/span&gt;
&lt;span id=&quot;cb2-7&quot;&gt;&lt;a href=&quot;#cb2-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-8&quot;&gt;&lt;a href=&quot;#cb2-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;findTriple ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-9&quot;&gt;&lt;a href=&quot;#cb2-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;findTriple xs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; listToMaybe &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-10&quot;&gt;&lt;a href=&quot;#cb2-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    x&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;ys &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; tails xs&lt;/span&gt;
&lt;span id=&quot;cb2-11&quot;&gt;&lt;a href=&quot;#cb2-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    y&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;zs &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; tails ys&lt;/span&gt;
&lt;span id=&quot;cb2-12&quot;&gt;&lt;a href=&quot;#cb2-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    z    &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; zs&lt;/span&gt;
&lt;span id=&quot;cb2-13&quot;&gt;&lt;a href=&quot;#cb2-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    guard (x &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; y &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; z &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2020&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb2-14&quot;&gt;&lt;a href=&quot;#cb2-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; (x&lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;y&lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;z)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But this method is a little bit “extra”, since we actually don’t need to search all of &lt;code&gt;ys&lt;/code&gt; for the proper sum…if we pick &lt;code&gt;x&lt;/code&gt; as &lt;code&gt;500&lt;/code&gt;, then we really only need to check if &lt;code&gt;1520&lt;/code&gt; is a part of &lt;code&gt;ys&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So we really only need to check for set inclusion:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;qualified&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Data.IntSet&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IS&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;findPair ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IS.IntSet&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;findPair goal xs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; listToMaybe &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    x &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; IS.toList xs&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; y &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; goal &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt; x&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    guard (y &lt;span class=&quot;ot&quot;&gt;`IS.member`&lt;/span&gt; xs)&lt;/span&gt;
&lt;span id=&quot;cb3-8&quot;&gt;&lt;a href=&quot;#cb3-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; (x &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt; y)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And our first part will be &lt;code&gt;findPair 2020&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;You could even implement &lt;code&gt;findTriple&lt;/code&gt; in terms of &lt;code&gt;findPair&lt;/code&gt;, using &lt;code&gt;IS.split&lt;/code&gt; to partition a set into all items smaller than and larger than a number. Splitting is a very efficient operation on a binary search tree like &lt;code&gt;IntSet&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;findTriple ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IS.IntSet&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;findTriple goal xs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; listToMaybe &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-3&quot;&gt;&lt;a href=&quot;#cb4-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    x &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; IS.toList xs&lt;/span&gt;
&lt;span id=&quot;cb4-4&quot;&gt;&lt;a href=&quot;#cb4-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; (_, ys) &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; IS.split x xs&lt;/span&gt;
&lt;span id=&quot;cb4-5&quot;&gt;&lt;a href=&quot;#cb4-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        goal&amp;#39;   &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; goal &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt; x&lt;/span&gt;
&lt;span id=&quot;cb4-6&quot;&gt;&lt;a href=&quot;#cb4-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt; findPair goal&amp;#39; ys &lt;span class=&quot;kw&quot;&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-7&quot;&gt;&lt;a href=&quot;#cb4-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; empty&lt;/span&gt;
&lt;span id=&quot;cb4-8&quot;&gt;&lt;a href=&quot;#cb4-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; yz &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; (x&lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;yz)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But hey…this recursive descent is kind of neat. We could write a general function to find any goal in any number of items!&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- | Given a number n of items and a goal sum and a set of numbers to&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;-- pick from, finds the n numbers in the set that add to the goal sum.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-3&quot;&gt;&lt;a href=&quot;#cb5-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;knapsack&lt;/span&gt;
&lt;span id=&quot;cb5-4&quot;&gt;&lt;a href=&quot;#cb5-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;    ::&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;              &lt;span class=&quot;co&quot;&gt;-- ^ number of items n to pick&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-5&quot;&gt;&lt;a href=&quot;#cb5-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;              &lt;span class=&quot;co&quot;&gt;-- ^ goal sum&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-6&quot;&gt;&lt;a href=&quot;#cb5-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;IS.IntSet&lt;/span&gt;        &lt;span class=&quot;co&quot;&gt;-- ^ set of options&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-7&quot;&gt;&lt;a href=&quot;#cb5-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;]      &lt;span class=&quot;co&quot;&gt;-- ^ resulting n items that sum to the goal&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-8&quot;&gt;&lt;a href=&quot;#cb5-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;knapsack &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; _    _  &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-9&quot;&gt;&lt;a href=&quot;#cb5-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;knapsack &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt; goal xs&lt;/span&gt;
&lt;span id=&quot;cb5-10&quot;&gt;&lt;a href=&quot;#cb5-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; goal &lt;span class=&quot;ot&quot;&gt;`IS.member`&lt;/span&gt; xs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; [goal]&lt;/span&gt;
&lt;span id=&quot;cb5-11&quot;&gt;&lt;a href=&quot;#cb5-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;otherwise&lt;/span&gt;           &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-12&quot;&gt;&lt;a href=&quot;#cb5-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;knapsack n goal xs &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; listToMaybe &lt;span class=&quot;op&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-13&quot;&gt;&lt;a href=&quot;#cb5-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    x &lt;span class=&quot;ot&quot;&gt;&amp;lt;-&lt;/span&gt; IS.toList xs&lt;/span&gt;
&lt;span id=&quot;cb5-14&quot;&gt;&lt;a href=&quot;#cb5-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; goal&amp;#39;   &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; goal &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt; x&lt;/span&gt;
&lt;span id=&quot;cb5-15&quot;&gt;&lt;a href=&quot;#cb5-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        (_, ys) &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; IS.split x xs&lt;/span&gt;
&lt;span id=&quot;cb5-16&quot;&gt;&lt;a href=&quot;#cb5-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;case&lt;/span&gt; knapsack (n &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;) goal&amp;#39; ys &lt;span class=&quot;kw&quot;&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-17&quot;&gt;&lt;a href=&quot;#cb5-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;dt&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; empty&lt;/span&gt;
&lt;span id=&quot;cb5-18&quot;&gt;&lt;a href=&quot;#cb5-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;dt&quot;&gt;Just&lt;/span&gt; rs &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;pure&lt;/span&gt; (x&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;rs)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And so we have:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb6&quot;&gt;&lt;pre class=&quot;sourceCode haskell&quot;&gt;&lt;code class=&quot;sourceCode haskell&quot;&gt;&lt;span id=&quot;cb6-1&quot;&gt;&lt;a href=&quot;#cb6-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part1 ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-2&quot;&gt;&lt;a href=&quot;#cb6-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part1 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; knapsack &lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2020&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; IS.fromList&lt;/span&gt;
&lt;span id=&quot;cb6-3&quot;&gt;&lt;a href=&quot;#cb6-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-4&quot;&gt;&lt;a href=&quot;#cb6-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ot&quot;&gt;part2 ::&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;] &lt;span class=&quot;ot&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-5&quot;&gt;&lt;a href=&quot;#cb6-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;part2 &lt;span class=&quot;ot&quot;&gt;=&lt;/span&gt; knapsack &lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2020&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt; IS.fromList&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And we could go on, and on, and on!&lt;/p&gt;
&lt;p&gt;Definitely very unnecessary, but it does shave my time on Part 2 down from around 2ms to around 20μs :)&lt;/p&gt;
&lt;h3 id=&quot;day-1-benchmarks&quot;&gt;Day 1 Benchmarks&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; Day 01a
benchmarking...
time                 5.564 μs   (5.347 μs .. 5.859 μs)
                     0.987 R²   (0.979 R² .. 1.000 R²)
mean                 5.499 μs   (5.390 μs .. 5.783 μs)
std dev              546.8 ns   (238.7 ns .. 928.6 ns)
variance introduced by outliers: 87% (severely inflated)

* parsing and formatting times excluded

&amp;gt;&amp;gt; Day 01b
benchmarking...
time                 51.91 μs   (51.03 μs .. 53.43 μs)
                     0.988 R²   (0.978 R² .. 0.995 R²)
mean                 58.57 μs   (56.07 μs .. 61.01 μs)
std dev              9.320 μs   (8.111 μs .. 10.06 μs)
variance introduced by outliers: 93% (severely inflated)

* parsing and formatting times excluded&lt;/code&gt;&lt;/pre&gt;
</description>
      <link>https://github.com/mstksg/advent-of-code-2020/blob/master/reflections.md#day-1</link>
      <pubDate>Tue,  1 Dec 2020 01:00:00 EST</pubDate>
    </item>

  </channel>
</rss>
