forked from mstksg/advent-of-code-2021
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfeed.xml
163 lines (156 loc) · 33.7 KB
/
feed.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
<?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 2021 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-2021/blob/master/reflections.md</link>
<copyright>Copyright 2021 Justin Le</copyright>
<language>en-us</language>
<lastBuildDate>Sat, 4 Dec 2021 03:20:39 EST</lastBuildDate>
<managingEditor>[email protected]</managingEditor>
<pubDate>Sat, 4 Dec 2021 03:20:39 EST</pubDate>
<webMaster>[email protected]</webMaster>
<generator>Shake + Template</generator>
<item>
<title>Day 2</title>
<description><h2 id="day-2">Day 2</h2>
<!--
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!
-->
<p><em><a href="https://adventofcode.com/2021/day/2">Prompt</a></em> / <em><a href="https://github.com/mstksg/advent-of-code-2021/blob/master/src/AOC/Challenge/Day02.hs">Code</a></em> / <em><a href="https://mstksg.github.io/advent-of-code-2021/src/AOC.Challenge.Day02.html">Rendered</a></em> / <em><a href="https://github.com/mstksg/advent-of-code-2021/blob/master/reflections-out/day02.md">Standalone Reflection Page</a></em></p>
<p>Day 2 has a satisfying “unified” solution for both parts that can be derived from group theory! The general group (or monoid) design pattern that I’ve gone over <a href="https://blog.jle.im/entries/series/+advent-of-code.html">in many Advent of Code blog posts</a> is that we can think of our “final action” as simply a “squishing” of individual smaller actions. The revelation is that our individual smaller actions are “combinable” to yield something of the <em>same type</em>, so solving the puzzle is generating all of the smaller actions repeatedly combining them to yield the final action.</p>
<p>In both of these parts, we can think of squishing a bunch of small actions (<code>forward</code>, <code>up</code>, <code>down</code>) into a mega-action, which represents the final trip as one big step. So here is our general solver:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- | A type for x-y coordinates/2d vectors</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Point</span> <span class="ot">=</span> <span class="dt">P</span> {<span class="ot"> pX ::</span> <span class="dt">Int</span>,<span class="ot"> pY ::</span> <span class="dt">Int</span> }</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>day02</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="ot"> ::</span> <span class="dt">Monoid</span> r</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a> <span class="ot">=&gt;</span> (<span class="dt">Int</span> <span class="ot">-&gt;</span> r) <span class="co">-- ^ construct a forward action</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a> <span class="ot">-&gt;</span> (<span class="dt">Int</span> <span class="ot">-&gt;</span> r) <span class="co">-- ^ construct an up/down action</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a> <span class="ot">-&gt;</span> (r <span class="ot">-&gt;</span> <span class="dt">Point</span> <span class="ot">-&gt;</span> <span class="dt">Point</span>) <span class="co">-- ^ how to apply an action to a point</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a> <span class="ot">-&gt;</span> <span class="dt">String</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a> <span class="ot">-&gt;</span> <span class="dt">Point</span> <span class="co">-- ^ the final point</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>day02 mkForward mkUpDown applyAct <span class="ot">=</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a> (<span class="ot">`applyAct`</span> <span class="dt">P</span> <span class="dv">0</span> <span class="dv">0</span>) <span class="co">-- get the answer by applying from 0,0</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> <span class="fu">foldMap</span> (parseAsDir <span class="op">.</span> <span class="fu">words</span>) <span class="co">-- convert each line into the action and merge</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> <span class="fu">lines</span> <span class="co">-- split up lines</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a> parseAsDir (dir<span class="op">:</span>n<span class="op">:</span>_) <span class="ot">=</span> <span class="kw">case</span> dir <span class="kw">of</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;forward&quot;</span> <span class="ot">-&gt;</span> mkForward amnt</span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;down&quot;</span> <span class="ot">-&gt;</span> mkUpDown amnt</span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;up&quot;</span> <span class="ot">-&gt;</span> mkUpDown (<span class="op">-</span>amnt)</span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a> amnt <span class="ot">=</span> <span class="fu">read</span> n</span></code></pre></div>
<p>And there we have it! A solver for both parts 1 and 2. Now we just need to pick the Monoid :)</p>
<p>For part 1, the choice of monoid is simple: our final action is a translation by a vector, so it makes sense that the intermediate actions would be vectors as well – composing actions means adding those vectors together.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Vector</span> <span class="ot">=</span> <span class="dt">V</span> {<span class="ot"> dX ::</span> <span class="dt">Int</span>,<span class="ot"> dY ::</span> <span class="dt">Int</span> }</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Semigroup</span> <span class="dt">Vector</span> <span class="kw">where</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a> <span class="dt">V</span> dx dy <span class="op">&lt;&gt;</span> <span class="dt">V</span> dx&#39; dy&#39; <span class="ot">=</span> <span class="dt">V</span> (dx <span class="op">+</span> dx&#39;) (dy <span class="op">+</span> dy&#39;)</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Monoid</span> <span class="dt">Vector</span> <span class="kw">where</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a> <span class="fu">mempty</span> <span class="ot">=</span> <span class="dt">V</span> <span class="dv">0</span> <span class="dv">0</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="ot">day02a ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>day02a <span class="ot">=</span> day02</span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a> (\dx <span class="ot">-&gt;</span> <span class="dt">V</span> dx <span class="dv">0</span>) <span class="co">-- forward is just a horizontal vector</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a> (\dy <span class="ot">-&gt;</span> <span class="dt">V</span> <span class="dv">0</span> dy) <span class="co">-- up/down is a vertical vector</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a> (\(<span class="dt">V</span> dx dy) (<span class="dt">P</span> x0 y0) <span class="ot">-&gt;</span> <span class="dt">P</span> (x0 <span class="op">+</span> dx) (y0 <span class="op">+</span> dy))</span></code></pre></div>
<p>Part 2 is a little trickier because we have to keep track of dx, dy <em>and</em> aim. So we can think of our action as manipulating a <code>Point</code> as well as an <code>Aim</code>, and combining them together.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">Aim</span> <span class="ot">=</span> <span class="dt">Aim</span> <span class="dt">Int</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Semigroup</span> <span class="dt">Aim</span> <span class="kw">where</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a> <span class="dt">Aim</span> a <span class="op">&lt;&gt;</span> <span class="dt">Aim</span> b <span class="ot">=</span> <span class="dt">Aim</span> (a <span class="op">+</span> b)</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Monoid</span> <span class="dt">Aim</span> <span class="kw">where</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a> <span class="fu">mempty</span> <span class="ot">=</span> <span class="dt">Aim</span> <span class="dv">0</span></span></code></pre></div>
<p>So our “action” looks like:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Part2Action</span> <span class="ot">=</span> <span class="dt">P2A</span> {<span class="ot"> p2Vector ::</span> <span class="dt">Vector</span>,<span class="ot"> p2Aim ::</span> <span class="dt">Aim</span> }</span></code></pre></div>
<p>However, it’s not exactly obvious how to turn this into a monoid. How do we combine two <code>Part2Action</code>s to create a new one, in a way that respects the logic of part 2? Simply adding them point-wise does not do the trick, because we have to somehow also get the <code>Aim</code> to factor into the new y value.</p>
<p>Group theory to the rescue! Using the <a href="https://hackage.haskell.org/package/monoid-extras-0.6.1">monoid-extras</a> library, we can can say that <code>Aim</code> encodes a “vector transformer”. Applying an aim means adding the dy value by the aim value multiplied the dx component.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Action</span> <span class="dt">Aim</span> <span class="dt">Vector</span> <span class="kw">where</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a> act (<span class="dt">Aim</span> a) <span class="ot">=</span> moveDownByAimFactor</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a> moveDownByAimFactor (<span class="dt">V</span> dx dy) <span class="ot">=</span> <span class="dt">V</span> dx (dy <span class="op">+</span> a <span class="op">*</span> dx)</span></code></pre></div>
<p>Because of this, we can now pair together <code>Vector</code> and <code>Aim</code> as a <a href="https://hackage.haskell.org/package/monoid-extras-0.6.1/docs/Data-Monoid-SemiDirectProduct.html">semi-direct product</a>: If we pair up our monoid (<code>Vector</code>) with a “point transformer” (<code>Aim</code>), then <code>Semi Vector Aim</code> is a monoid that contains both (like our <code>Part2Action</code> above) but also provides a <code>Monoid</code> instance that “does the right thing” (adds vector, adds aim, and also makes sure the aim action gets applied correctly when adding vectors) thanks to group theory.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- constructors/deconstructors that monoid-extras gives us</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="ot">inject ::</span> <span class="dt">Vector</span> <span class="ot">-&gt;</span> <span class="dt">Semi</span> <span class="dt">Vector</span> <span class="dt">Aim</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="ot">embed ::</span> <span class="dt">Aim</span> <span class="ot">-&gt;</span> <span class="dt">Semi</span> <span class="dt">Vector</span> <span class="dt">Aim</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="ot">untag ::</span> <span class="dt">Semi</span> <span class="dt">Vector</span> <span class="dt">Aim</span> <span class="ot">-&gt;</span> <span class="dt">Vector</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a><span class="ot">day02b ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>day02b <span class="ot">=</span> day02</span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a> (\dx <span class="ot">-&gt;</span> inject <span class="op">$</span> <span class="dt">V</span> dx <span class="dv">0</span>) <span class="co">-- forward just contributs a vector motion</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a> (\a <span class="ot">-&gt;</span> embed <span class="op">$</span> <span class="dt">Aim</span> a ) <span class="co">-- up/down just adjusts the aim</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a> (\sdp (<span class="dt">P</span> x0 y0) <span class="ot">-&gt;</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> <span class="dt">V</span> dx dy <span class="ot">=</span> untag sdp</span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a> <span class="kw">in</span> <span class="dt">P</span> (x0 <span class="op">+</span> dx) (y0 <span class="op">+</span> dy)</span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a> )</span></code></pre></div>
<p>And that’s it, we’re done, thanks to the power of group theory! We identified that our final monoid must somehow contain both components (<code>Vector</code>, and <code>Aim</code>), but did not know how the two could come together to form a mega-monoid of both. However, because we saw that <code>Aim</code> also gets accumulated while also acting as a “point transformer”, we can describe how it transforms points (with the <code>Action</code> instance) and so we can use <code>Semi</code> (semi-direct product) to encode our action with a <code>Monoid</code> instance that does the right thing.</p>
<p>What was the point of this? Well, we were able to unify both parts 1 and 2 to be solved in the same overall method, just by picking a different monoid for each part. With only two parts, it might not seem that worth it to abstract, but maybe if there were more we could experiment with what other neat monoids we could express our solution as! But, a major advantage we reap now is that, because each action combines into other actions (associatively), we could do all of this in parallel! If our list of actions was very long, we could distribute the work over multiple cores or computers and re-combine like a map-reduce. There’s just something very satisfying about having the “final action” be of the same type as our intermediate actions. With that revelation, we open the door to the entire field of monoid-based optimizations and pre-made algorithms (like <code>Semi</code>)</p>
<p>(Thanks to <code>mniip</code> in libera irc’s <em>#adventofcode</em> channel for helping me express this in terms of a semi-direct product! My original attempt used a 4x4 matrix that ended up doing the same thing after some symbolic analysis.)</p>
<p>(Thanks too to @lysxia on twitter for pointing out a nicer way of interpreting the action in terms of how it acts on points!)</p>
<h3 id="day-2-benchmarks">Day 2 Benchmarks</h3>
<pre><code>&gt;&gt; Day 02a
benchmarking...
time 8.030 μs (7.348 μs .. 8.777 μs)
0.955 R² (0.936 R² .. 0.993 R²)
mean 7.800 μs (7.516 μs .. 8.666 μs)
std dev 1.719 μs (936.6 ns .. 3.161 μs)
variance introduced by outliers: 97% (severely inflated)
* parsing and formatting times excluded
&gt;&gt; Day 02b
benchmarking...
time 1.710 ms (1.616 ms .. 1.830 ms)
0.964 R² (0.929 R² .. 0.987 R²)
mean 1.730 ms (1.673 ms .. 1.792 ms)
std dev 215.9 μs (168.1 μs .. 321.3 μs)
variance introduced by outliers: 79% (severely inflated)</code></pre>
</description>
<link>https://github.com/mstksg/advent-of-code-2021/blob/master/reflections.md#day-2</link>
<pubDate>Thu, 2 Dec 2021 01:00:00 EST</pubDate>
</item>
<item>
<title>Day 1</title>
<description><h2 id="day-1">Day 1</h2>
<!--
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!
-->
<p><em><a href="https://adventofcode.com/2021/day/1">Prompt</a></em> / <em><a href="https://github.com/mstksg/advent-of-code-2021/blob/master/src/AOC/Challenge/Day01.hs">Code</a></em> / <em><a href="https://mstksg.github.io/advent-of-code-2021/src/AOC.Challenge.Day01.html">Rendered</a></em> / <em><a href="https://github.com/mstksg/advent-of-code-2021/blob/master/reflections-out/day01.md">Standalone Reflection Page</a></em></p>
<p>As a simple data processing thing, this one shines pretty well in Haskell :)</p>
<p>Assuming we have a list, we can get the consecutive items with a combination of <code>zipWith</code> and <code>drop</code>. Then we can just count how many pairs of items match the predicate (strictly increasing):</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">countIncreasesPart1 ::</span> [<span class="dt">Int</span>] <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>countIncreasesPart1 xs <span class="ot">=</span> <span class="fu">length</span> (<span class="fu">filter</span> (<span class="op">==</span> <span class="dt">True</span>) (<span class="fu">zipWith</span> (<span class="op">&lt;</span>) xs (<span class="fu">drop</span> <span class="dv">1</span> xs)))</span></code></pre></div>
<p>Yes, <code>filter (== True)</code> is the same as <code>filter id</code>, but it’s a bit easier to read this way :)</p>
<p>Remember that if <code>xs</code> is <code>[2,4,6,5]</code>, then <code>drop 1 xs</code> is <code>[4,6,5]</code>, and so <code>zip xs (drop 1 xs)</code> is <code>[(2,4), (4,6), (6,5)]</code> So <code>zipWith (&lt;) xs (drop 1 xs)</code> is <code>[True, True, False]</code>. So counting all of the <code>True</code> items yields the right answer!</p>
<p>Part 2 is very similar, but we need to check if items <em>three</em> positions apart are increasing. That’s because for each window, the sum of the window is increasing if the new item gained is bigger than the item that was just lost. So for an example like <code>[3,5,6,4,7,8]</code>, as we move from <code>[3,5,6]</code> to <code>[5,6,4]</code>, we only need to check if <code>4</code> is greater than <code>3</code>. So we only need to compare 4 and 3, 7 and 5, and then 8 and 6.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">countIncreasesPart2 ::</span> [<span class="dt">Int</span>] <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>countIncreasesPart2 xs <span class="ot">=</span> <span class="fu">length</span> (<span class="fu">filter</span> (<span class="op">==</span> <span class="dt">True</span>) (<span class="fu">zipWith</span> (<span class="op">&lt;</span>) xs (<span class="fu">drop</span> <span class="dv">3</span> xs)))</span></code></pre></div>
<p>We just need to replace <code>drop 1 xs</code> with <code>drop 3 xs</code> to compare three-away items.</p>
<p>Anyway the parsing in Haskell is straightforward, at least – we can just do <code>map read . lines</code>, to split our input into lines and then map <code>read :: String -&gt; Int</code> over each line. Ta dah! Fun start to the year :)</p>
<h3 id="day-1-benchmarks">Day 1 Benchmarks</h3>
<pre><code>&gt;&gt; Day 01a
benchmarking...
time 26.81 μs (26.45 μs .. 27.29 μs)
0.996 R² (0.991 R² .. 1.000 R²)
mean 26.75 μs (26.43 μs .. 27.57 μs)
std dev 1.478 μs (130.1 ns .. 2.625 μs)
variance introduced by outliers: 62% (severely inflated)
* parsing and formatting times excluded
&gt;&gt; Day 01b
benchmarking...
time 27.02 μs (25.16 μs .. 28.74 μs)
0.966 R² (0.956 R² .. 0.979 R²)
mean 26.40 μs (25.02 μs .. 27.78 μs)
std dev 4.752 μs (3.640 μs .. 6.699 μs)
variance introduced by outliers: 95% (severely inflated)
* parsing and formatting times excluded</code></pre>
</description>
<link>https://github.com/mstksg/advent-of-code-2021/blob/master/reflections.md#day-1</link>
<pubDate>Wed, 1 Dec 2021 01:00:00 EST</pubDate>
</item>
</channel>
</rss>