advent of code solutions aoc.oppi.li
haskell aoc

book: unignore out dir

Signed-off-by: oppiliappan <me@oppi.li>

oppi.li 526ab8f1 086241a4

verified
+3332 -1
-1
.gitignore
··· 1 1 *inputs* 2 2 .direnv 3 3 .envrc 4 - out 5 4 *.tar.zst 6 5 bin 7 6 *.hi
+49
out/1-section.html
··· 1 + <!DOCTYPE html> 2 + <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang=""> 3 + <head> 4 + <meta charset="utf-8" /> 5 + <meta name="generator" content="pandoc" /> 6 + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> 7 + <title>2016</title> 8 + <style> 9 + code{white-space: pre-wrap;} 10 + span.smallcaps{font-variant: small-caps;} 11 + div.columns{display: flex; gap: min(4vw, 1.5em);} 12 + div.column{flex: auto; overflow-x: auto;} 13 + div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} 14 + /* The extra [class] is a hack that increases specificity enough to 15 + override a similar rule in reveal.js */ 16 + ul.task-list[class]{list-style: none;} 17 + ul.task-list li input[type="checkbox"] { 18 + font-size: inherit; 19 + width: 0.8em; 20 + margin: 0 0.8em 0.2em -1.6em; 21 + vertical-align: middle; 22 + } 23 + .display.math{display: block; text-align: center; margin: 0.5rem auto;} 24 + </style> 25 + <link rel="stylesheet" href="style.css" /> 26 + </head> 27 + <body> 28 + <nav id="sitenav"> 29 + <div class="sitenav"> 30 + <span class="navlink"> 31 + <span class="navlink-label">Up:</span> <a href="index.html" accesskey="u" rel="up"></a> 32 + </span> 33 + <span class="navlink"> 34 + <span class="navlink-label">Top:</span> <a href="index.html" accesskey="t" rel="top"></a> 35 + </span> 36 + </div> 37 + <div class="sitenav"> 38 + <span class="navlink"> 39 + <span class="navlink-label">Previous:</span> <a href="index.html" accesskey="p" rel="previous"></a> 40 + </span> 41 + <span class="navlink"> 42 + <span class="navlink-label">Next:</span> <a href="1.1-day-1.html" accesskey="n" rel="next">Day 1</a> 43 + </span> 44 + </div> 45 + </nav> 46 + 47 + <h1 data-number="1" id="section">2016</h1> 48 + </body> 49 + </html>
+254
out/1.1-day-1.html
··· 1 + <!DOCTYPE html> 2 + <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang=""> 3 + <head> 4 + <meta charset="utf-8" /> 5 + <meta name="generator" content="pandoc" /> 6 + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> 7 + <title>Day 1</title> 8 + <style> 9 + code{white-space: pre-wrap;} 10 + span.smallcaps{font-variant: small-caps;} 11 + div.columns{display: flex; gap: min(4vw, 1.5em);} 12 + div.column{flex: auto; overflow-x: auto;} 13 + div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} 14 + /* The extra [class] is a hack that increases specificity enough to 15 + override a similar rule in reveal.js */ 16 + ul.task-list[class]{list-style: none;} 17 + ul.task-list li input[type="checkbox"] { 18 + font-size: inherit; 19 + width: 0.8em; 20 + margin: 0 0.8em 0.2em -1.6em; 21 + vertical-align: middle; 22 + } 23 + .display.math{display: block; text-align: center; margin: 0.5rem auto;} 24 + /* CSS for syntax highlighting */ 25 + html { -webkit-text-size-adjust: 100%; } 26 + pre > code.sourceCode { white-space: pre; position: relative; } 27 + pre > code.sourceCode > span { display: inline-block; line-height: 1.25; } 28 + pre > code.sourceCode > span:empty { height: 1.2em; } 29 + .sourceCode { overflow: visible; } 30 + code.sourceCode > span { color: inherit; text-decoration: inherit; } 31 + div.sourceCode { margin: 1em 0; } 32 + pre.sourceCode { margin: 0; } 33 + @media screen { 34 + div.sourceCode { overflow: auto; } 35 + } 36 + @media print { 37 + pre > code.sourceCode { white-space: pre-wrap; } 38 + pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; } 39 + } 40 + pre.numberSource code 41 + { counter-reset: source-line 0; } 42 + pre.numberSource code > span 43 + { position: relative; left: -4em; counter-increment: source-line; } 44 + pre.numberSource code > span > a:first-child::before 45 + { content: counter(source-line); 46 + position: relative; left: -1em; text-align: right; vertical-align: baseline; 47 + border: none; display: inline-block; 48 + -webkit-touch-callout: none; -webkit-user-select: none; 49 + -khtml-user-select: none; -moz-user-select: none; 50 + -ms-user-select: none; user-select: none; 51 + padding: 0 4px; width: 4em; 52 + } 53 + pre.numberSource { margin-left: 3em; padding-left: 4px; } 54 + div.sourceCode 55 + { } 56 + @media screen { 57 + pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; } 58 + } 59 + code span.al { font-weight: bold; } /* Alert */ 60 + code span.an { font-style: italic; } /* Annotation */ 61 + code span.cf { font-weight: bold; } /* ControlFlow */ 62 + code span.co { font-style: italic; } /* Comment */ 63 + code span.cv { font-style: italic; } /* CommentVar */ 64 + code span.do { font-style: italic; } /* Documentation */ 65 + code span.dt { color: #8888c7; } /* DataType */ 66 + code span.er { font-weight: bold; } /* Error */ 67 + code span.in { font-style: italic; } /* Information */ 68 + code span.kw { font-weight: bold; } /* Keyword */ 69 + code span.pp { font-weight: bold; } /* Preprocessor */ 70 + code span.wa { font-style: italic; } /* Warning */ 71 + </style> 72 + <link rel="stylesheet" href="style.css" /> 73 + </head> 74 + <body> 75 + <nav id="sitenav"> 76 + <div class="sitenav"> 77 + <span class="navlink"> 78 + <span class="navlink-label">Up:</span> <a href="1-section.html" accesskey="u" rel="up">2016</a> 79 + </span> 80 + <span class="navlink"> 81 + <span class="navlink-label">Top:</span> <a href="index.html" accesskey="t" rel="top"></a> 82 + </span> 83 + </div> 84 + <div class="sitenav"> 85 + <span class="navlink"> 86 + <span class="navlink-label">Previous:</span> <a href="1-section.html" accesskey="p" rel="previous">2016</a> 87 + </span> 88 + <span class="navlink"> 89 + <span class="navlink-label">Next:</span> <a href="1.2-day-2.html" accesskey="n" rel="next">Day 2</a> 90 + </span> 91 + </div> 92 + </nav> 93 + 94 + <h2 data-number="1.1" id="day-1">Day 1</h2> 95 + <h3 data-number="1.1.1" id="part-1">Part 1</h3> 96 + <div class="row"> 97 + <p>We start with some imports obviously:</p> 98 + <div class="code"> 99 + <div class="sourceCode" id="cb1"><pre 100 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE LambdaCase #-}</span></span> 101 + <span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.Set</span> <span class="kw">as</span> <span class="dt">S</span></span></code></pre></div> 102 + </div> 103 + </div> 104 + <div class="row"> 105 + <p>Once we have those in place, begin by parsing the input; the 106 + input is of the form:</p> 107 + <div class="code"> 108 + 109 + </div> 110 + </div> 111 + <pre><code>R24, L45, CNN ...</code></pre> 112 + <div class="row"> 113 + <p>Where <code>C</code> is a letter, <code>NN</code> form a 114 + natural number. First we normalize the input by appending a “,” to 115 + the end. We then use <code>words</code> to split on spaces, now 116 + each element is of the form <code>CNN,</code>. Using 117 + <code>init</code> we can drop the trailing comma, and finally, 118 + call <code>extract</code> to parse <code>C</code> and 119 + <code>NN</code> separately.</p> 120 + <div class="code"> 121 + <div class="sourceCode" id="cb3"><pre 122 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">parse ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> [(<span class="dt">Char</span>, <span class="dt">Int</span>)]</span> 123 + <span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>parse input <span class="ot">=</span> <span class="fu">map</span> (extract <span class="op">.</span> <span class="fu">init</span>) <span class="op">$</span> <span class="fu">words</span> normalized</span> 124 + <span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span> normalized <span class="ot">=</span> input <span class="op">++</span> <span class="st">&quot;,&quot;</span></span> 125 + <span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a> extract (d<span class="op">:</span>rest) <span class="ot">=</span> (d, <span class="fu">read</span> rest)</span></code></pre></div> 126 + </div> 127 + </div> 128 + <div class="row"> 129 + <p>Next, we define a list of axes, the +x axis is defined as (1, 130 + 0) and so on:</p> 131 + <div class="code"> 132 + <div class="sourceCode" id="cb4"><pre 133 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ot">axis ::</span> [(<span class="dt">Int</span>, <span class="dt">Int</span>)]</span> 134 + <span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>axis <span class="ot">=</span> [(<span class="dv">0</span>, <span class="dv">1</span>), (<span class="dv">1</span>, <span class="dv">0</span>), (<span class="dv">0</span>, <span class="op">-</span><span class="dv">1</span>), (<span class="op">-</span><span class="dv">1</span>, <span class="dv">0</span>)]</span></code></pre></div> 135 + </div> 136 + </div> 137 + <div class="row"> 138 + <p>And finally, the first bit of interesting computation; given a 139 + direction, we apply a move to the right or left. Each face is 140 + represented by an integer (0 being North, 1 being East etc.), 141 + Turning right adds one; and turing left subtracts one, the modulo 142 + makes the computation cyclic:</p> 143 + <div class="code"> 144 + <div class="sourceCode" id="cb5"><pre 145 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ot">dir ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Char</span> <span class="ot">-&gt;</span> <span class="dt">Int</span></span> 146 + <span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>dir face <span class="ot">=</span> \<span class="kw">case</span></span> 147 + <span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a> <span class="ch">&#39;R&#39;</span> <span class="ot">-&gt;</span> (face <span class="op">+</span> <span class="dv">1</span>) <span class="ot">`mod`</span> <span class="dv">4</span></span> 148 + <span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a> <span class="ch">&#39;L&#39;</span> <span class="ot">-&gt;</span> (face <span class="op">-</span> <span class="dv">1</span>) <span class="ot">`mod`</span> <span class="dv">4</span></span></code></pre></div> 149 + </div> 150 + </div> 151 + <div class="row"> 152 + <p>Now, given a position, and a movement; we can compute the new 153 + position like so; first compute the new face to look at by 154 + turning, next, determine the axis that we would move along. If we 155 + are moving along the +x axis, (dx, dy) is set to (1, 0). Thus the 156 + new position is given by movind <code>l * dx</code> along the 157 + x-axis, and <code>l * dy</code> along the y-axis (which would be 158 + zero if <code>dy</code> is zero).</p> 159 + <div class="code"> 160 + <div class="sourceCode" id="cb6"><pre 161 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>move (face, x, y) (d, l) <span class="ot">=</span> (nf, x <span class="op">+</span> l <span class="op">*</span> dx, y <span class="op">+</span> l <span class="op">*</span> dy)</span> 162 + <span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span> nf <span class="ot">=</span> dir face d</span> 163 + <span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a> (dx, dy) <span class="ot">=</span> axis <span class="op">!!</span> nf</span></code></pre></div> 164 + </div> 165 + </div> 166 + <div class="row"> 167 + <p>The problem requires us to compute the Manhattan distance of 168 + the destination location; which is given by:</p> 169 + <div class="code"> 170 + <div class="sourceCode" id="cb7"><pre 171 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>mag (_, x, y) <span class="ot">=</span> <span class="fu">abs</span> x <span class="op">+</span> <span class="fu">abs</span> y</span></code></pre></div> 172 + </div> 173 + </div> 174 + <div class="row"> 175 + <p>Thus, the solution to part 1 is given by <code>p1</code>; apply 176 + the <code>move</code> function starting at (0, 0, 0); and applying 177 + all the moves in the input. Finally compute the Manhattan distance 178 + of the destination from the origin.</p> 179 + <div class="code"> 180 + <div class="sourceCode" id="cb8"><pre 181 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ot">p1 ::</span> [(<span class="dt">Char</span>, <span class="dt">Int</span>)] <span class="ot">-&gt;</span> <span class="dt">Int</span></span> 182 + <span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>p1 n <span class="ot">=</span> mag <span class="op">$</span> foldl&#39; move (<span class="dv">0</span>, <span class="dv">0</span>, <span class="dv">0</span>) n</span></code></pre></div> 183 + </div> 184 + </div> 185 + <h3 data-number="1.1.2" id="part-2">Part 2</h3> 186 + <div class="row"> 187 + <p>In the second part, we are tasked with finding the first point 188 + that we cross over. This requires us to first enumerate all the 189 + points we have visited by making each move.</p> 190 + <div class="code"> 191 + 192 + </div> 193 + </div> 194 + <div class="row"> 195 + <p>This <code>range</code> function is a helper to enumerate all 196 + points between two integers:</p> 197 + <div class="code"> 198 + <div class="sourceCode" id="cb9"><pre 199 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="fu">range</span><span class="ot"> ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> [<span class="dt">Int</span>]</span> 200 + <span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="fu">range</span> a b</span> 201 + <span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> a <span class="op">&lt;=</span> b <span class="ot">=</span> [a <span class="op">..</span> b]</span> 202 + <span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="fu">otherwise</span> <span class="ot">=</span> [a, a <span class="op">-</span> <span class="dv">1</span> <span class="op">..</span> b]</span></code></pre></div> 203 + </div> 204 + </div> 205 + <div class="row"> 206 + <p>The first point we cross over will then be the first duplicate 207 + element in the list of points we visit, <code>firstDup</code> uses 208 + <code>Data.Set</code> to determine the first duplicate point from 209 + a sequence:</p> 210 + <div class="code"> 211 + <div class="sourceCode" id="cb10"><pre 212 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ot">firstDup ::</span> <span class="dt">Ord</span> a <span class="ot">=&gt;</span> [a] <span class="ot">-&gt;</span> a</span> 213 + <span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>firstDup xs <span class="ot">=</span> go S.empty xs</span> 214 + <span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span> 215 + <span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a> go seen (x <span class="op">:</span> xs)</span> 216 + <span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> x <span class="ot">`S.member`</span> seen <span class="ot">=</span> x</span> 217 + <span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="fu">otherwise</span> <span class="ot">=</span> go (S.insert x seen) xs</span></code></pre></div> 218 + </div> 219 + </div> 220 + <div class="row"> 221 + <p>Thus, the solution to the second part is given by 222 + <code>p2</code>. First, <code>pts</code> is calculated as all the 223 + final locations after each move. We then run through these 224 + pairwise and calculate all the points in between. Finally, we 225 + determine the magnitude of the first point we visit twice.</p> 226 + <div class="code"> 227 + <div class="sourceCode" id="cb11"><pre 228 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="ot">p2 ::</span> [(<span class="dt">Char</span>, <span class="dt">Int</span>)] <span class="ot">-&gt;</span> <span class="dt">Int</span></span> 229 + <span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>p2 n <span class="ot">=</span> mag <span class="op">$</span> firstDup coords</span> 230 + <span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span> 231 + <span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a> pts <span class="ot">=</span> <span class="fu">scanl</span> move (<span class="dv">0</span>, <span class="dv">0</span>, <span class="dv">0</span>) n</span> 232 + <span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a> pairs <span class="ot">=</span> <span class="fu">zip</span> pts (<span class="fu">tail</span> pts)</span> 233 + <span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a> coords <span class="ot">=</span></span> 234 + <span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a> [ (<span class="dv">0</span>, x, y)</span> 235 + <span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> ((_, x1, y1), (_, x2, y2)) <span class="ot">&lt;-</span> pairs,</span> 236 + <span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a> x <span class="ot">&lt;-</span> <span class="fu">range</span> x1 x2,</span> 237 + <span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a> y <span class="ot">&lt;-</span> <span class="fu">range</span> y1 y2,</span> 238 + <span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a> (x, y) <span class="op">/=</span> (x1, y1)</span> 239 + <span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a> ]</span></code></pre></div> 240 + </div> 241 + </div> 242 + <div class="row"> 243 + <p>Finally the <code>main</code> function is defined like so:</p> 244 + <div class="code"> 245 + <div class="sourceCode" id="cb12"><pre 246 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>input <span class="ot">=</span> <span class="st">&quot;R8, R4, R4, R8&quot;</span></span> 247 + <span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span> 248 + <span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> f <span class="ot">=</span> parse input</span> 249 + <span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">print</span> <span class="op">$</span> p1 f</span> 250 + <span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a> <span class="fu">print</span> <span class="op">$</span> p2 f</span></code></pre></div> 251 + </div> 252 + </div> 253 + </body> 254 + </html>
+2254
out/1.2-day-2.html
··· 1 + <!DOCTYPE html> 2 + <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang=""> 3 + <head> 4 + <meta charset="utf-8" /> 5 + <meta name="generator" content="pandoc" /> 6 + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> 7 + <title>Day 2</title> 8 + <style> 9 + code{white-space: pre-wrap;} 10 + span.smallcaps{font-variant: small-caps;} 11 + div.columns{display: flex; gap: min(4vw, 1.5em);} 12 + div.column{flex: auto; overflow-x: auto;} 13 + div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} 14 + /* The extra [class] is a hack that increases specificity enough to 15 + override a similar rule in reveal.js */ 16 + ul.task-list[class]{list-style: none;} 17 + ul.task-list li input[type="checkbox"] { 18 + font-size: inherit; 19 + width: 0.8em; 20 + margin: 0 0.8em 0.2em -1.6em; 21 + vertical-align: middle; 22 + } 23 + .display.math{display: block; text-align: center; margin: 0.5rem auto;} 24 + /* CSS for syntax highlighting */ 25 + html { -webkit-text-size-adjust: 100%; } 26 + pre > code.sourceCode { white-space: pre; position: relative; } 27 + pre > code.sourceCode > span { display: inline-block; line-height: 1.25; } 28 + pre > code.sourceCode > span:empty { height: 1.2em; } 29 + .sourceCode { overflow: visible; } 30 + code.sourceCode > span { color: inherit; text-decoration: inherit; } 31 + div.sourceCode { margin: 1em 0; } 32 + pre.sourceCode { margin: 0; } 33 + @media screen { 34 + div.sourceCode { overflow: auto; } 35 + } 36 + @media print { 37 + pre > code.sourceCode { white-space: pre-wrap; } 38 + pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; } 39 + } 40 + pre.numberSource code 41 + { counter-reset: source-line 0; } 42 + pre.numberSource code > span 43 + { position: relative; left: -4em; counter-increment: source-line; } 44 + pre.numberSource code > span > a:first-child::before 45 + { content: counter(source-line); 46 + position: relative; left: -1em; text-align: right; vertical-align: baseline; 47 + border: none; display: inline-block; 48 + -webkit-touch-callout: none; -webkit-user-select: none; 49 + -khtml-user-select: none; -moz-user-select: none; 50 + -ms-user-select: none; user-select: none; 51 + padding: 0 4px; width: 4em; 52 + } 53 + pre.numberSource { margin-left: 3em; padding-left: 4px; } 54 + div.sourceCode 55 + { } 56 + @media screen { 57 + pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; } 58 + } 59 + code span.al { font-weight: bold; } /* Alert */ 60 + code span.an { font-style: italic; } /* Annotation */ 61 + code span.cf { font-weight: bold; } /* ControlFlow */ 62 + code span.co { font-style: italic; } /* Comment */ 63 + code span.cv { font-style: italic; } /* CommentVar */ 64 + code span.do { font-style: italic; } /* Documentation */ 65 + code span.dt { color: #8888c7; } /* DataType */ 66 + code span.er { font-weight: bold; } /* Error */ 67 + code span.in { font-style: italic; } /* Information */ 68 + code span.kw { font-weight: bold; } /* Keyword */ 69 + code span.pp { font-weight: bold; } /* Preprocessor */ 70 + code span.wa { font-style: italic; } /* Warning */ 71 + </style> 72 + <link rel="stylesheet" href="style.css" /> 73 + </head> 74 + <body> 75 + <nav id="sitenav"> 76 + <div class="sitenav"> 77 + <span class="navlink"> 78 + <span class="navlink-label">Up:</span> <a href="1-section.html" accesskey="u" rel="up">2016</a> 79 + </span> 80 + <span class="navlink"> 81 + <span class="navlink-label">Top:</span> <a href="index.html" accesskey="t" rel="top"></a> 82 + </span> 83 + </div> 84 + <div class="sitenav"> 85 + <span class="navlink"> 86 + <span class="navlink-label">Previous:</span> <a href="1.1-day-1.html" accesskey="p" rel="previous">Day 1</a> 87 + </span> 88 + <span class="navlink"> 89 + <span class="navlink-label">Next:</span> <a href="2-section-1.html" accesskey="n" rel="next">2025</a> 90 + </span> 91 + </div> 92 + </nav> 93 + 94 + <h2 data-number="1.2" id="day-2">Day 2</h2> 95 + <h3 data-number="1.2.1" id="part-1-1">Part 1</h3> 96 + <div class="sourceCode" id="cb1"><pre 97 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE LambdaCase #-}</span></span> 98 + <span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span> 99 + <span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.Map</span> <span class="kw">as</span> <span class="dt">M</span></span> 100 + <span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">System.Environment</span> (getArgs)</span> 101 + <span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a></span> 102 + <span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>grid <span class="ot">=</span> M.fromList <span class="op">$</span> <span class="fu">zip</span> [(x, y) <span class="op">|</span> y <span class="ot">&lt;-</span> [<span class="dv">1</span>, <span class="dv">0</span>, <span class="op">-</span><span class="dv">1</span>], x <span class="ot">&lt;-</span> [<span class="op">-</span><span class="dv">1</span>, <span class="dv">0</span>, <span class="dv">1</span>]] [<span class="dv">1</span> <span class="op">..</span> <span class="dv">9</span>]</span> 103 + <span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span> 104 + <span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>grid2 <span class="ot">=</span></span> 105 + <span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a> M.fromList <span class="op">$</span></span> 106 + <span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a> <span class="fu">concat</span></span> 107 + <span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a> [ [((<span class="dv">0</span>, <span class="dv">2</span>), <span class="ch">&#39;1&#39;</span>)],</span> 108 + <span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a> [((<span class="op">-</span><span class="dv">1</span>, <span class="dv">1</span>), <span class="ch">&#39;2&#39;</span>), ((<span class="dv">0</span>, <span class="dv">1</span>), <span class="ch">&#39;3&#39;</span>), ((<span class="dv">1</span>, <span class="dv">1</span>), <span class="ch">&#39;4&#39;</span>)],</span> 109 + <span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a> [((<span class="op">-</span><span class="dv">2</span>, <span class="dv">0</span>), <span class="ch">&#39;5&#39;</span>), ((<span class="op">-</span><span class="dv">1</span>, <span class="dv">0</span>), <span class="ch">&#39;6&#39;</span>), ((<span class="dv">0</span>, <span class="dv">0</span>), <span class="ch">&#39;7&#39;</span>), ((<span class="dv">1</span>, <span class="dv">0</span>), <span class="ch">&#39;8&#39;</span>), ((<span class="dv">2</span>, <span class="dv">0</span>), <span class="ch">&#39;9&#39;</span>)],</span> 110 + <span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a> [((<span class="op">-</span><span class="dv">1</span>, <span class="op">-</span><span class="dv">1</span>), <span class="ch">&#39;A&#39;</span>), ((<span class="dv">0</span>, <span class="op">-</span><span class="dv">1</span>), <span class="ch">&#39;B&#39;</span>), ((<span class="dv">1</span>, <span class="op">-</span><span class="dv">1</span>), <span class="ch">&#39;C&#39;</span>)],</span> 111 + <span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a> [((<span class="dv">0</span>, <span class="op">-</span><span class="dv">2</span>), <span class="ch">&#39;D&#39;</span>)]</span> 112 + <span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a> ]</span> 113 + <span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a></span> 114 + <span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>move <span class="ot">=</span> \<span class="kw">case</span></span> 115 + <span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a> <span class="ch">&#39;L&#39;</span> <span class="ot">-&gt;</span> (<span class="op">-</span><span class="dv">1</span>, <span class="dv">0</span>)</span> 116 + <span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a> <span class="ch">&#39;R&#39;</span> <span class="ot">-&gt;</span> (<span class="dv">1</span>, <span class="dv">0</span>)</span> 117 + <span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a> <span class="ch">&#39;U&#39;</span> <span class="ot">-&gt;</span> (<span class="dv">0</span>, <span class="dv">1</span>)</span> 118 + <span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a> <span class="ch">&#39;D&#39;</span> <span class="ot">-&gt;</span> (<span class="dv">0</span>, <span class="op">-</span><span class="dv">1</span>)</span> 119 + <span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a></span> 120 + <span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>mmove g pos d <span class="ot">=</span> <span class="kw">if</span> M.member npos g <span class="kw">then</span> npos <span class="kw">else</span> pos</span> 121 + <span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span> 122 + <span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a> delta <span class="ot">=</span> move d</span> 123 + <span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a> npos <span class="ot">=</span> (<span class="fu">fst</span> pos <span class="op">+</span> <span class="fu">fst</span> delta, <span class="fu">snd</span> pos <span class="op">+</span> <span class="fu">snd</span> delta)</span> 124 + <span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a></span> 125 + <span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a>p1 ns <span class="ot">=</span> <span class="fu">tail</span> <span class="op">$</span> <span class="fu">map</span> (grid <span class="op">M.!</span>) <span class="op">$</span> <span class="fu">scanl</span> (foldl&#39; (mmove grid)) (<span class="dv">0</span>, <span class="dv">0</span>) ns</span> 126 + <span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a></span> 127 + <span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a>p2 ns <span class="ot">=</span> <span class="fu">tail</span> <span class="op">$</span> <span class="fu">map</span> (grid2 <span class="op">M.!</span>) <span class="op">$</span> <span class="fu">scanl</span> (foldl&#39; (mmove grid2)) (<span class="op">-</span><span class="dv">2</span>, <span class="dv">0</span>) ns</span> 128 + <span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a></span> 129 + <span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span> 130 + <span id="cb1-34"><a href="#cb1-34" aria-hidden="true" tabindex="-1"></a> args <span class="ot">&lt;-</span> getArgs</span> 131 + <span id="cb1-35"><a href="#cb1-35" aria-hidden="true" tabindex="-1"></a> n <span class="ot">&lt;-</span> <span class="kw">case</span> args <span class="kw">of</span></span> 132 + <span id="cb1-36"><a href="#cb1-36" aria-hidden="true" tabindex="-1"></a> [<span class="st">&quot;-&quot;</span>] <span class="ot">-&gt;</span> <span class="fu">getContents</span></span> 133 + <span id="cb1-37"><a href="#cb1-37" aria-hidden="true" tabindex="-1"></a> [file] <span class="ot">-&gt;</span> <span class="fu">readFile</span> file</span> 134 + <span id="cb1-38"><a href="#cb1-38" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> f <span class="ot">=</span> <span class="fu">lines</span> n</span> 135 + <span id="cb1-39"><a href="#cb1-39" aria-hidden="true" tabindex="-1"></a> <span class="fu">print</span> <span class="op">$</span> p1 f</span> 136 + <span id="cb1-40"><a href="#cb1-40" aria-hidden="true" tabindex="-1"></a> <span class="fu">print</span> <span class="op">$</span> p2 f</span></code></pre></div> 137 + <div class="row"> 138 + <p>import qualified Data.List as L import Data.List.Split 139 + (chunksOf, splitOn) import qualified Data.Text as T import 140 + System.Environment (getArgs)</p> 141 + <div class="code"> 142 + 143 + </div> 144 + </div> 145 + <div class="row"> 146 + <p>strip = T.unpack . T.strip . T.pack</p> 147 + <div class="code"> 148 + 149 + </div> 150 + </div> 151 + <div class="row"> 152 + <p>parse i = map read $ filter (not . null) $ map strip $ splitOn 153 + ” ” i</p> 154 + <div class="code"> 155 + 156 + </div> 157 + </div> 158 + <div class="row"> 159 + <p>possible l = all test $ L.permutations l where test [a, b, c] = 160 + a + b &gt; c</p> 161 + <div class="code"> 162 + 163 + </div> 164 + </div> 165 + <div class="row"> 166 + <p>p1 = length . filter possible</p> 167 + <div class="code"> 168 + 169 + </div> 170 + </div> 171 + <div class="row"> 172 + <p>main = do args &lt;- getArgs n &lt;- case args of [“-”] -&gt; 173 + getContents [file] -&gt; readFile file let f = map parse $ lines n 174 + let f2 = chunksOf 3 $ concat $ L.transpose f print $ p1 f print $ 175 + p1 f2</p> 176 + <div class="code"> 177 + 178 + </div> 179 + </div> 180 + <div class="row"> 181 + <p>import Data.Char import qualified Data.List as L import 182 + Data.List.Split (splitOn) import qualified Data.Map as M import 183 + qualified Data.Text as T import System.Environment (getArgs)</p> 184 + <div class="code"> 185 + 186 + </div> 187 + </div> 188 + <div class="row"> 189 + <p>parse i = (ls, read r, init c) where parts = splitOn “-” i ls = 190 + concat $ init parts [r, c] = splitOn “[” (L.last parts)</p> 191 + <div class="code"> 192 + 193 + </div> 194 + </div> 195 + <div class="row"> 196 + <p>freqs = M.fromListWith (+) . map (,1)</p> 197 + <div class="code"> 198 + 199 + </div> 200 + </div> 201 + <div class="row"> 202 + <p>cksum m = take 5 $ map fst $ L.sortBy f $ M.toList m where f 203 + (a, f1) (b, f2) = compare f2 f1 &lt;&gt; compare a b</p> 204 + <div class="code"> 205 + 206 + </div> 207 + </div> 208 + <div class="row"> 209 + <p>p1 it = sum $ map ((<em>, b, </em>) -&gt; b) $ filter solve it 210 + where solve (ls, room, c) = cksum (freqs ls) == c</p> 211 + <div class="code"> 212 + 213 + </div> 214 + </div> 215 + <div class="row"> 216 + <p>decrypt n = map (chr . (+ 97) . (<code>mod</code> 26) . (+ n) . 217 + flip (-) 97 . ord)</p> 218 + <div class="code"> 219 + 220 + </div> 221 + </div> 222 + <div class="row"> 223 + <p>p2 it = L.find ((== “northpoleobjectstorage”) . fst) $ map ((a, 224 + b, _) -&gt; (decrypt b a, b)) $ filter solve it where solve (ls, 225 + room, c) = cksum (freqs ls) == c</p> 226 + <div class="code"> 227 + 228 + </div> 229 + </div> 230 + <div class="row"> 231 + <p>main = do args &lt;- getArgs n &lt;- case args of [“-”] -&gt; 232 + getContents [file] -&gt; readFile file let f = map parse $ lines n 233 + print $ p1 f print $ p2 f</p> 234 + <div class="code"> 235 + 236 + </div> 237 + </div> 238 + <div class="row"> 239 + <p>import qualified Crypto.Hash.MD5 as MD5 import qualified 240 + Data.ByteString.Base16 as B16 import Data.ByteString.Char8 (pack) 241 + import qualified Data.ByteString.Char8 as BS import qualified 242 + Data.List as L import qualified Data.Map as M import 243 + System.Environment (getArgs)</p> 244 + <div class="code"> 245 + 246 + </div> 247 + </div> 248 + <div class="row"> 249 + <p>validHashes inp = [ h | f &lt;- [0 ..], let h = BS.unpack $ 250 + B16.encode $ MD5.hash $ BS.pack $ inp ++ show f, “00000” 251 + <code>L.isPrefixOf</code> h ]</p> 252 + <div class="code"> 253 + 254 + </div> 255 + </div> 256 + <div class="row"> 257 + <p>p1 = take 8 . map (!! 5) . validHashes</p> 258 + <div class="code"> 259 + 260 + </div> 261 + </div> 262 + <div class="row"> 263 + <p>p2 inp = M.elems $ go M.empty [ (pos, val) | h &lt;- 264 + validHashes inp, let pos = h !! 5, let val = h !! 6, pos 265 + <code>elem</code> “01234567” ] where go seen ((p, v) : rest) | 266 + length seen == 8 = seen | M.member p seen = go seen rest | 267 + otherwise = go (M.insert p v seen) rest</p> 268 + <div class="code"> 269 + 270 + </div> 271 + </div> 272 + <div class="row"> 273 + <p>main = do args &lt;- getArgs n &lt;- case args of [“-”] -&gt; 274 + getContents [file] -&gt; readFile file let f = init n print $ p1 f 275 + print $ p2 f</p> 276 + <div class="code"> 277 + 278 + </div> 279 + </div> 280 + <div class="row"> 281 + <p>import qualified Data.List as L import qualified Data.Map as M 282 + import Data.Ord (comparing) import System.Environment 283 + (getArgs)</p> 284 + <div class="code"> 285 + 286 + </div> 287 + </div> 288 + <div class="row"> 289 + <p>freqs = M.fromListWith (+) . map (,1)</p> 290 + <div class="code"> 291 + 292 + </div> 293 + </div> 294 + <div class="row"> 295 + <p>highest = L.maximumBy (comparing snd) . M.toList</p> 296 + <div class="code"> 297 + 298 + </div> 299 + </div> 300 + <div class="row"> 301 + <p>lowest = L.minimumBy (comparing snd) . M.toList</p> 302 + <div class="code"> 303 + 304 + </div> 305 + </div> 306 + <div class="row"> 307 + <p>p1 = map (fst . highest . freqs)</p> 308 + <div class="code"> 309 + 310 + </div> 311 + </div> 312 + <div class="row"> 313 + <p>p2 = map (fst . lowest . freqs)</p> 314 + <div class="code"> 315 + 316 + </div> 317 + </div> 318 + <div class="row"> 319 + <p>main = do args &lt;- getArgs n &lt;- case args of [“-”] -&gt; 320 + getContents [file] -&gt; readFile file let f = L.transpose $ lines 321 + n putStrLn $ p1 f putStrLn $ p2 f</p> 322 + <div class="code"> 323 + 324 + </div> 325 + </div> 326 + <div class="row"> 327 + <p>import qualified Data.Char as C import System.Environment 328 + (getArgs)</p> 329 + <div class="code"> 330 + 331 + </div> 332 + </div> 333 + <div class="row"> 334 + <p>main = do args &lt;- getArgs n &lt;- case args of [“-”] -&gt; 335 + getContents [file] -&gt; readFile file let f = map C.digitToInt $ 336 + init n l = length f print $ sum $ map fst $ filter (uncurry (==)) 337 + $ zip f (tail f ++ [head f]) print $ sum $ map fst $ filter 338 + (uncurry (==)) $ zip f (drop (l <code>div</code> 2) (cycle f))</p> 339 + <div class="code"> 340 + 341 + </div> 342 + </div> 343 + <div class="row"> 344 + <p>import Control.Arrow ((&amp;&amp;&amp;)) import Data.List 345 + (maximum, minimum) import Data.List.Split (splitOn) import 346 + System.Environment (getArgs)</p> 347 + <div class="code"> 348 + 349 + </div> 350 + </div> 351 + <div class="row"> 352 + <p>parse = map read . splitOn “</p> 353 + <div class="code"> 354 + 355 + </div> 356 + </div> 357 + <div class="row"> 358 + <p>checksum = uncurry (-) . (maximum &amp;&amp;&amp; minimum)</p> 359 + <div class="code"> 360 + 361 + </div> 362 + </div> 363 + <div class="row"> 364 + <p>divisible ls = sum [x <code>div</code> y | x &lt;- ls, y &lt;- 365 + ls, x <code>rem</code> y == 0, x /= y]</p> 366 + <div class="code"> 367 + 368 + </div> 369 + </div> 370 + <div class="row"> 371 + <p>p1 = sum . map checksum</p> 372 + <div class="code"> 373 + 374 + </div> 375 + </div> 376 + <div class="row"> 377 + <p>p2 = sum . map divisible</p> 378 + <div class="code"> 379 + 380 + </div> 381 + </div> 382 + <div class="row"> 383 + <p>main = do args &lt;- getArgs n &lt;- case args of [“-”] -&gt; 384 + getContents [file] -&gt; readFile file let f = map parse $ lines n 385 + print $ p1 f print $ p2 f</p> 386 + <div class="code"> 387 + 388 + </div> 389 + </div> 390 + <div class="row"> 391 + <p>import Data.List (maximum, minimum) import Data.List.Split 392 + (splitOn) import System.Environment (getArgs)</p> 393 + <div class="code"> 394 + 395 + </div> 396 + </div> 397 + <div class="row"> 398 + <p>ring = toInteger . ceiling . (/ 2) . subtract 1 . sqrt . 399 + fromInteger</p> 400 + <div class="code"> 401 + 402 + </div> 403 + </div> 404 + <div class="row"> 405 + <p>p1 n = curr + mid where curr = ring n prev = (2 * curr - 1) ^ 2 406 + mid = minimum $ map (abs . subtract n . (+ prev) . (* curr)) [1, 407 + 3, 5, 7]</p> 408 + <div class="code"> 409 + 410 + </div> 411 + </div> 412 + <div class="row"> 413 + <p>main = do args &lt;- getArgs n &lt;- case args of [“-”] -&gt; 414 + getContents [file] -&gt; readFile file let f = read $ init n print 415 + $ p1 f</p> 416 + <div class="code"> 417 + 418 + </div> 419 + </div> 420 + <div class="row"> 421 + <p>{-# LANGUAGE LambdaCase #-}</p> 422 + <div class="code"> 423 + 424 + </div> 425 + </div> 426 + <div class="row"> 427 + <p>import qualified Data.Set as S import System.Environment 428 + (getArgs)</p> 429 + <div class="code"> 430 + 431 + </div> 432 + </div> 433 + <div class="row"> 434 + <p>parse :: String -&gt; Int parse (‘+’ : f) = read f parse f = 435 + read f</p> 436 + <div class="code"> 437 + 438 + </div> 439 + </div> 440 + <div class="row"> 441 + <p>p1 = sum</p> 442 + <div class="code"> 443 + 444 + </div> 445 + </div> 446 + <div class="row"> 447 + <p>p2 n = firstDup $ scanl1 (+) (cycle n)</p> 448 + <div class="code"> 449 + 450 + </div> 451 + </div> 452 + <div class="row"> 453 + <p>firstDup = go S.empty where go seen (x : xs) = if S.member x 454 + seen then x else go (S.insert x seen) xs</p> 455 + <div class="code"> 456 + 457 + </div> 458 + </div> 459 + <div class="row"> 460 + <p>main = do n &lt;- fmap (map parse . lines) $ getArgs &gt;&gt;= 461 + -&gt; getContents [file] -&gt; readFile file print $ p1 n print $ 462 + p2 n</p> 463 + <div class="code"> 464 + 465 + </div> 466 + </div> 467 + <div class="row"> 468 + <p>{-# LANGUAGE LambdaCase #-}</p> 469 + <div class="code"> 470 + 471 + </div> 472 + </div> 473 + <div class="row"> 474 + <p>import qualified Data.Map as M import System.Environment 475 + (getArgs)</p> 476 + <div class="code"> 477 + 478 + </div> 479 + </div> 480 + <div class="row"> 481 + <p>freqs = M.fromListWith (+) . map (,1)</p> 482 + <div class="code"> 483 + 484 + </div> 485 + </div> 486 + <div class="row"> 487 + <p>p1 n = occurs 2 fqs * occurs 3 fqs where fqs = map freqs n 488 + occurs n = length . filter (not . M.null . M.filter (== n))</p> 489 + <div class="code"> 490 + 491 + </div> 492 + </div> 493 + <div class="row"> 494 + <p>lev x y = sum [1 | (a, b) &lt;- zip x y, a /= b]</p> 495 + <div class="code"> 496 + 497 + </div> 498 + </div> 499 + <div class="row"> 500 + <p>p2 n = [(a, b) | a &lt;- n, b &lt;- n, a /= b, lev a b == 501 + 1]</p> 502 + <div class="code"> 503 + 504 + </div> 505 + </div> 506 + <div class="row"> 507 + <p>main = do n &lt;- fmap lines $ getArgs &gt;&gt;= -&gt; 508 + getContents [file] -&gt; readFile file print $ p1 n print $ p2 509 + n</p> 510 + <div class="code"> 511 + 512 + </div> 513 + </div> 514 + <div class="row"> 515 + <p>{-# LANGUAGE LambdaCase #-}</p> 516 + <div class="code"> 517 + 518 + </div> 519 + </div> 520 + <div class="row"> 521 + <p>import Data.List.Split (splitOn) import qualified Data.Map as M 522 + import qualified Data.Set as S import System.Environment 523 + (getArgs)</p> 524 + <div class="code"> 525 + 526 + </div> 527 + </div> 528 + <div class="row"> 529 + <p>parse :: String -&gt; (Int, (Int, Int), (Int, Int)) parse l = 530 + (read (tail a), (read x, read y), (read w, read h)) where [a, b, 531 + c, d] = splitOn ” ” l [x, y] = splitOn “,” (init c) [w, h] = 532 + splitOn “x” d</p> 533 + <div class="code"> 534 + 535 + </div> 536 + </div> 537 + <div class="row"> 538 + <p>grid = M.fromList [ ((x, y), []) | x &lt;- [0 .. 999], y &lt;- 539 + [0 .. 999] ]</p> 540 + <div class="code"> 541 + 542 + </div> 543 + </div> 544 + <div class="row"> 545 + <p>claim grid (id, (x, y), (w, h)) = foldl conv grid subgrid where 546 + subgrid = [(x’, y’) | x’ &lt;- [x .. x + w - 1], y’ &lt;- [y .. y 547 + + h - 1]] conv g (x’, y’) = M.adjust (id :) (x’, y’) g</p> 548 + <div class="code"> 549 + 550 + </div> 551 + </div> 552 + <div class="row"> 553 + <p>p1 n = M.size $ M.filter ((&gt; 1) . length) $ foldl claim grid 554 + n</p> 555 + <div class="code"> 556 + 557 + </div> 558 + </div> 559 + <div class="row"> 560 + <p>(-|-) x y = (x S.\ y) <code>S.union</code> (y S.\ x)</p> 561 + <div class="code"> 562 + 563 + </div> 564 + </div> 565 + <div class="row"> 566 + <p>p2 n = a -|- seen where a = S.fromList $ map ((a, <em>, </em>) 567 + -&gt; a) n seen = foldl1 S.union $ map S.fromList $ M.elems $ 568 + M.filter ((&gt; 1) . length) $ foldl claim grid n</p> 569 + <div class="code"> 570 + 571 + </div> 572 + </div> 573 + <div class="row"> 574 + <p>main = do n &lt;- fmap (map parse . lines) $ getArgs &gt;&gt;= 575 + -&gt; getContents [file] -&gt; readFile file print $ p1 n print $ 576 + p2 n</p> 577 + <div class="code"> 578 + 579 + </div> 580 + </div> 581 + <div class="row"> 582 + <p>import System.Environment (getArgs)</p> 583 + <div class="code"> 584 + 585 + </div> 586 + </div> 587 + <div class="row"> 588 + <p>p1 l = head [a * b | a &lt;- l, b &lt;- l, a + b == 2020]</p> 589 + <div class="code"> 590 + 591 + </div> 592 + </div> 593 + <div class="row"> 594 + <p>p2 l = head [a * b * c | a &lt;- l, b &lt;- l, c &lt;- l, a + b 595 + + c == 2020]</p> 596 + <div class="code"> 597 + 598 + </div> 599 + </div> 600 + <div class="row"> 601 + <p>main = do args &lt;- getArgs n &lt;- case args of [“-”] -&gt; 602 + getContents [file] -&gt; readFile file let f = map read $ lines n 603 + print $ p1 f print $ p2 f</p> 604 + <div class="code"> 605 + 606 + </div> 607 + </div> 608 + <div class="row"> 609 + <p>import Data.Bits (xor) import Data.List.Split (splitOn) import 610 + System.Environment (getArgs)</p> 611 + <div class="code"> 612 + 613 + </div> 614 + </div> 615 + <div class="row"> 616 + <p>parse i = (read l, read h, c’, p) where [r, c, p] = splitOn ” ” 617 + i [l, h] = splitOn “-” r c’ = head c</p> 618 + <div class="code"> 619 + 620 + </div> 621 + </div> 622 + <div class="row"> 623 + <p>p1 = length . filter id . map solve where solve (l, u, c, p) = 624 + all ($ length $ filter (== c) p) [(&gt;= l), (&lt;= u)]</p> 625 + <div class="code"> 626 + 627 + </div> 628 + </div> 629 + <div class="row"> 630 + <p>p2 = length . filter id . map solve where solve (l, u, c, p) = 631 + foldl1 xor $ map ((== c) . (p !!) . subtract 1) [l, u]</p> 632 + <div class="code"> 633 + 634 + </div> 635 + </div> 636 + <div class="row"> 637 + <p>main = do args &lt;- getArgs n &lt;- case args of [“-”] -&gt; 638 + getContents [file] -&gt; readFile file let f = map parse $ lines n 639 + print $ p1 f print $ p2 f</p> 640 + <div class="code"> 641 + 642 + </div> 643 + </div> 644 + <div class="row"> 645 + <p>import System.Environment (getArgs)</p> 646 + <div class="code"> 647 + 648 + </div> 649 + </div> 650 + <div class="row"> 651 + <p>countTrees right down ls = go (map cycle ls) where go [] = 0 go 652 + remaining@(r : rs) = fromEnum (head r == ‘#’) + go (map (drop 653 + right) (drop down remaining))</p> 654 + <div class="code"> 655 + 656 + </div> 657 + </div> 658 + <div class="row"> 659 + <p>p1 = countTrees 3 1</p> 660 + <div class="code"> 661 + 662 + </div> 663 + </div> 664 + <div class="row"> 665 + <p>p2 n = product [ countTrees 1 1 n, countTrees 3 1 n, countTrees 666 + 5 1 n, countTrees 7 1 n, countTrees 1 2 n ]</p> 667 + <div class="code"> 668 + 669 + </div> 670 + </div> 671 + <div class="row"> 672 + <p>main = do args &lt;- getArgs n &lt;- case args of [“-”] -&gt; 673 + getContents [file] -&gt; readFile file let f = lines n print $ p1 674 + f print $ p2 f</p> 675 + <div class="code"> 676 + 677 + </div> 678 + </div> 679 + <div class="row"> 680 + <p>module Main where</p> 681 + <div class="code"> 682 + 683 + </div> 684 + </div> 685 + <div class="row"> 686 + <p>import Data.Char (isDigit, isHexDigit) import Data.Map.Strict 687 + (Map, (!)) import qualified Data.Map.Strict as Map import 688 + System.Environment (getArgs) import 689 + Text.ParserCombinators.Parsec</p> 690 + <div class="code"> 691 + 692 + </div> 693 + </div> 694 + <div class="row"> 695 + <p>bet k (l, u) = k &gt;= l &amp;&amp; k &lt;= u</p> 696 + <div class="code"> 697 + 698 + </div> 699 + </div> 700 + <div class="row"> 701 + <p>right (Right b) = b</p> 702 + <div class="code"> 703 + 704 + </div> 705 + </div> 706 + <div class="row"> 707 + <p>requiredFields = [“byr”, “iyr”, “eyr”, “hgt”, “hcl”, “ecl”, 708 + “pid”]</p> 709 + <div class="code"> 710 + 711 + </div> 712 + </div> 713 + <div class="row"> 714 + <p>eyeColors = [“amb”, “blu”, “brn”, “gry”, “grn”, “hzl”, 715 + “oth”]</p> 716 + <div class="code"> 717 + 718 + </div> 719 + </div> 720 + <div class="row"> 721 + <p>block = cell <code>sepBy</code> oneOf ” ”</p> 722 + <div class="code"> 723 + 724 + </div> 725 + </div> 726 + <div class="row"> 727 + <p>cell = do tag &lt;- many lower char ‘:’ rest &lt;- many 728 + (alphaNum &lt;|&gt; char ‘#’) return (tag, rest)</p> 729 + <div class="code"> 730 + 731 + </div> 732 + </div> 733 + <div class="row"> 734 + <p>parseInput :: String -&gt; Either ParseError (Map String 735 + String) parseInput s = Map.fromList &lt;$&gt; parse block “input” 736 + s</p> 737 + <div class="code"> 738 + 739 + </div> 740 + </div> 741 + <div class="row"> 742 + <p>doCheck :: Map String String -&gt; Bool doCheck ls = all 743 + (<code>Map.member</code> ls) requiredFields</p> 744 + <div class="code"> 745 + 746 + </div> 747 + </div> 748 + <div class="row"> 749 + <p>validByr s = bet (read s :: Int) (1920, 2002)</p> 750 + <div class="code"> 751 + 752 + </div> 753 + </div> 754 + <div class="row"> 755 + <p>validIyr s = bet (read s :: Int) (2010, 2020)</p> 756 + <div class="code"> 757 + 758 + </div> 759 + </div> 760 + <div class="row"> 761 + <p>validEyr s = bet (read s :: Int) (2020, 2030)</p> 762 + <div class="code"> 763 + 764 + </div> 765 + </div> 766 + <div class="row"> 767 + <p>validEcl = flip elem eyeColors</p> 768 + <div class="code"> 769 + 770 + </div> 771 + </div> 772 + <div class="row"> 773 + <p>validPid s = length s == 9 &amp;&amp; all isDigit s</p> 774 + <div class="code"> 775 + 776 + </div> 777 + </div> 778 + <div class="row"> 779 + <p>validHcl (‘#’ : rest) = length rest == 6 &amp;&amp; all 780 + isHexDigit rest validHcl _ = False</p> 781 + <div class="code"> 782 + 783 + </div> 784 + </div> 785 + <div class="row"> 786 + <p>validHgt s = let value = takeWhile isDigit s unit = dropWhile 787 + isDigit s height = (read value :: Int, unit) in case height of (v, 788 + “cm”) -&gt; bet v (150, 193) (v, “in”) -&gt; bet v (59, 76) _ 789 + -&gt; False</p> 790 + <div class="code"> 791 + 792 + </div> 793 + </div> 794 + <div class="row"> 795 + <p>doValidate :: Map String String -&gt; Bool doValidate map = all 796 + ((s, v) -&gt; v $ map ! s) ls where ls = [ (“byr”, validByr), 797 + (“iyr”, validIyr), (“eyr”, validEyr), (“hgt”, validHgt), (“hcl”, 798 + validHcl), (“ecl”, validEcl), (“pid”, validPid) ]</p> 799 + <div class="code"> 800 + 801 + </div> 802 + </div> 803 + <div class="row"> 804 + <p>parseLines :: [String] -&gt; [String] parseLines allLines = 805 + unwords first : next where (first, rest) = break null allLines 806 + next = if null rest then [] else parseLines (tail rest)</p> 807 + <div class="code"> 808 + 809 + </div> 810 + </div> 811 + <div class="row"> 812 + <p>p1 = length . filter doCheck</p> 813 + <div class="code"> 814 + 815 + </div> 816 + </div> 817 + <div class="row"> 818 + <p>p2 = length . filter doValidate . filter doCheck</p> 819 + <div class="code"> 820 + 821 + </div> 822 + </div> 823 + <div class="row"> 824 + <p>main = do args &lt;- getArgs n &lt;- case args of [“-”] -&gt; 825 + getContents [file] -&gt; readFile file let f = parseLines $ lines 826 + n let blocks = map (right . parseInput) f print $ p1 blocks print 827 + $ p2 blocks</p> 828 + <div class="code"> 829 + 830 + </div> 831 + </div> 832 + <div class="row"> 833 + <p>module Main where</p> 834 + <div class="code"> 835 + 836 + </div> 837 + </div> 838 + <div class="row"> 839 + <p>import Data.Char (digitToInt) import Data.List (sort) import 840 + System.Environment (getArgs)</p> 841 + <div class="code"> 842 + 843 + </div> 844 + </div> 845 + <div class="row"> 846 + <p>binaryToInt = foldl (x -&gt; a * 2 + digitToInt x) 0</p> 847 + <div class="code"> 848 + 849 + </div> 850 + </div> 851 + <div class="row"> 852 + <p>doValidate = binaryToInt . map readBin</p> 853 + <div class="code"> 854 + 855 + </div> 856 + </div> 857 + <div class="row"> 858 + <p>readBin s | s <code>elem</code> “FL” = ‘0’ | otherwise = 859 + ‘1’</p> 860 + <div class="code"> 861 + 862 + </div> 863 + </div> 864 + <div class="row"> 865 + <p>p1 = maximum . sort . map doValidate</p> 866 + <div class="code"> 867 + 868 + </div> 869 + </div> 870 + <div class="row"> 871 + <p>p2 = (+ 1) . fst . head . dropWhile ((== 1) . uncurry subtract) 872 + . (zip &lt;*&gt; tail) . sort . map doValidate</p> 873 + <div class="code"> 874 + 875 + </div> 876 + </div> 877 + <div class="row"> 878 + <p>main = do args &lt;- getArgs n &lt;- case args of [“-”] -&gt; 879 + getContents [file] -&gt; readFile file let f = lines n print $ p1 880 + f print $ p2 f</p> 881 + <div class="code"> 882 + 883 + </div> 884 + </div> 885 + <div class="row"> 886 + <p>import Data.List.Split (splitOn) import Data.Set (Set) import 887 + qualified Data.Set as Set import System.Environment (getArgs)</p> 888 + <div class="code"> 889 + 890 + </div> 891 + </div> 892 + <div class="row"> 893 + <p>p1 = sum . map (Set.size . Set.fromList . filter (/= ‘’))</p> 894 + <div class="code"> 895 + 896 + </div> 897 + </div> 898 + <div class="row"> 899 + <p>p2 = sum . map (Set.size . foldl1 Set.intersection . map 900 + Set.fromList . words)</p> 901 + <div class="code"> 902 + 903 + </div> 904 + </div> 905 + <div class="row"> 906 + <p>main = do args &lt;- getArgs n &lt;- case args of [“-”] -&gt; 907 + getContents [file] -&gt; readFile file let f = splitOn “” n print 908 + $ p1 f print $ p2 f</p> 909 + <div class="code"> 910 + 911 + </div> 912 + </div> 913 + <div class="row"> 914 + <p>import Data.Map (Map) import qualified Data.Map as Map import 915 + System.Environment (getArgs)</p> 916 + <div class="code"> 917 + 918 + </div> 919 + </div> 920 + <div class="row"> 921 + <p>myBag = “shiny gold”</p> 922 + <div class="code"> 923 + 924 + </div> 925 + </div> 926 + <div class="row"> 927 + <p>parseContained [] = [] parseContained (“no” : <em>) = [] 928 + parseContained (count : b : c : </em> : rest) = (read count, 929 + unwords [b, c]) : parseContained rest</p> 930 + <div class="code"> 931 + 932 + </div> 933 + </div> 934 + <div class="row"> 935 + <p>parseLine s = (leadingBag, parseContained trailingBags) where 936 + leadingBag = unwords (take 2 s) trailingBags = drop 4 s</p> 937 + <div class="code"> 938 + 939 + </div> 940 + </div> 941 + <div class="row"> 942 + <p>canContain m outer = myBag <code>elem</code> inners || any 943 + (canContain m) inners where inners = map snd $ m Map.! outer</p> 944 + <div class="code"> 945 + 946 + </div> 947 + </div> 948 + <div class="row"> 949 + <p>countNested s m = foldl ((c, b) -&gt; acc + c * (1 + 950 + countNested b m)) 0 $ m Map.! s</p> 951 + <div class="code"> 952 + 953 + </div> 954 + </div> 955 + <div class="row"> 956 + <p>p1 q = length $ filter (canContain q . fst) $ Map.toList q</p> 957 + <div class="code"> 958 + 959 + </div> 960 + </div> 961 + <div class="row"> 962 + <p>p2 = countNested myBag</p> 963 + <div class="code"> 964 + 965 + </div> 966 + </div> 967 + <div class="row"> 968 + <p>main = do args &lt;- getArgs n &lt;- case args of [“-”] -&gt; 969 + getContents [file] -&gt; readFile file let f = map (parseLine . 970 + words) $ lines n let q = Map.fromList f print $ p1 q print $ p2 971 + q</p> 972 + <div class="code"> 973 + 974 + </div> 975 + </div> 976 + <div class="row"> 977 + <p>module Main where</p> 978 + <div class="code"> 979 + 980 + </div> 981 + </div> 982 + <div class="row"> 983 + <p>import Data.Map (Map) import qualified Data.Map as Map import 984 + Data.Set (Set) import qualified Data.Set as Set import 985 + System.Environment (getArgs)</p> 986 + <div class="code"> 987 + 988 + </div> 989 + </div> 990 + <div class="row"> 991 + <p>type Op = (String, Int)</p> 992 + <div class="code"> 993 + 994 + </div> 995 + </div> 996 + <div class="row"> 997 + <p>parseLine :: [String] -&gt; Op parseLine [s, j] = (s, read 998 + (dropWhile (== ‘+’) j))</p> 999 + <div class="code"> 1000 + 1001 + </div> 1002 + </div> 1003 + <div class="row"> 1004 + <p>run :: Int -&gt; Int -&gt; Set Int -&gt; Map Int Op -&gt; Int 1005 + run acc pc visited operations = if Set.member pc visited then acc 1006 + else handleCase where visited’ = Set.insert pc visited handleCase 1007 + = case Map.lookup pc operations of Just (“acc”, v) -&gt; run (acc 1008 + + v) (pc + 1) visited’ operations Just (“nop”, <em>) -&gt; run acc 1009 + (pc + 1) visited’ operations Just (“jmp”, j) -&gt; run acc (pc + 1010 + j) visited’ operations </em> -&gt; acc</p> 1011 + <div class="code"> 1012 + 1013 + </div> 1014 + </div> 1015 + <div class="row"> 1016 + <p>doesEnd :: Int -&gt; Int -&gt; Set Int -&gt; Map Int Op -&gt; 1017 + Bool doesEnd acc pc visited operations = not (Set.member pc 1018 + visited) &amp;&amp; handleCase where visited’ = Set.insert pc 1019 + visited handleCase = case Map.lookup pc operations of Just (“acc”, 1020 + v) -&gt; doesEnd (acc + v) (pc + 1) visited’ operations Just 1021 + (“nop”, <em>) -&gt; doesEnd acc (pc + 1) visited’ operations Just 1022 + (“jmp”, j) -&gt; doesEnd acc (pc + j) visited’ operations </em> 1023 + -&gt; True – pc has crossed the end!</p> 1024 + <div class="code"> 1025 + 1026 + </div> 1027 + </div> 1028 + <div class="row"> 1029 + <p>genAll :: [Op] -&gt; [[Op]] genAll [] = [] genAll (n@(“nop”, v) 1030 + : rest) = ((“jmp”, v) : rest) : map (n :) (genAll rest) genAll 1031 + (j@(“jmp”, v) : rest) = ((“nop”, v) : rest) : map (j :) (genAll 1032 + rest) genAll (acc : rest) = map (acc :) $ genAll rest</p> 1033 + <div class="code"> 1034 + 1035 + </div> 1036 + </div> 1037 + <div class="row"> 1038 + <p>p1 = run 0 0 mempty . Map.fromList . zip [0 ..]</p> 1039 + <div class="code"> 1040 + 1041 + </div> 1042 + </div> 1043 + <div class="row"> 1044 + <p>p2 = p1 . head . filter (doesEnd 0 0 mempty . Map.fromList . 1045 + zip [0 ..]) . genAll</p> 1046 + <div class="code"> 1047 + 1048 + </div> 1049 + </div> 1050 + <div class="row"> 1051 + <p>main = do args &lt;- getArgs n &lt;- case args of [“-”] -&gt; 1052 + getContents [file] -&gt; readFile file let f = map (parseLine . 1053 + words) $ lines n print $ p1 f print $ p2 f</p> 1054 + <div class="code"> 1055 + 1056 + </div> 1057 + </div> 1058 + <div class="row"> 1059 + <p>import Data.Bifunctor import Data.List (find, inits, sort, 1060 + tails) import System.Environment (getArgs)</p> 1061 + <div class="code"> 1062 + 1063 + </div> 1064 + </div> 1065 + <div class="row"> 1066 + <p>sublists = concatMap inits . tails</p> 1067 + <div class="code"> 1068 + 1069 + </div> 1070 + </div> 1071 + <div class="row"> 1072 + <p>windows m = foldr (zipWith (:)) (repeat []) . take m . 1073 + tails</p> 1074 + <div class="code"> 1075 + 1076 + </div> 1077 + </div> 1078 + <div class="row"> 1079 + <p>doCheck preamble target = target <code>elem</code> [x + y | x 1080 + &lt;- preamble, y &lt;- preamble, x /= y]</p> 1081 + <div class="code"> 1082 + 1083 + </div> 1084 + </div> 1085 + <div class="row"> 1086 + <p>checkAll = zipWith (t -&gt; (t, doCheck p t))</p> 1087 + <div class="code"> 1088 + 1089 + </div> 1090 + </div> 1091 + <div class="row"> 1092 + <p>findWeakness subs target = minimum t + maximum t where Just t = 1093 + find ((== target) . sum) subs</p> 1094 + <div class="code"> 1095 + 1096 + </div> 1097 + </div> 1098 + <div class="row"> 1099 + <p>p1 f = find (not . snd) $ checkAll (windows 25 f) (drop 25 1100 + f)</p> 1101 + <div class="code"> 1102 + 1103 + </div> 1104 + </div> 1105 + <div class="row"> 1106 + <p>p2 f = findWeakness (sublists f) target where Just (target, _) 1107 + = p1 f</p> 1108 + <div class="code"> 1109 + 1110 + </div> 1111 + </div> 1112 + <div class="row"> 1113 + <p>main = do args &lt;- getArgs n &lt;- map read . lines &lt;$&gt; 1114 + case args of [“-”] -&gt; getContents [file] -&gt; readFile file 1115 + print $ p1 n print $ p2 n</p> 1116 + <div class="code"> 1117 + 1118 + </div> 1119 + </div> 1120 + <div class="row"> 1121 + <p>import Control.Monad.Memo import Data.List (sort) import 1122 + System.Environment (getArgs)</p> 1123 + <div class="code"> 1124 + 1125 + </div> 1126 + </div> 1127 + <div class="row"> 1128 + <p>p1 s = product $ ($ q s) &lt;$&gt; [length . filter (== 1), 1129 + length . filter (== 3)] where q = zipWith subtract &lt;*&gt; 1130 + tail</p> 1131 + <div class="code"> 1132 + 1133 + </div> 1134 + </div> 1135 + <div class="row"> 1136 + <p>p2 top s = startEvalMemo $ go 0 where go c | c == top = return 1137 + 1 | otherwise = sum &lt;$&gt; mapM (memo go) (filter 1138 + (<code>elem</code> s) $ map (+ c) [1, 2, 3])</p> 1139 + <div class="code"> 1140 + 1141 + </div> 1142 + </div> 1143 + <div class="row"> 1144 + <p>main = do args &lt;- getArgs n &lt;- map read . lines &lt;$&gt; 1145 + case args of [“-”] -&gt; getContents [file] -&gt; readFile file 1146 + let top = maximum n + 3 ls = sort (0 : top : n) print $ p1 ls 1147 + print $ p2 top ls</p> 1148 + <div class="code"> 1149 + 1150 + </div> 1151 + </div> 1152 + <div class="row"> 1153 + <p>import Data.List (sortOn) import Data.Map (Map, (!)) import 1154 + qualified Data.Map as Map import Data.Maybe import 1155 + System.Environment (getArgs)</p> 1156 + <div class="code"> 1157 + 1158 + </div> 1159 + </div> 1160 + <div class="row"> 1161 + <p>dirs = [ (-1, -1), (0, -1), (1, -1), (-1, 0), (1, 0), (-1, 1), 1162 + (0, 1), (1, 1) ]</p> 1163 + <div class="code"> 1164 + 1165 + </div> 1166 + </div> 1167 + <div class="row"> 1168 + <p>makeGrid s = (grid, width, height) where rows = lines s grid = 1169 + Map.fromList [((x, y), a) | (y, row) &lt;- zip [0 ..] rows, (x, a) 1170 + &lt;- zip [0 ..] row] width = length (head rows) height = length 1171 + rows</p> 1172 + <div class="code"> 1173 + 1174 + </div> 1175 + </div> 1176 + <div class="row"> 1177 + <p>adjs1 m pt = length $ filter (== ‘#’) $ mapMaybe 1178 + ((<code>Map.lookup</code> m) . add pt) dirs</p> 1179 + <div class="code"> 1180 + 1181 + </div> 1182 + </div> 1183 + <div class="row"> 1184 + <p>inGrid (x, y) w h = x &lt; w &amp;&amp; x &gt;= 0 &amp;&amp; y 1185 + &lt; h &amp;&amp; y &gt;= 0</p> 1186 + <div class="code"> 1187 + 1188 + </div> 1189 + </div> 1190 + <div class="row"> 1191 + <p>add (x, y) (a, b) = (x + a, y + b)</p> 1192 + <div class="code"> 1193 + 1194 + </div> 1195 + </div> 1196 + <div class="row"> 1197 + <p>– [f, f.f, f.f.f, …] repeatF f = f : map (f .) (repeatF f)</p> 1198 + <div class="code"> 1199 + 1200 + </div> 1201 + </div> 1202 + <div class="row"> 1203 + <p>bet k (l, u) = k &gt;= l &amp;&amp; k &lt;= u</p> 1204 + <div class="code"> 1205 + 1206 + </div> 1207 + </div> 1208 + <div class="row"> 1209 + <p>inside (p, q) (r, s) (a, b) = bet a (p, r) &amp;&amp; bet b (q, 1210 + s)</p> 1211 + <div class="code"> 1212 + 1213 + </div> 1214 + </div> 1215 + <div class="row"> 1216 + <p>adjs2 grid pt w h = length $ filter ((== ‘#’) . head) $ filter 1217 + (not . null) $ map ( dropWhile (== ‘.’) . map (grid !) . takeWhile 1218 + (inside (0, 0) (w - 1, h - 1)) . map ($ pt) . repeatF . add ) 1219 + dirs</p> 1220 + <div class="code"> 1221 + 1222 + </div> 1223 + </div> 1224 + <div class="row"> 1225 + <p>rule1 w h m pt@(x, y) = if as == 0 then ‘#’ else ‘L’ where as = 1226 + adjs2 m pt w h</p> 1227 + <div class="code"> 1228 + 1229 + </div> 1230 + </div> 1231 + <div class="row"> 1232 + <p>rule2 w h m pt@(x, y) = if as &gt;= 5 then ‘L’ else ‘#’ where 1233 + as = adjs2 m pt w h</p> 1234 + <div class="code"> 1235 + 1236 + </div> 1237 + </div> 1238 + <div class="row"> 1239 + <p>doStep w h m = Map.mapWithKey fn m where fn k ‘L’ = rule1 w h m 1240 + k fn k ‘#’ = rule2 w h m k fn k ‘.’ = ‘.’</p> 1241 + <div class="code"> 1242 + 1243 + </div> 1244 + </div> 1245 + <div class="row"> 1246 + <p>stepWhile prev w h | prev == next = next | otherwise = 1247 + stepWhile next w h where next = doStep w h prev</p> 1248 + <div class="code"> 1249 + 1250 + </div> 1251 + </div> 1252 + <div class="row"> 1253 + <p>main = do args &lt;- getArgs n &lt;- case args of [“-”] -&gt; 1254 + getContents [file] -&gt; readFile file let (grid, width, height) = 1255 + makeGrid n let solve1 = stepWhile grid width height print $ length 1256 + $ filter ((== ‘#’) . snd) $ Map.toList solve1</p> 1257 + <div class="code"> 1258 + 1259 + </div> 1260 + </div> 1261 + <div class="row"> 1262 + <p>import System.Environment (getArgs)</p> 1263 + <div class="code"> 1264 + 1265 + </div> 1266 + </div> 1267 + <div class="row"> 1268 + <p>parseLine s = (head s, read (tail s) :: Float)</p> 1269 + <div class="code"> 1270 + 1271 + </div> 1272 + </div> 1273 + <div class="row"> 1274 + <p>rotate (x, y) t = (nx, ny) where nx = x * cos (pi * t / 180) - 1275 + y * sin (pi * t / 180) ny = x * sin (pi * t / 180) + y * cos (pi * 1276 + t / 180)</p> 1277 + <div class="code"> 1278 + 1279 + </div> 1280 + </div> 1281 + <div class="row"> 1282 + <p>p1 ls = sum $ map (round . abs) [fx, fy] where (fx, fy, _) = 1283 + foldl fn (0.0, 0.0, 0.0) ls fn (x, y, rot) (‘N’, v) = (x, y + v, 1284 + rot) fn (x, y, rot) (‘E’, v) = (x + v, y, rot) fn (x, y, rot) 1285 + (‘W’, v) = (x - v, y, rot) fn (x, y, rot) (‘S’, v) = (x, y - v, 1286 + rot) fn (x, y, rot) (‘R’, v) = (x, y, rot - v) fn (x, y, rot) 1287 + (‘L’, v) = (x, y, rot + v) fn (x, y, rot) (‘F’, v) = (nx, ny, rot) 1288 + where nx = x + v * cos (pi * rot / 180) ny = y + v * sin (pi * rot 1289 + / 180)</p> 1290 + <div class="code"> 1291 + 1292 + </div> 1293 + </div> 1294 + <div class="row"> 1295 + <p>p2 (sx, sy) ls = sum $ map (round . abs) [fx, fy] where (fx, 1296 + fy, <em>, </em>) = foldl fn (0.0, 0.0, sx, sy) ls fn (x, y, wx, 1297 + wy) (‘N’, v) = (x, y, wx, wy + v) fn (x, y, wx, wy) (‘E’, v) = (x, 1298 + y, wx + v, wy) fn (x, y, wx, wy) (‘W’, v) = (x, y, wx - v, wy) fn 1299 + (x, y, wx, wy) (‘S’, v) = (x, y, wx, wy - v) fn (x, y, wx, wy) 1300 + (‘R’, v) = (x, y, nwx, nwy) where (nwx, nwy) = rotate (wx, wy) 1301 + (negate v) fn (x, y, wx, wy) (‘L’, v) = (x, y, nwx, nwy) where 1302 + (nwx, nwy) = rotate (wx, wy) v fn (x, y, wx, wy) (‘F’, v) = (x + v 1303 + * wx, y + v * wy, wx, wy)</p> 1304 + <div class="code"> 1305 + 1306 + </div> 1307 + </div> 1308 + <div class="row"> 1309 + <p>main = do args &lt;- getArgs n &lt;- map parseLine . lines 1310 + &lt;$&gt; case args of [“-”] -&gt; getContents [file] -&gt; 1311 + readFile file print $ p1 n print $ p2 (10.0, 1.0) n</p> 1312 + <div class="code"> 1313 + 1314 + </div> 1315 + </div> 1316 + <div class="row"> 1317 + <p>import Control.Monad (ap, zipWithM) import Data.Bifunctor 1318 + import Data.List (sortOn) import Data.List.Split import Data.Tuple 1319 + import System.Environment (getArgs)</p> 1320 + <div class="code"> 1321 + 1322 + </div> 1323 + </div> 1324 + <div class="row"> 1325 + <p>egcd _ 0 = (1, 0) egcd a b = (t, s - q * t) where (s, t) = egcd 1326 + b r (q, r) = a <code>quotRem</code> b</p> 1327 + <div class="code"> 1328 + 1329 + </div> 1330 + </div> 1331 + <div class="row"> 1332 + <p>modInv a b = case egcd a b of (x, y) | a * x + b * y == 1 -&gt; 1333 + Just x | otherwise -&gt; Nothing</p> 1334 + <div class="code"> 1335 + 1336 + </div> 1337 + </div> 1338 + <div class="row"> 1339 + <p>– from rosetta code chineseRemainder ls = zipWithM modInv 1340 + crtModulii modulii &gt;&gt;= (Just . (<code>mod</code> modPI) . 1341 + sum . zipWith (<em>) crtModulii . zipWith (</em>) residues) where 1342 + residues = map fst ls modulii = map snd ls modPI = product modulii 1343 + crtModulii = (modPI <code>div</code>) &lt;$&gt; modulii</p> 1344 + <div class="code"> 1345 + 1346 + </div> 1347 + </div> 1348 + <div class="row"> 1349 + <p>earliest start ls = t * b where (t, b) = minimum $ map swap $ 1350 + zip <code>ap</code> map (mod start) $ ls</p> 1351 + <div class="code"> 1352 + 1353 + </div> 1354 + </div> 1355 + <div class="row"> 1356 + <p>p1 n = earliest (negate start) departs where start = read (head 1357 + n) :: Int departs = map read $ filter (/= “x”) $ splitOn “,” (last 1358 + n)</p> 1359 + <div class="code"> 1360 + 1361 + </div> 1362 + </div> 1363 + <div class="row"> 1364 + <p>p2 n = chineseRemainder offs where offs = map (bimap negate 1365 + read) $ filter ((/= “x”) . snd) $ zip [0 ..] $ splitOn “,” (last 1366 + n)</p> 1367 + <div class="code"> 1368 + 1369 + </div> 1370 + </div> 1371 + <div class="row"> 1372 + <p>main = do args &lt;- getArgs n &lt;- lines &lt;$&gt; case args 1373 + of [“-”] -&gt; getContents [file] -&gt; readFile file print $ p1 n 1374 + print $ p2 n</p> 1375 + <div class="code"> 1376 + 1377 + </div> 1378 + </div> 1379 + <div class="row"> 1380 + <p>module Main where</p> 1381 + <div class="code"> 1382 + 1383 + </div> 1384 + </div> 1385 + <div class="row"> 1386 + <p>import Data.Bifunctor (bimap) import Data.Char import 1387 + Data.Either import Data.Map (Map) import qualified Data.Map as Map 1388 + import Data.Strings import Numeric (readInt, showIntAtBase) import 1389 + System.Environment (getArgs) import Text.Parsec.Char import 1390 + Text.ParserCombinators.Parsec</p> 1391 + <div class="code"> 1392 + 1393 + </div> 1394 + </div> 1395 + <div class="row"> 1396 + <p>data Stmt = Mask String | Mem Int Int deriving (Show)</p> 1397 + <div class="code"> 1398 + 1399 + </div> 1400 + </div> 1401 + <div class="row"> 1402 + <p>parseMask :: Parser Stmt parseMask = string “mask =” &gt;&gt; 1403 + Mask &lt;$&gt; many anyChar</p> 1404 + <div class="code"> 1405 + 1406 + </div> 1407 + </div> 1408 + <div class="row"> 1409 + <p>parseNumber :: Parser Int parseNumber = read &lt;$&gt; many1 1410 + digit</p> 1411 + <div class="code"> 1412 + 1413 + </div> 1414 + </div> 1415 + <div class="row"> 1416 + <p>parseMem :: Parser Stmt parseMem = Mem &lt;$ string “mem[” 1417 + &lt;<em>&gt; parseNumber &lt;</em> string ”] =” &lt;*&gt; 1418 + parseNumber</p> 1419 + <div class="code"> 1420 + 1421 + </div> 1422 + </div> 1423 + <div class="row"> 1424 + <p>parseLine :: Parser Stmt parseLine = try parseMask &lt;|&gt; 1425 + parseMem</p> 1426 + <div class="code"> 1427 + 1428 + </div> 1429 + </div> 1430 + <div class="row"> 1431 + <p>applyMask :: Int -&gt; String -&gt; Int applyMask v m = fst $ 1432 + head $ readInt 2 (<code>elem</code> “01”) digitToInt wm where bv = 1433 + strPadLeft ‘0’ 36 $ showIntAtBase 2 intToDigit v “” wm = zipWith 1434 + fn bv m fn o ‘X’ = o fn _ ‘1’ = ‘1’ fn _ ‘0’ = ‘0’</p> 1435 + <div class="code"> 1436 + 1437 + </div> 1438 + </div> 1439 + <div class="row"> 1440 + <p>runProgram :: [Stmt] -&gt; Int runProgram ls = sum regs where 1441 + (mask, regs) = foldl fn (““, Map.empty) ls fn (_, regs) (Mask s) = 1442 + (s, regs) fn (m, regs) (Mem idx val) = (m, Map.insert idx nval 1443 + regs) where nval = applyMask val m</p> 1444 + <div class="code"> 1445 + 1446 + </div> 1447 + </div> 1448 + <div class="row"> 1449 + <p>floatings :: String -&gt; [String] floatings [] = [[]] 1450 + floatings (‘X’ : xs) = floatings xs &gt;&gt;= (&gt; [‘0’ : b, ‘1’ 1451 + : b]) floatings (x : xs) = map (x :) $ floatings xs</p> 1452 + <div class="code"> 1453 + 1454 + </div> 1455 + </div> 1456 + <div class="row"> 1457 + <p>genIdxs :: Int -&gt; String -&gt; [Int] genIdxs v m = map (fst 1458 + . head . readInt 2 (<code>elem</code> “01”) digitToInt) (floatings 1459 + wm) where bv = strPadLeft ‘0’ 36 $ showIntAtBase 2 intToDigit v “” 1460 + wm = zipWith fn bv m fn o ‘0’ = o fn _ ‘1’ = ‘1’ fn _ ‘X’ = 1461 + ‘X’</p> 1462 + <div class="code"> 1463 + 1464 + </div> 1465 + </div> 1466 + <div class="row"> 1467 + <p>v2chip :: [Stmt] -&gt; Int v2chip ls = sum regs where (mask, 1468 + regs) = foldl fn (““, Map.empty) ls fn (_, regs) (Mask s) = (s, 1469 + regs) fn (m, regs) (Mem idx val) = (m, nmap) where idxs = genIdxs 1470 + idx m nmap = flip Map.union regs $ Map.fromList $ map (,val) 1471 + idxs</p> 1472 + <div class="code"> 1473 + 1474 + </div> 1475 + </div> 1476 + <div class="row"> 1477 + <p>main = do args &lt;- getArgs n &lt;- rights . map (parse 1478 + parseLine “main”) . lines &lt;$&gt; case args of [“-”] -&gt; 1479 + getContents [file] -&gt; readFile file print $ runProgram n print 1480 + $ v2chip n</p> 1481 + <div class="code"> 1482 + 1483 + </div> 1484 + </div> 1485 + <div class="row"> 1486 + <p>module Main where</p> 1487 + <div class="code"> 1488 + 1489 + </div> 1490 + </div> 1491 + <div class="row"> 1492 + <p>import Data.List.Split import qualified Data.Map as M import 1493 + Data.Maybe import System.Environment (getArgs)</p> 1494 + <div class="code"> 1495 + 1496 + </div> 1497 + </div> 1498 + <div class="row"> 1499 + <p>run ls start input = fst $ foldl fn (start, startMap) ls where 1500 + startMap = M.fromList $ zip input [1 ..] fn (last, seen) i = (i - 1501 + last’, seen’) where last’ = fromMaybe i (M.lookup last seen) seen’ 1502 + = M.insert last i seen</p> 1503 + <div class="code"> 1504 + 1505 + </div> 1506 + </div> 1507 + <div class="row"> 1508 + <p>main = do args &lt;- getArgs n &lt;- map read . splitOn “,” 1509 + &lt;$&gt; case args of [“-”] -&gt; getContents [file] -&gt; 1510 + readFile file</p> 1511 + <div class="code"> 1512 + 1513 + </div> 1514 + </div> 1515 + <div class="row"> 1516 + <p>– holy off-by-one errors print $ run [8 .. 2020 - 1] 0 n print 1517 + $ run [8 .. 30000000 - 1] 0 n</p> 1518 + <div class="code"> 1519 + 1520 + </div> 1521 + </div> 1522 + <div class="row"> 1523 + <p>module Main where</p> 1524 + <div class="code"> 1525 + 1526 + </div> 1527 + </div> 1528 + <div class="row"> 1529 + <p>import Control.Monad (liftM2) import Data.Function (on) import 1530 + Data.List (sortBy) import Data.List.Split (splitOn) import 1531 + Data.Map (Map, (!)) import qualified Data.Map as Map import 1532 + Data.Set (Set, (\)) import qualified Data.Set as Set import 1533 + System.Environment (getArgs) import Text.Parsec.Char import 1534 + Text.ParserCombinators.Parsec</p> 1535 + <div class="code"> 1536 + 1537 + </div> 1538 + </div> 1539 + <div class="row"> 1540 + <p>type Constraint = ((Int, Int), (Int, Int))</p> 1541 + <div class="code"> 1542 + 1543 + </div> 1544 + </div> 1545 + <div class="row"> 1546 + <p>parseNumber = read &lt;$&gt; many1 digit</p> 1547 + <div class="code"> 1548 + 1549 + </div> 1550 + </div> 1551 + <div class="row"> 1552 + <p>parseBound = (,) &lt;$&gt; parseNumber &lt;* char ‘-’ &lt;*&gt; 1553 + parseNumber</p> 1554 + <div class="code"> 1555 + 1556 + </div> 1557 + </div> 1558 + <div class="row"> 1559 + <p>parseConstraint = (,) &lt;$&gt; parseBound &lt;* string ” or ” 1560 + &lt;*&gt; parseBound</p> 1561 + <div class="code"> 1562 + 1563 + </div> 1564 + </div> 1565 + <div class="row"> 1566 + <p>parseConstraints = (manyTill anyChar (string “:”) *&gt; 1567 + parseConstraint) <code>sepBy</code> newline</p> 1568 + <div class="code"> 1569 + 1570 + </div> 1571 + </div> 1572 + <div class="row"> 1573 + <p>parseTicket = parseNumber <code>sepBy</code> char ‘,’</p> 1574 + <div class="code"> 1575 + 1576 + </div> 1577 + </div> 1578 + <div class="row"> 1579 + <p>parseNears = string “nearby tickets:” <em>&gt; newline 1580 + </em>&gt; parseTicket <code>sepBy</code> newline</p> 1581 + <div class="code"> 1582 + 1583 + </div> 1584 + </div> 1585 + <div class="row"> 1586 + <p>parseMine = string “your ticket:” <em>&gt; newline </em>&gt; 1587 + parseTicket</p> 1588 + <div class="code"> 1589 + 1590 + </div> 1591 + </div> 1592 + <div class="row"> 1593 + <p>parseInput s = do let (p : q : r : _) = splitOn “” s (,,) 1594 + &lt;$&gt; parse parseConstraints “cs” p &lt;<em>&gt; parse 1595 + parseMine “mine” q &lt;</em>&gt; parse parseNears “nears” r</p> 1596 + <div class="code"> 1597 + 1598 + </div> 1599 + </div> 1600 + <div class="row"> 1601 + <p>bet k (l, u) = k &gt;= l &amp;&amp; k &lt;= u</p> 1602 + <div class="code"> 1603 + 1604 + </div> 1605 + </div> 1606 + <div class="row"> 1607 + <p>(|+) = liftM2 (||)</p> 1608 + <div class="code"> 1609 + 1610 + </div> 1611 + </div> 1612 + <div class="row"> 1613 + <p>within (a, b) = flip bet a |+ flip bet b</p> 1614 + <div class="code"> 1615 + 1616 + </div> 1617 + </div> 1618 + <div class="row"> 1619 + <p>findInvalid cs = filter (&gt; not $ any (<code>within</code> t) 1620 + cs)</p> 1621 + <div class="code"> 1622 + 1623 + </div> 1624 + </div> 1625 + <div class="row"> 1626 + <p>isValid cs = all (&gt; any (<code>within</code> t) cs)</p> 1627 + <div class="code"> 1628 + 1629 + </div> 1630 + </div> 1631 + <div class="row"> 1632 + <p>validFor :: [Constraint] -&gt; [Int] -&gt; Set Int validFor cs 1633 + items = foldl1 Set.intersection (map vcf items) where vcf i = 1634 + Set.fromList [idx | (cons, idx) &lt;- zip cs [0 ..], cons 1635 + <code>within</code> i]</p> 1636 + <div class="code"> 1637 + 1638 + </div> 1639 + </div> 1640 + <div class="row"> 1641 + <p>main = do args &lt;- getArgs n &lt;- parseInput &lt;$&gt; case 1642 + args of [“-”] -&gt; getContents [file] -&gt; readFile file let 1643 + Right (cs, mine, nears) = n validTickets = filter (isValid cs) 1644 + nears cols = map (-&gt; map (!! i) validTickets) [0 .. length cs - 1645 + 1] possibleCons = sortBy (compare <code>on</code> (Set.size . 1646 + snd)) $ zip [0 ..] $ map (validFor cs) cols corresp = Map.fromList 1647 + $ map ((i, v) -&gt; (head $ Set.toList v, i)) $ (head possibleCons 1648 + :) $ zipWith fn &lt;*&gt; tail $ possibleCons where fn (i, s) (i’, 1649 + s’) = (i’, s’ \ s) print $ sum $ concatMap (findInvalid cs) nears 1650 + print $ product $ map ((mine !!) . (corresp !)) [0 .. 5]</p> 1651 + <div class="code"> 1652 + 1653 + </div> 1654 + </div> 1655 + <div class="row"> 1656 + <p>module Main where</p> 1657 + <div class="code"> 1658 + 1659 + </div> 1660 + </div> 1661 + <div class="row"> 1662 + <p>import Control.Monad import Data.Map (Map) import qualified 1663 + Data.Map as M import Data.Maybe import System.Environment 1664 + (getArgs)</p> 1665 + <div class="code"> 1666 + 1667 + </div> 1668 + </div> 1669 + <div class="row"> 1670 + <p>toBool ‘#’ = True toBool ‘.’ = False</p> 1671 + <div class="code"> 1672 + 1673 + </div> 1674 + </div> 1675 + <div class="row"> 1676 + <p>gridMap s = M.fromList [ ((x, y, 0, 0), toBool a) | (y, row) 1677 + &lt;- zip [0 ..] rows, (x, a) &lt;- zip [0 ..] row ] where rows = 1678 + lines s</p> 1679 + <div class="code"> 1680 + 1681 + </div> 1682 + </div> 1683 + <div class="row"> 1684 + <p>around (x, y, z, w) = [ (x + x’, y + y’, z + z’, w + w’) | x’ 1685 + &lt;- [-1 .. 1], y’ &lt;- [-1 .. 1], z’ &lt;- [-1 .. 1], w’ &lt;- 1686 + [-1 .. 1], (x’, y’, z’, w’) /= (0, 0, 0, 0) ]</p> 1687 + <div class="code"> 1688 + 1689 + </div> 1690 + </div> 1691 + <div class="row"> 1692 + <p>convert True 2 = True convert True 3 = True convert False 3 = 1693 + True convert _ _ = False</p> 1694 + <div class="code"> 1695 + 1696 + </div> 1697 + </div> 1698 + <div class="row"> 1699 + <p>doStep m = M.mapWithKey fn $ m &lt;&gt; M.fromList [(p, False) 1700 + | p &lt;- concatMap around (M.keys m)] where fn pos v = convert v 1701 + n where n = length $ filter id $ map (fromMaybe False . flip 1702 + M.lookup m) $ around pos</p> 1703 + <div class="code"> 1704 + 1705 + </div> 1706 + </div> 1707 + <div class="row"> 1708 + <p>p1 grid = M.size $ M.filter id (iterate doStep grid !! 6)</p> 1709 + <div class="code"> 1710 + 1711 + </div> 1712 + </div> 1713 + <div class="row"> 1714 + <p>p2 grid = M.size $ M.filter id (iterate doStep grid !! 6)</p> 1715 + <div class="code"> 1716 + 1717 + </div> 1718 + </div> 1719 + <div class="row"> 1720 + <p>main = do args &lt;- getArgs n &lt;- case args of [“-”] -&gt; 1721 + getContents [file] -&gt; readFile file let grid = gridMap n print 1722 + $ p1 grid print $ p2 grid</p> 1723 + <div class="code"> 1724 + 1725 + </div> 1726 + </div> 1727 + <div class="row"> 1728 + <p>{-# LANGUAGE LambdaCase #-}</p> 1729 + <div class="code"> 1730 + 1731 + </div> 1732 + </div> 1733 + <div class="row"> 1734 + <p>import Data.List (tails) import System.Environment 1735 + (getArgs)</p> 1736 + <div class="code"> 1737 + 1738 + </div> 1739 + </div> 1740 + <div class="row"> 1741 + <p>main = do n &lt;- fmap (map read . lines) $ getArgs &gt;&gt;= 1742 + -&gt; getContents [file] -&gt; readFile file print $ p1 n print $ 1743 + p2 n</p> 1744 + <div class="code"> 1745 + 1746 + </div> 1747 + </div> 1748 + <div class="row"> 1749 + <p>p1 = length . filter (uncurry (&lt;)) . (zip &lt;*&gt; 1750 + tail)</p> 1751 + <div class="code"> 1752 + 1753 + </div> 1754 + </div> 1755 + <div class="row"> 1756 + <p>p2 = p1 . map (sum . take 3) . tails</p> 1757 + <div class="code"> 1758 + 1759 + </div> 1760 + </div> 1761 + <div class="row"> 1762 + <p>{-# LANGUAGE LambdaCase #-}</p> 1763 + <div class="code"> 1764 + 1765 + </div> 1766 + </div> 1767 + <div class="row"> 1768 + <p>import System.Environment (getArgs)</p> 1769 + <div class="code"> 1770 + 1771 + </div> 1772 + </div> 1773 + <div class="row"> 1774 + <p>ans1 = foldl mv (0, 0) where mv (f, d) [“forward”, i] = (f + 1775 + read i, d) mv (f, d) [“up”, i] = (f, d - read i) mv (f, d) 1776 + [“down”, i] = (f, d + read i) mv x _ = x</p> 1777 + <div class="code"> 1778 + 1779 + </div> 1780 + </div> 1781 + <div class="row"> 1782 + <p>ans2 = foldl mv (0, 0, 0) where mv (f, d, a) [“forward”, i] = 1783 + (f + read i, d + a * read i, a) mv (f, d, a) [“up”, i] = (f, d, a 1784 + - read i) mv (f, d, a) [“down”, i] = (f, d, a + read i) mv x _ = 1785 + x</p> 1786 + <div class="code"> 1787 + 1788 + </div> 1789 + </div> 1790 + <div class="row"> 1791 + <p>main = do n &lt;- fmap (map words . lines) $ getArgs &gt;&gt;= 1792 + -&gt; getContents [file] -&gt; readFile file print $ uncurry (*) $ 1793 + ans1 n print $ ((f, d, _) -&gt; f * d) $ ans2 n</p> 1794 + <div class="code"> 1795 + 1796 + </div> 1797 + </div> 1798 + <div class="row"> 1799 + <p>{-# LANGUAGE LambdaCase #-}</p> 1800 + <div class="code"> 1801 + 1802 + </div> 1803 + </div> 1804 + <div class="row"> 1805 + <p>import Data.Char (digitToInt) import Data.List (transpose) 1806 + import Data.Map (Map) import qualified Data.Map as M import 1807 + System.Environment (getArgs)</p> 1808 + <div class="code"> 1809 + 1810 + </div> 1811 + </div> 1812 + <div class="row"> 1813 + <p>bitsOfString = map (== ‘1’)</p> 1814 + <div class="code"> 1815 + 1816 + </div> 1817 + </div> 1818 + <div class="row"> 1819 + <p>intOfBits = foldl (x -&gt; a * 2 + if x then 1 else 0) 0</p> 1820 + <div class="code"> 1821 + 1822 + </div> 1823 + </div> 1824 + <div class="row"> 1825 + <p>binaryToInt = foldl (x -&gt; a * 2 + digitToInt x) 0</p> 1826 + <div class="code"> 1827 + 1828 + </div> 1829 + </div> 1830 + <div class="row"> 1831 + <p>freqs = M.fromListWith (+) . map (,1)</p> 1832 + <div class="code"> 1833 + 1834 + </div> 1835 + </div> 1836 + <div class="row"> 1837 + <p>mostCommon l = ones m &gt;= zeroes m where ones = (M.! True) 1838 + zeroes = (M.! False) m = freqs l</p> 1839 + <div class="code"> 1840 + 1841 + </div> 1842 + </div> 1843 + <div class="row"> 1844 + <p>leastCommon = not . mostCommon</p> 1845 + <div class="code"> 1846 + 1847 + </div> 1848 + </div> 1849 + <div class="row"> 1850 + <p>type Stepper = [Bool] -&gt; Bool</p> 1851 + <div class="code"> 1852 + 1853 + </div> 1854 + </div> 1855 + <div class="row"> 1856 + <p>step :: Stepper -&gt; [String] -&gt; Int -&gt; [String] step 1857 + stepper ls n = filter (-&gt; bitsOfString l !! n == filterFn n) ls 1858 + where filterFn n = stepper . bitsOfString $ map (!! n) ls</p> 1859 + <div class="code"> 1860 + 1861 + </div> 1862 + </div> 1863 + <div class="row"> 1864 + <p>oxygen ls = head $ head $ dropWhile ((/= 1) . length) $ scanl 1865 + (step mostCommon) ls [0 ..]</p> 1866 + <div class="code"> 1867 + 1868 + </div> 1869 + </div> 1870 + <div class="row"> 1871 + <p>co2 ls = head $ head $ dropWhile ((/= 1) . length) $ scanl 1872 + (step leastCommon) ls [0 ..]</p> 1873 + <div class="code"> 1874 + 1875 + </div> 1876 + </div> 1877 + <div class="row"> 1878 + <p>ans1 = map (mostCommon . bitsOfString) . transpose</p> 1879 + <div class="code"> 1880 + 1881 + </div> 1882 + </div> 1883 + <div class="row"> 1884 + <p>main = do n &lt;- fmap lines $ getArgs &gt;&gt;= -&gt; 1885 + getContents [file] -&gt; readFile file let one = ans1 n γ = 1886 + intOfBits one ε = intOfBits $ map not one o = binaryToInt $ oxygen 1887 + n co = binaryToInt $ co2 n print $ γ * ε print $ o * co</p> 1888 + <div class="code"> 1889 + 1890 + </div> 1891 + </div> 1892 + <div class="row"> 1893 + <p>{-# LANGUAGE LambdaCase #-}</p> 1894 + <div class="code"> 1895 + 1896 + </div> 1897 + </div> 1898 + <div class="row"> 1899 + <p>import Control.Monad (join) import Data.List (find, transpose) 1900 + import Data.List.Split (splitOn) import Data.Maybe (isJust) import 1901 + System.Environment (getArgs) import Text.Parsec.Char import 1902 + Text.ParserCombinators.Parsec</p> 1903 + <div class="code"> 1904 + 1905 + </div> 1906 + </div> 1907 + <div class="row"> 1908 + <p>parseInt :: Parser Int parseInt = read &lt;$&gt; (spaces *&gt; 1909 + many1 digit)</p> 1910 + <div class="code"> 1911 + 1912 + </div> 1913 + </div> 1914 + <div class="row"> 1915 + <p>parseNums :: Parser [Int] parseNums = parseInt 1916 + <code>sepBy</code> char ‘,’</p> 1917 + <div class="code"> 1918 + 1919 + </div> 1920 + </div> 1921 + <div class="row"> 1922 + <p>parseBoardLine :: Parser [Int] parseBoardLine = parseInt 1923 + <code>sepBy</code> many1 (char ’ ’)</p> 1924 + <div class="code"> 1925 + 1926 + </div> 1927 + </div> 1928 + <div class="row"> 1929 + <p>type Board = [[Int]]</p> 1930 + <div class="code"> 1931 + 1932 + </div> 1933 + </div> 1934 + <div class="row"> 1935 + <p>parseBoard :: Parser Board parseBoard = parseBoardLine 1936 + <code>sepBy</code> newline</p> 1937 + <div class="code"> 1938 + 1939 + </div> 1940 + </div> 1941 + <div class="row"> 1942 + <p>parseInput :: Parser ([Int], [Board]) parseInput = do nums 1943 + &lt;- parseNums &lt;* newline boards &lt;- parseBoard 1944 + <code>sepBy</code> newline return (nums, boards)</p> 1945 + <div class="code"> 1946 + 1947 + </div> 1948 + </div> 1949 + <div class="row"> 1950 + <p>doParse :: Parser a -&gt; String -&gt; a doParse parser input = 1951 + v where Right v = parse parser “input” input</p> 1952 + <div class="code"> 1953 + 1954 + </div> 1955 + </div> 1956 + <div class="row"> 1957 + <p>isVictor board = any row board || any row (transpose board) 1958 + where row = all (== -1)</p> 1959 + <div class="code"> 1960 + 1961 + </div> 1962 + </div> 1963 + <div class="row"> 1964 + <p>score :: Board -&gt; Int score = sum . concatMap (filter (&gt; 1965 + 0))</p> 1966 + <div class="code"> 1967 + 1968 + </div> 1969 + </div> 1970 + <div class="row"> 1971 + <p>stepBoard call = map squish where squish = map (-&gt; if x == 1972 + call then -1 else x)</p> 1973 + <div class="code"> 1974 + 1975 + </div> 1976 + </div> 1977 + <div class="row"> 1978 + <p>doRound boards call = map (stepBoard call) boards</p> 1979 + <div class="code"> 1980 + 1981 + </div> 1982 + </div> 1983 + <div class="row"> 1984 + <p>doRound2 boards call = filter (not . isVictor) $ doRound boards 1985 + call</p> 1986 + <div class="code"> 1987 + 1988 + </div> 1989 + </div> 1990 + <div class="row"> 1991 + <p>victor :: Int -&gt; [Board] -&gt; Maybe Int victor call boards 1992 + = (* call) . score &lt;$&gt; find isVictor boards</p> 1993 + <div class="code"> 1994 + 1995 + </div> 1996 + </div> 1997 + <div class="row"> 1998 + <p>ans1 boards calls = join $ find isJust $ map (uncurry victor) $ 1999 + zip (0 : calls) (scanl doRound boards calls)</p> 2000 + <div class="code"> 2001 + 2002 + </div> 2003 + </div> 2004 + <div class="row"> 2005 + <p>ans2 boards calls = head $ dropWhile (null . snd) $ reverse $ 2006 + zip calls (scanl doRound2 boards calls)</p> 2007 + <div class="code"> 2008 + 2009 + </div> 2010 + </div> 2011 + <div class="row"> 2012 + <p>main = do n &lt;- fmap (splitOn “”) $ getArgs &gt;&gt;= -&gt; 2013 + getContents [file] -&gt; readFile file let calls = doParse 2014 + parseNums $ head n boards = map (filter (not . null) . doParse 2015 + parseBoard) (tail n) print $ ans1 boards calls print $ ((call, 2016 + boards) -&gt; (* call) $ score $ stepBoard call (head boards)) $ 2017 + ans2 boards calls</p> 2018 + <div class="code"> 2019 + 2020 + </div> 2021 + </div> 2022 + <div class="row"> 2023 + <p>{-# LANGUAGE LambdaCase #-}</p> 2024 + <div class="code"> 2025 + 2026 + </div> 2027 + </div> 2028 + <div class="row"> 2029 + <p>module Main where</p> 2030 + <div class="code"> 2031 + 2032 + </div> 2033 + </div> 2034 + <div class="row"> 2035 + <p>import Control.Monad (liftM2) import Data.Functor 2036 + ((&lt;&amp;&gt;)) import Data.List.Split (splitOn) import Data.Map 2037 + (Map) import qualified Data.Map as M import System.Environment 2038 + (getArgs)</p> 2039 + <div class="code"> 2040 + 2041 + </div> 2042 + </div> 2043 + <div class="row"> 2044 + <p>parse n = ((a, b), (c, d)) where [a, b, c, d] = map read $ 2045 + concatMap (splitOn “,”) $ splitOn ” -&gt; ” n</p> 2046 + <div class="code"> 2047 + 2048 + </div> 2049 + </div> 2050 + <div class="row"> 2051 + <p>doRange ((a, b), (c, d)) | a == c = map (a,) r2 | b == d = map 2052 + (,b) r1 | otherwise = zip r1 r2 where r1 = if a &lt; c then [a .. 2053 + c] else [a, a - 1 .. c] r2 = if b &lt; d then [b .. d] else [b, b 2054 + - 1 .. d]</p> 2055 + <div class="code"> 2056 + 2057 + </div> 2058 + </div> 2059 + <div class="row"> 2060 + <p>freqs = M.fromListWith (+) . map (,1)</p> 2061 + <div class="code"> 2062 + 2063 + </div> 2064 + </div> 2065 + <div class="row"> 2066 + <p>solve = M.size . M.filter (&gt; 1) . freqs . concatMap 2067 + doRange</p> 2068 + <div class="code"> 2069 + 2070 + </div> 2071 + </div> 2072 + <div class="row"> 2073 + <p>p1 = solve . filter (isHor |+ isVer) where isVer ((a, <em>), 2074 + (c, </em>)) = a == c isHor ((<em>, b), (</em>, d)) = b == d</p> 2075 + <div class="code"> 2076 + 2077 + </div> 2078 + </div> 2079 + <div class="row"> 2080 + <p>p2 = solve</p> 2081 + <div class="code"> 2082 + 2083 + </div> 2084 + </div> 2085 + <div class="row"> 2086 + <p>(|+) = liftM2 (||)</p> 2087 + <div class="code"> 2088 + 2089 + </div> 2090 + </div> 2091 + <div class="row"> 2092 + <p>main = do n &lt;- fmap (map parse . lines) $ getArgs &gt;&gt;= 2093 + -&gt; getContents [file] -&gt; readFile file print $ p1 n print $ 2094 + p2 n</p> 2095 + <div class="code"> 2096 + 2097 + </div> 2098 + </div> 2099 + <div class="row"> 2100 + <p>{-# LANGUAGE LambdaCase #-}</p> 2101 + <div class="code"> 2102 + 2103 + </div> 2104 + </div> 2105 + <div class="row"> 2106 + <p>import Data.List.Split (splitOn) import qualified Data.Map as M 2107 + import Data.Maybe (fromMaybe) import System.Environment 2108 + (getArgs)</p> 2109 + <div class="code"> 2110 + 2111 + </div> 2112 + </div> 2113 + <div class="row"> 2114 + <p>grow m = M.insertWith (+) 6 new . M.insertWith (+) 8 new . 2115 + M.mapKeys pred . M.delete 0 $ m where new = fromMaybe 0 $ M.lookup 2116 + 0 m</p> 2117 + <div class="code"> 2118 + 2119 + </div> 2120 + </div> 2121 + <div class="row"> 2122 + <p>main = do n &lt;- fmap (map read . splitOn “,”) $ getArgs 2123 + &gt;&gt;= -&gt; getContents [file] -&gt; readFile file let fish = 2124 + M.fromListWith (+) $ map (,1) n print $ sum $ iterate grow fish !! 2125 + 80 print $ sum $ iterate grow fish !! 256</p> 2126 + <div class="code"> 2127 + 2128 + </div> 2129 + </div> 2130 + <div class="row"> 2131 + <p>{-# LANGUAGE LambdaCase #-}</p> 2132 + <div class="code"> 2133 + 2134 + </div> 2135 + </div> 2136 + <div class="row"> 2137 + <p>import Data.List.Split (splitOn) import qualified Data.Map as M 2138 + import Data.Maybe (fromMaybe) import System.Environment 2139 + (getArgs)</p> 2140 + <div class="code"> 2141 + 2142 + </div> 2143 + </div> 2144 + <div class="row"> 2145 + <p>cost1 = abs</p> 2146 + <div class="code"> 2147 + 2148 + </div> 2149 + </div> 2150 + <div class="row"> 2151 + <p>cost2 d = (d * d + abs d) <code>div</code> 2</p> 2152 + <div class="code"> 2153 + 2154 + </div> 2155 + </div> 2156 + <div class="row"> 2157 + <p>solve cost n = minimum [sum (map (cost . subtract p) n) | p 2158 + &lt;- [minimum n .. maximum n]]</p> 2159 + <div class="code"> 2160 + 2161 + </div> 2162 + </div> 2163 + <div class="row"> 2164 + <p>main = do n &lt;- fmap (map read . splitOn “,”) $ getArgs 2165 + &gt;&gt;= -&gt; getContents [file] -&gt; readFile file print $ 2166 + solve cost1 n print $ solve cost2 n</p> 2167 + <div class="code"> 2168 + 2169 + </div> 2170 + </div> 2171 + <div class="row"> 2172 + <p>{-# LANGUAGE LambdaCase #-}</p> 2173 + <div class="code"> 2174 + 2175 + </div> 2176 + </div> 2177 + <div class="row"> 2178 + <p>import Data.Char (digitToInt) import Data.List (sortBy) import 2179 + qualified Data.Map as M import Data.Maybe (fromMaybe, mapMaybe) 2180 + import Data.Ord (Down (Down), comparing) import qualified Data.Ord 2181 + import qualified Data.Set as S import System.Environment 2182 + (getArgs)</p> 2183 + <div class="code"> 2184 + 2185 + </div> 2186 + </div> 2187 + <div class="row"> 2188 + <p>grid lines = M.fromList [ ((x, y), digitToInt d) | (y, l) &lt;- 2189 + zip [0 ..] lines, (x, d) &lt;- zip [0 ..] l ]</p> 2190 + <div class="code"> 2191 + 2192 + </div> 2193 + </div> 2194 + <div class="row"> 2195 + <p>around (x, y) = [(x + dx, y + dy) | (dx, dy) &lt;- [(-1, 0), 2196 + (1, 0), (0, -1), (0, 1)]]</p> 2197 + <div class="code"> 2198 + 2199 + </div> 2200 + </div> 2201 + <div class="row"> 2202 + <p>minimas g = M.filterWithKey minima g where minima k a = a &lt; 2203 + minimum (mapMaybe (g M.!?) (around k))</p> 2204 + <div class="code"> 2205 + 2206 + </div> 2207 + </div> 2208 + <div class="row"> 2209 + <p>– generic bfs bfs :: (Num n, Ord a) =&gt; (a -&gt; [a]) -&gt; 2210 + [a] -&gt; [(a, n)] bfs next s = go S.empty (map (,0) s) where go _ 2211 + [] = [] go seen ((x, dist) : xs) | x <code>S.member</code> seen = 2212 + go seen xs | otherwise = (x, dist) : go (S.insert x seen) (xs ++ 2213 + map (,dist + 1) (next x))</p> 2214 + <div class="code"> 2215 + 2216 + </div> 2217 + </div> 2218 + <div class="row"> 2219 + <p>basin g m = bfs search [m] where search k = [a | a &lt;- around 2220 + k, Just v &lt;- [M.lookup a g], v /= 9]</p> 2221 + <div class="code"> 2222 + 2223 + </div> 2224 + </div> 2225 + <div class="row"> 2226 + <p>main = do n &lt;- fmap lines $ getArgs &gt;&gt;= -&gt; 2227 + getContents [file] -&gt; readFile file let g = grid n let m = 2228 + minimas g print $ sum m + length m print $ product $ take 3 $ 2229 + sortBy (comparing Down) $ length . basin g &lt;$&gt; M.keys m</p> 2230 + <div class="code"> 2231 + 2232 + </div> 2233 + </div> 2234 + <div class="row"> 2235 + <p>{-# LANGUAGE LambdaCase #-}</p> 2236 + <div class="code"> 2237 + 2238 + </div> 2239 + </div> 2240 + <div class="row"> 2241 + <p>import System.Environment (getArgs)</p> 2242 + <div class="code"> 2243 + 2244 + </div> 2245 + </div> 2246 + <div class="row"> 2247 + <p>main = do n &lt;- fmap lines $ getArgs &gt;&gt;= -&gt; 2248 + getContents [file] -&gt; readFile file print n</p> 2249 + <div class="code"> 2250 + 2251 + </div> 2252 + </div> 2253 + </body> 2254 + </html>
+49
out/2-section-1.html
··· 1 + <!DOCTYPE html> 2 + <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang=""> 3 + <head> 4 + <meta charset="utf-8" /> 5 + <meta name="generator" content="pandoc" /> 6 + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> 7 + <title>2025</title> 8 + <style> 9 + code{white-space: pre-wrap;} 10 + span.smallcaps{font-variant: small-caps;} 11 + div.columns{display: flex; gap: min(4vw, 1.5em);} 12 + div.column{flex: auto; overflow-x: auto;} 13 + div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} 14 + /* The extra [class] is a hack that increases specificity enough to 15 + override a similar rule in reveal.js */ 16 + ul.task-list[class]{list-style: none;} 17 + ul.task-list li input[type="checkbox"] { 18 + font-size: inherit; 19 + width: 0.8em; 20 + margin: 0 0.8em 0.2em -1.6em; 21 + vertical-align: middle; 22 + } 23 + .display.math{display: block; text-align: center; margin: 0.5rem auto;} 24 + </style> 25 + <link rel="stylesheet" href="style.css" /> 26 + </head> 27 + <body> 28 + <nav id="sitenav"> 29 + <div class="sitenav"> 30 + <span class="navlink"> 31 + <span class="navlink-label">Up:</span> <a href="index.html" accesskey="u" rel="up"></a> 32 + </span> 33 + <span class="navlink"> 34 + <span class="navlink-label">Top:</span> <a href="index.html" accesskey="t" rel="top"></a> 35 + </span> 36 + </div> 37 + <div class="sitenav"> 38 + <span class="navlink"> 39 + <span class="navlink-label">Previous:</span> <a href="1.2-day-2.html" accesskey="p" rel="previous">Day 2</a> 40 + </span> 41 + <span class="navlink"> 42 + <span class="navlink-label">Next:</span> <a href="2.1-day-2-1.html" accesskey="n" rel="next">Day 2</a> 43 + </span> 44 + </div> 45 + </nav> 46 + 47 + <h1 data-number="2" id="section-1">2025</h1> 48 + </body> 49 + </html>
+182
out/2.1-day-2-1.html
··· 1 + <!DOCTYPE html> 2 + <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang=""> 3 + <head> 4 + <meta charset="utf-8" /> 5 + <meta name="generator" content="pandoc" /> 6 + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> 7 + <title>Day 2</title> 8 + <style> 9 + code{white-space: pre-wrap;} 10 + span.smallcaps{font-variant: small-caps;} 11 + div.columns{display: flex; gap: min(4vw, 1.5em);} 12 + div.column{flex: auto; overflow-x: auto;} 13 + div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} 14 + /* The extra [class] is a hack that increases specificity enough to 15 + override a similar rule in reveal.js */ 16 + ul.task-list[class]{list-style: none;} 17 + ul.task-list li input[type="checkbox"] { 18 + font-size: inherit; 19 + width: 0.8em; 20 + margin: 0 0.8em 0.2em -1.6em; 21 + vertical-align: middle; 22 + } 23 + .display.math{display: block; text-align: center; margin: 0.5rem auto;} 24 + /* CSS for syntax highlighting */ 25 + html { -webkit-text-size-adjust: 100%; } 26 + pre > code.sourceCode { white-space: pre; position: relative; } 27 + pre > code.sourceCode > span { display: inline-block; line-height: 1.25; } 28 + pre > code.sourceCode > span:empty { height: 1.2em; } 29 + .sourceCode { overflow: visible; } 30 + code.sourceCode > span { color: inherit; text-decoration: inherit; } 31 + div.sourceCode { margin: 1em 0; } 32 + pre.sourceCode { margin: 0; } 33 + @media screen { 34 + div.sourceCode { overflow: auto; } 35 + } 36 + @media print { 37 + pre > code.sourceCode { white-space: pre-wrap; } 38 + pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; } 39 + } 40 + pre.numberSource code 41 + { counter-reset: source-line 0; } 42 + pre.numberSource code > span 43 + { position: relative; left: -4em; counter-increment: source-line; } 44 + pre.numberSource code > span > a:first-child::before 45 + { content: counter(source-line); 46 + position: relative; left: -1em; text-align: right; vertical-align: baseline; 47 + border: none; display: inline-block; 48 + -webkit-touch-callout: none; -webkit-user-select: none; 49 + -khtml-user-select: none; -moz-user-select: none; 50 + -ms-user-select: none; user-select: none; 51 + padding: 0 4px; width: 4em; 52 + } 53 + pre.numberSource { margin-left: 3em; padding-left: 4px; } 54 + div.sourceCode 55 + { } 56 + @media screen { 57 + pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; } 58 + } 59 + code span.al { font-weight: bold; } /* Alert */ 60 + code span.an { font-style: italic; } /* Annotation */ 61 + code span.cf { font-weight: bold; } /* ControlFlow */ 62 + code span.co { font-style: italic; } /* Comment */ 63 + code span.cv { font-style: italic; } /* CommentVar */ 64 + code span.do { font-style: italic; } /* Documentation */ 65 + code span.dt { color: #8888c7; } /* DataType */ 66 + code span.er { font-weight: bold; } /* Error */ 67 + code span.in { font-style: italic; } /* Information */ 68 + code span.kw { font-weight: bold; } /* Keyword */ 69 + code span.pp { font-weight: bold; } /* Preprocessor */ 70 + code span.wa { font-style: italic; } /* Warning */ 71 + </style> 72 + <link rel="stylesheet" href="style.css" /> 73 + </head> 74 + <body> 75 + <nav id="sitenav"> 76 + <div class="sitenav"> 77 + <span class="navlink"> 78 + <span class="navlink-label">Up:</span> <a href="2-section-1.html" accesskey="u" rel="up">2025</a> 79 + </span> 80 + <span class="navlink"> 81 + <span class="navlink-label">Top:</span> <a href="index.html" accesskey="t" rel="top"></a> 82 + </span> 83 + </div> 84 + <div class="sitenav"> 85 + <span class="navlink"> 86 + <span class="navlink-label">Previous:</span> <a href="2-section-1.html" accesskey="p" rel="previous">2025</a> 87 + </span> 88 + <span class="navlink"> 89 + <span class="navlink-label">Next:</span> <a href="2.2-day-4.html" accesskey="n" rel="next">Day 4</a> 90 + </span> 91 + </div> 92 + </nav> 93 + 94 + <h2 data-number="2.1" id="day-2-1">Day 2</h2> 95 + <div class="row"> 96 + <p>Starting with the parse step, the input is of the form 97 + <code>11-22,15-17,...</code>. So we first split on commas, for 98 + each item in the list (of the form <code>"11-22"</code>), we can 99 + split again on <code>"-"</code>, and finally, use 100 + <code>read</code> to parse them to integers.</p> 101 + <div class="code"> 102 + <div class="sourceCode" id="cb1"><pre 103 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.List.Split</span> (splitOn)</span> 104 + <span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span> 105 + <span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="ot">parse ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> [[<span class="dt">Int</span>]]</span> 106 + <span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>parse <span class="ot">=</span> <span class="fu">map</span> (<span class="fu">map</span> <span class="fu">read</span> <span class="op">.</span> splitOn <span class="st">&quot;-&quot;</span>) <span class="op">.</span> splitOn <span class="st">&quot;,&quot;</span></span></code></pre></div> 107 + </div> 108 + </div> 109 + <div class="row"> 110 + <p>We can move onto the problem itself now.</p> 111 + <div class="code"> 112 + 113 + </div> 114 + </div> 115 + <h3 data-number="2.1.1" id="part-1-2">Part 1</h3> 116 + <div class="row"> 117 + <p>The check for invalidity for an integer in Part 1 requires us 118 + to simply split the string in half and ensure that the two halves 119 + are identical, this is easily produced using 120 + <code>splitAt</code>:</p> 121 + <div class="code"> 122 + <div class="sourceCode" id="cb2"><pre 123 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">invalid ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Bool</span></span> 124 + <span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>invalid n <span class="ot">=</span> l <span class="op">==</span> r</span> 125 + <span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span> 126 + <span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a> s <span class="ot">=</span> <span class="fu">show</span> n</span> 127 + <span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a> (l, r) <span class="ot">=</span> <span class="fu">splitAt</span> (<span class="fu">length</span> s <span class="ot">`div`</span> <span class="dv">2</span>) s</span></code></pre></div> 128 + </div> 129 + </div> 130 + <div class="row"> 131 + <p>With that in place, we can define the solution to part 1. 132 + <code>range</code> is a utility to iterate through the pair, we 133 + then filter out <code>invalid</code> items and add everything 134 + up:</p> 135 + <div class="code"> 136 + <div class="sourceCode" id="cb3"><pre 137 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="fu">range</span> [a, b] <span class="ot">=</span> [a <span class="op">..</span> b]</span> 138 + <span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a></span> 139 + <span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>p1 i <span class="ot">=</span> <span class="fu">sum</span> <span class="op">$</span> <span class="fu">concatMap</span> (<span class="fu">filter</span> invalid <span class="op">.</span> <span class="fu">range</span>) i</span></code></pre></div> 140 + </div> 141 + </div> 142 + <h3 data-number="2.1.2" id="part-2-1">Part 2</h3> 143 + <div class="row"> 144 + <p>This part requires a slight modification to the invalidity 145 + check. We now need to check for any number of repeating 146 + substrings, so “123123123” is invalid because it is formed from 147 + <code>"123" + "123" + "123"</code>. The methodology here is 148 + slightly involved, first we get all prefixes of the input using 149 + <code>inits</code>. We can filter out the initial empty prefix 150 + with <code>tail</code>. Upon repeated cyling the prefixes, if we 151 + are able to form the original string, then the string can be 152 + considered invalid!</p> 153 + <div class="code"> 154 + <div class="sourceCode" id="cb4"><pre 155 + class="sourceCode haskell haskell-top"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.List</span> (inits, isPrefixOf)</span></code></pre></div> 156 + <div class="sourceCode" id="cb5"><pre 157 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ot">invalid2 ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Bool</span></span> 158 + <span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>invalid2 n <span class="ot">=</span> <span class="fu">any</span> ((s <span class="ot">`isPrefixOf`</span>) <span class="op">.</span> <span class="fu">cycle</span>) <span class="op">$</span> <span class="fu">tail</span> <span class="op">$</span> inits l</span> 159 + <span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span> 160 + <span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a> s <span class="ot">=</span> <span class="fu">show</span> n</span> 161 + <span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a> (l, _) <span class="ot">=</span> <span class="fu">splitAt</span> (<span class="fu">length</span> s <span class="ot">`div`</span> <span class="dv">2</span>) s</span></code></pre></div> 162 + </div> 163 + </div> 164 + <div class="row"> 165 + <p>Then, part 2 is defined like so:</p> 166 + <div class="code"> 167 + <div class="sourceCode" id="cb6"><pre 168 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>p2 i <span class="ot">=</span> <span class="fu">sum</span> <span class="op">$</span> <span class="fu">concatMap</span> (<span class="fu">filter</span> invalid2 <span class="op">.</span> <span class="fu">range</span>) i</span></code></pre></div> 169 + </div> 170 + </div> 171 + <div class="row"> 172 + <p>Finally, a main function to wrap it all up:</p> 173 + <div class="code"> 174 + <div class="sourceCode" id="cb7"><pre 175 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span> 176 + <span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a> n <span class="ot">&lt;-</span> parse <span class="op">&lt;$&gt;</span> <span class="fu">getContents</span></span> 177 + <span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">print</span> <span class="op">$</span> p1 n</span> 178 + <span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">print</span> <span class="op">$</span> p2 n</span></code></pre></div> 179 + </div> 180 + </div> 181 + </body> 182 + </html>
+213
out/2.2-day-4.html
··· 1 + <!DOCTYPE html> 2 + <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang=""> 3 + <head> 4 + <meta charset="utf-8" /> 5 + <meta name="generator" content="pandoc" /> 6 + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> 7 + <title>Day 4</title> 8 + <style> 9 + code{white-space: pre-wrap;} 10 + span.smallcaps{font-variant: small-caps;} 11 + div.columns{display: flex; gap: min(4vw, 1.5em);} 12 + div.column{flex: auto; overflow-x: auto;} 13 + div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} 14 + /* The extra [class] is a hack that increases specificity enough to 15 + override a similar rule in reveal.js */ 16 + ul.task-list[class]{list-style: none;} 17 + ul.task-list li input[type="checkbox"] { 18 + font-size: inherit; 19 + width: 0.8em; 20 + margin: 0 0.8em 0.2em -1.6em; 21 + vertical-align: middle; 22 + } 23 + .display.math{display: block; text-align: center; margin: 0.5rem auto;} 24 + /* CSS for syntax highlighting */ 25 + html { -webkit-text-size-adjust: 100%; } 26 + pre > code.sourceCode { white-space: pre; position: relative; } 27 + pre > code.sourceCode > span { display: inline-block; line-height: 1.25; } 28 + pre > code.sourceCode > span:empty { height: 1.2em; } 29 + .sourceCode { overflow: visible; } 30 + code.sourceCode > span { color: inherit; text-decoration: inherit; } 31 + div.sourceCode { margin: 1em 0; } 32 + pre.sourceCode { margin: 0; } 33 + @media screen { 34 + div.sourceCode { overflow: auto; } 35 + } 36 + @media print { 37 + pre > code.sourceCode { white-space: pre-wrap; } 38 + pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; } 39 + } 40 + pre.numberSource code 41 + { counter-reset: source-line 0; } 42 + pre.numberSource code > span 43 + { position: relative; left: -4em; counter-increment: source-line; } 44 + pre.numberSource code > span > a:first-child::before 45 + { content: counter(source-line); 46 + position: relative; left: -1em; text-align: right; vertical-align: baseline; 47 + border: none; display: inline-block; 48 + -webkit-touch-callout: none; -webkit-user-select: none; 49 + -khtml-user-select: none; -moz-user-select: none; 50 + -ms-user-select: none; user-select: none; 51 + padding: 0 4px; width: 4em; 52 + } 53 + pre.numberSource { margin-left: 3em; padding-left: 4px; } 54 + div.sourceCode 55 + { } 56 + @media screen { 57 + pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; } 58 + } 59 + code span.al { font-weight: bold; } /* Alert */ 60 + code span.an { font-style: italic; } /* Annotation */ 61 + code span.cf { font-weight: bold; } /* ControlFlow */ 62 + code span.co { font-style: italic; } /* Comment */ 63 + code span.cv { font-style: italic; } /* CommentVar */ 64 + code span.do { font-style: italic; } /* Documentation */ 65 + code span.dt { color: #8888c7; } /* DataType */ 66 + code span.er { font-weight: bold; } /* Error */ 67 + code span.in { font-style: italic; } /* Information */ 68 + code span.kw { font-weight: bold; } /* Keyword */ 69 + code span.pp { font-weight: bold; } /* Preprocessor */ 70 + code span.wa { font-style: italic; } /* Warning */ 71 + </style> 72 + <link rel="stylesheet" href="style.css" /> 73 + </head> 74 + <body> 75 + <nav id="sitenav"> 76 + <div class="sitenav"> 77 + <span class="navlink"> 78 + <span class="navlink-label">Up:</span> <a href="2-section-1.html" accesskey="u" rel="up">2025</a> 79 + </span> 80 + <span class="navlink"> 81 + <span class="navlink-label">Top:</span> <a href="index.html" accesskey="t" rel="top"></a> 82 + </span> 83 + </div> 84 + <div class="sitenav"> 85 + <span class="navlink"> 86 + <span class="navlink-label">Previous:</span> <a href="2.1-day-2-1.html" accesskey="p" rel="previous">Day 2</a> 87 + </span> 88 + <span class="navlink"> 89 + <span class="navlink-label">Next:</span> <a href="2.3-day-5.html" accesskey="n" rel="next">Day 5</a> 90 + </span> 91 + </div> 92 + </nav> 93 + 94 + <h2 data-number="2.2" id="day-4">Day 4</h2> 95 + <div class="row"> 96 + <p>As always, we start by parsing the input into something more 97 + manageable:</p> 98 + <div class="code"> 99 + <div class="sourceCode" id="cb1"><pre 100 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Set</span></span> 101 + <span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span> 102 + <span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="ot">parse ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Set</span> (<span class="dt">Int</span>, <span class="dt">Int</span>)</span> 103 + <span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>parse <span class="ot">=</span> grid <span class="op">.</span> <span class="fu">lines</span></span></code></pre></div> 104 + </div> 105 + </div> 106 + <div class="row"> 107 + <p><code>grid</code> is a helper function that produces a 108 + <code>Set</code> of points. An interesting note about this problem 109 + is that the points that do <em>not</em> contain rolls (points that 110 + are not <code>@</code>) are inconsequential to the problem itself, 111 + and we can fully ignore them. Using a list comprehension, we first 112 + enumerate each line of the input, and then enumerate each 113 + character of that line, and only preserve the characters that are 114 + <code>@</code>:</p> 115 + <div class="code"> 116 + <div class="sourceCode" id="cb2"><pre 117 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>grid l <span class="ot">=</span></span> 118 + <span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a> fromList</span> 119 + <span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a> [ (x, y)</span> 120 + <span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> (r, x) <span class="ot">&lt;-</span> <span class="fu">zip</span> l [<span class="dv">0</span> <span class="op">..</span>],</span> 121 + <span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a> (c, y) <span class="ot">&lt;-</span> <span class="fu">zip</span> r [<span class="dv">0</span> <span class="op">..</span>],</span> 122 + <span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a> c <span class="op">==</span> <span class="ch">&#39;@&#39;</span></span> 123 + <span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a> ]</span></code></pre></div> 124 + </div> 125 + </div> 126 + <div class="row"> 127 + <p>Now that are input has been munged, lets move onto the problem 128 + itself.</p> 129 + <div class="code"> 130 + 131 + </div> 132 + </div> 133 + <h3 data-number="2.2.1" id="part-1-3">Part 1</h3> 134 + <div class="row"> 135 + <p>This part requires us to first calculate all points adjacent to 136 + a roll, if there are more than 4 rolls at these adjacent 137 + locations, disqualify the roll, as it cannot be lifted by a 138 + forklift. First, lets generate a list comprehension that produces 139 + the points adjacent to a given point. We ignore the offset (0, 0) 140 + because that is the point itself:</p> 141 + <div class="code"> 142 + <div class="sourceCode" id="cb3"><pre 143 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>adjs (x, y) <span class="ot">=</span></span> 144 + <span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a> [ (x <span class="op">+</span> x&#39;, y <span class="op">+</span> y&#39;)</span> 145 + <span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> x&#39; <span class="ot">&lt;-</span> [<span class="op">-</span><span class="dv">1</span>, <span class="dv">0</span>, <span class="dv">1</span>],</span> 146 + <span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a> y&#39; <span class="ot">&lt;-</span> [<span class="op">-</span><span class="dv">1</span>, <span class="dv">0</span>, <span class="dv">1</span>],</span> 147 + <span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a> (x&#39;, y&#39;) <span class="op">/=</span> (<span class="dv">0</span>, <span class="dv">0</span>)</span> 148 + <span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a> ]</span></code></pre></div> 149 + </div> 150 + </div> 151 + <div class="row"> 152 + <p>Then, a roll is liftable by a forklift if the adjacent points 153 + only have upto 4 rolls. We can use <code>Set.filter</code> to 154 + traverse the entire grid. Our filter predicate first collects 155 + adjacent points, filters out ones that are within the boundaries 156 + of the grid, and counts them. Remember that our grid does not 157 + contain points that are <em>not</em> rolls anyway!</p> 158 + <div class="code"> 159 + <div class="sourceCode" id="cb4"><pre 160 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>liftable g <span class="ot">=</span> Data.Set.filter <span class="fu">pred</span> g</span> 161 + <span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span> 162 + <span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">pred</span> <span class="ot">=</span></span> 163 + <span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a> (<span class="op">&lt;</span> <span class="dv">4</span>)</span> 164 + <span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> <span class="fu">length</span></span> 165 + <span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> Prelude.filter (<span class="ot">`member`</span> g)</span> 166 + <span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> adjs</span></code></pre></div> 167 + </div> 168 + </div> 169 + <div class="row"> 170 + <p>Thus, the solution to part one is given as:</p> 171 + <div class="code"> 172 + <div class="sourceCode" id="cb5"><pre 173 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>p1 <span class="ot">=</span> size <span class="op">.</span> liftable</span></code></pre></div> 174 + </div> 175 + </div> 176 + <h3 data-number="2.2.2" id="part-2-2">Part 2</h3> 177 + <div class="row"> 178 + <p>This part is very similar to the previous part. We need to 179 + sequentially remove liftable rolls until we can lift no more. A 180 + simple recursive function can do the trick. The base case: if no 181 + more rolls can be lifted from the grid, return the number of rolls 182 + lifted thus far. The recursive case: accumulate the rolls that are 183 + liftable in the current state of the grid, and recurse into the 184 + grid where the rolls are removed! The removal is calculated simply 185 + using <code>Set.\\</code>, which performs set difference:</p> 186 + <div class="code"> 187 + <div class="sourceCode" id="cb6"><pre 188 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>go s g</span> 189 + <span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> size lifted <span class="op">==</span> <span class="dv">0</span> <span class="ot">=</span> s</span> 190 + <span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="fu">otherwise</span> <span class="ot">=</span> go (s <span class="op">+</span> size lifted) (g \\ lifted)</span> 191 + <span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span> 192 + <span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a> lifted <span class="ot">=</span> liftable g</span></code></pre></div> 193 + </div> 194 + </div> 195 + <div class="row"> 196 + <p>Thus, the solution for the second part is given like so:</p> 197 + <div class="code"> 198 + <div class="sourceCode" id="cb7"><pre 199 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>p2 <span class="ot">=</span> go <span class="dv">0</span></span></code></pre></div> 200 + </div> 201 + </div> 202 + <div class="row"> 203 + <p>Finally, a main function to wrap it all up:</p> 204 + <div class="code"> 205 + <div class="sourceCode" id="cb8"><pre 206 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span> 207 + <span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a> n <span class="ot">&lt;-</span> parse <span class="op">&lt;$&gt;</span> <span class="fu">getContents</span></span> 208 + <span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">print</span> <span class="op">$</span> p1 n</span> 209 + <span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">print</span> <span class="op">$</span> p2 n</span></code></pre></div> 210 + </div> 211 + </div> 212 + </body> 213 + </html>
+181
out/2.3-day-5.html
··· 1 + <!DOCTYPE html> 2 + <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang=""> 3 + <head> 4 + <meta charset="utf-8" /> 5 + <meta name="generator" content="pandoc" /> 6 + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> 7 + <title>Day 5</title> 8 + <style> 9 + code{white-space: pre-wrap;} 10 + span.smallcaps{font-variant: small-caps;} 11 + div.columns{display: flex; gap: min(4vw, 1.5em);} 12 + div.column{flex: auto; overflow-x: auto;} 13 + div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} 14 + /* The extra [class] is a hack that increases specificity enough to 15 + override a similar rule in reveal.js */ 16 + ul.task-list[class]{list-style: none;} 17 + ul.task-list li input[type="checkbox"] { 18 + font-size: inherit; 19 + width: 0.8em; 20 + margin: 0 0.8em 0.2em -1.6em; 21 + vertical-align: middle; 22 + } 23 + .display.math{display: block; text-align: center; margin: 0.5rem auto;} 24 + /* CSS for syntax highlighting */ 25 + html { -webkit-text-size-adjust: 100%; } 26 + pre > code.sourceCode { white-space: pre; position: relative; } 27 + pre > code.sourceCode > span { display: inline-block; line-height: 1.25; } 28 + pre > code.sourceCode > span:empty { height: 1.2em; } 29 + .sourceCode { overflow: visible; } 30 + code.sourceCode > span { color: inherit; text-decoration: inherit; } 31 + div.sourceCode { margin: 1em 0; } 32 + pre.sourceCode { margin: 0; } 33 + @media screen { 34 + div.sourceCode { overflow: auto; } 35 + } 36 + @media print { 37 + pre > code.sourceCode { white-space: pre-wrap; } 38 + pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; } 39 + } 40 + pre.numberSource code 41 + { counter-reset: source-line 0; } 42 + pre.numberSource code > span 43 + { position: relative; left: -4em; counter-increment: source-line; } 44 + pre.numberSource code > span > a:first-child::before 45 + { content: counter(source-line); 46 + position: relative; left: -1em; text-align: right; vertical-align: baseline; 47 + border: none; display: inline-block; 48 + -webkit-touch-callout: none; -webkit-user-select: none; 49 + -khtml-user-select: none; -moz-user-select: none; 50 + -ms-user-select: none; user-select: none; 51 + padding: 0 4px; width: 4em; 52 + } 53 + pre.numberSource { margin-left: 3em; padding-left: 4px; } 54 + div.sourceCode 55 + { } 56 + @media screen { 57 + pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; } 58 + } 59 + code span.al { font-weight: bold; } /* Alert */ 60 + code span.an { font-style: italic; } /* Annotation */ 61 + code span.cf { font-weight: bold; } /* ControlFlow */ 62 + code span.co { font-style: italic; } /* Comment */ 63 + code span.cv { font-style: italic; } /* CommentVar */ 64 + code span.do { font-style: italic; } /* Documentation */ 65 + code span.dt { color: #8888c7; } /* DataType */ 66 + code span.er { font-weight: bold; } /* Error */ 67 + code span.in { font-style: italic; } /* Information */ 68 + code span.kw { font-weight: bold; } /* Keyword */ 69 + code span.pp { font-weight: bold; } /* Preprocessor */ 70 + code span.wa { font-style: italic; } /* Warning */ 71 + </style> 72 + <link rel="stylesheet" href="style.css" /> 73 + </head> 74 + <body> 75 + <nav id="sitenav"> 76 + <div class="sitenav"> 77 + <span class="navlink"> 78 + <span class="navlink-label">Up:</span> <a href="2-section-1.html" accesskey="u" rel="up">2025</a> 79 + </span> 80 + <span class="navlink"> 81 + <span class="navlink-label">Top:</span> <a href="index.html" accesskey="t" rel="top"></a> 82 + </span> 83 + </div> 84 + <div class="sitenav"> 85 + <span class="navlink"> 86 + <span class="navlink-label">Previous:</span> <a href="2.2-day-4.html" accesskey="p" rel="previous">Day 4</a> 87 + </span> 88 + <span class="navlink"> 89 + </span> 90 + </div> 91 + </nav> 92 + 93 + <h2 data-number="2.3" id="day-5">Day 5</h2> 94 + <div class="row"> 95 + <p>As always, we start by parsing the input into something more 96 + manageable.</p> 97 + <div class="code"> 98 + 99 + </div> 100 + </div> 101 + <div class="row"> 102 + <p>The input consists of two sections separated by a blank line. 103 + The first section contains fresh ingredient ID ranges (e.g., 104 + <code>3-5</code>), and the second contains available ingredient 105 + IDs. We split on <code>\n\n</code> to separate these sections, 106 + then parse each range into a list of two integers and each point 107 + as a single integer:</p> 108 + <div class="code"> 109 + <div class="sourceCode" id="cb1"><pre 110 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.List.Split</span> (splitOn)</span> 111 + <span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span> 112 + <span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>parse i <span class="ot">=</span> (ranges, points)</span> 113 + <span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span> 114 + <span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a> [h1, h2] <span class="ot">=</span> splitOn <span class="st">&quot;\n\n&quot;</span> i</span> 115 + <span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a> ranges <span class="ot">=</span> <span class="fu">map</span> (<span class="fu">map</span> <span class="fu">read</span> <span class="op">.</span> splitOn <span class="st">&quot;-&quot;</span>) <span class="op">$</span> <span class="fu">lines</span> h1</span> 116 + <span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a> points <span class="ot">=</span> <span class="fu">map</span> <span class="fu">read</span> <span class="op">$</span> <span class="fu">lines</span> h2</span></code></pre></div> 117 + </div> 118 + </div> 119 + <div class="row"> 120 + <p>Our representation of intervals is list with two elements 121 + <code>[start, end]</code>. <code>contains</code> is a helper 122 + function to check if an ingredient ID falls within a given 123 + range:</p> 124 + <div class="code"> 125 + <div class="sourceCode" id="cb2"><pre 126 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">contains ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> [<span class="dt">Int</span>] <span class="ot">-&gt;</span> <span class="dt">Bool</span></span> 127 + <span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>contains e [start, end] <span class="ot">=</span> e <span class="op">&gt;=</span> start <span class="op">&amp;&amp;</span> e <span class="op">&lt;=</span> end</span></code></pre></div> 128 + </div> 129 + </div> 130 + <h3 data-number="2.3.1" id="part-1-4">Part 1</h3> 131 + <div class="row"> 132 + <p>For part one, we need to count how many of the available 133 + ingredient IDs are fresh. An ID is fresh if it falls within 134 + <code>any</code> of the fresh ranges:</p> 135 + <div class="code"> 136 + <div class="sourceCode" id="cb3"><pre 137 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">p1 ::</span> [[<span class="dt">Int</span>]] <span class="ot">-&gt;</span> [<span class="dt">Int</span>] <span class="ot">-&gt;</span> <span class="dt">Int</span></span> 138 + <span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>p1 is <span class="ot">=</span> <span class="fu">length</span> <span class="op">.</span> <span class="fu">filter</span> (\p <span class="ot">-&gt;</span> <span class="fu">any</span> (contains p) is)</span></code></pre></div> 139 + </div> 140 + </div> 141 + <h3 data-number="2.3.2" id="part-2-3">Part 2</h3> 142 + <div class="row"> 143 + <p>For part two, we need to count the total number of unique 144 + ingredient IDs covered by all the fresh ranges. The methodology 145 + here is to iterate over the intervals sorted by ascending start 146 + bounds, while keeping track of the last end-bound we jumped over. 147 + This is necessary to avoid double-counting overlapping ranges. If 148 + we have <code>10-14</code> followed by <code>12-18</code>, we 149 + should avoid counting <code>12, 13, 14</code> twice. So we first 150 + account for <code>10-14</code>, and keep note of <code>14</code>. 151 + Upon encountering <code>12-18</code>, we then only count 152 + <code>18 - 14 = 4</code> new points, and not 153 + <code>18 - 12 + 1 = 7</code> new points, since the three points 154 + <code>12, 13, 14</code> are accounted for.</p> 155 + <div class="code"> 156 + <div class="sourceCode" id="cb4"><pre 157 + class="sourceCode haskell haskell-top"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.List</span> (sortBy)</span> 158 + <span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Ord</span> (comparing)</span></code></pre></div> 159 + <div class="sourceCode" id="cb5"><pre 160 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ot">p2 ::</span> [[<span class="dt">Int</span>]] <span class="ot">-&gt;</span> <span class="dt">Int</span></span> 161 + <span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>p2 <span class="ot">=</span> go <span class="dv">0</span> <span class="dv">0</span> <span class="op">.</span> sortBy (comparing (<span class="op">!!</span> <span class="dv">0</span>))</span> 162 + <span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span> 163 + <span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a> go tot _ [] <span class="ot">=</span> tot</span> 164 + <span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a> go tot le (i<span class="op">@</span>[start, end] <span class="op">:</span> rest)</span> 165 + <span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> le <span class="op">&gt;</span> end <span class="ot">=</span> go tot le rest</span> 166 + <span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> contains le i <span class="ot">=</span> go (tot <span class="op">+</span> end <span class="op">-</span> le) end rest</span> 167 + <span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> le <span class="op">&lt;</span> start <span class="ot">=</span> go (tot <span class="op">+</span> end <span class="op">-</span> start <span class="op">+</span> <span class="dv">1</span>) end rest</span></code></pre></div> 168 + </div> 169 + </div> 170 + <div class="row"> 171 + <p>Finally, a main function to wrap it all up:</p> 172 + <div class="code"> 173 + <div class="sourceCode" id="cb6"><pre 174 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span> 175 + <span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a> (is, pts) <span class="ot">&lt;-</span> parse <span class="op">&lt;$&gt;</span> <span class="fu">getContents</span></span> 176 + <span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">print</span> <span class="op">$</span> p1 is pts</span> 177 + <span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">print</span> <span class="op">$</span> p2 is</span></code></pre></div> 178 + </div> 179 + </div> 180 + </body> 181 + </html>
+61
out/index.html
··· 1 + <!DOCTYPE html> 2 + <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang=""> 3 + <head> 4 + <meta charset="utf-8" /> 5 + <meta name="generator" content="pandoc" /> 6 + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> 7 + <title>01</title> 8 + <style> 9 + code{white-space: pre-wrap;} 10 + span.smallcaps{font-variant: small-caps;} 11 + div.columns{display: flex; gap: min(4vw, 1.5em);} 12 + div.column{flex: auto; overflow-x: auto;} 13 + div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} 14 + /* The extra [class] is a hack that increases specificity enough to 15 + override a similar rule in reveal.js */ 16 + ul.task-list[class]{list-style: none;} 17 + ul.task-list li input[type="checkbox"] { 18 + font-size: inherit; 19 + width: 0.8em; 20 + margin: 0 0.8em 0.2em -1.6em; 21 + vertical-align: middle; 22 + } 23 + .display.math{display: block; text-align: center; margin: 0.5rem auto;} 24 + </style> 25 + <link rel="stylesheet" href="style.css" /> 26 + </head> 27 + <body> 28 + <nav id="sitenav"> 29 + <div class="sitenav"> 30 + <span class="navlink"> 31 + </span> 32 + <span class="navlink"> 33 + </span> 34 + </div> 35 + <div class="sitenav"> 36 + <span class="navlink"> 37 + </span> 38 + <span class="navlink"> 39 + <span class="navlink-label">Next:</span> <a href="1-section.html" accesskey="n" rel="next">2016</a> 40 + </span> 41 + </div> 42 + </nav> 43 + </header> 44 + <nav id="TOC" role="doc-toc"> 45 + <ul> 46 + <li><a href="1-section.html#section" id="toc-section">2016</a> 47 + <ul> 48 + <li><a href="1.1-day-1.html#day-1" id="toc-day-1">Day 1</a></li> 49 + <li><a href="1.2-day-2.html#day-2" id="toc-day-2">Day 2</a></li> 50 + </ul></li> 51 + <li><a href="2-section-1.html#section-1" id="toc-section-1">2025</a> 52 + <ul> 53 + <li><a href="2.1-day-2-1.html#day-2-1" id="toc-day-2-1">Day 2</a></li> 54 + <li><a href="2.2-day-4.html#day-4" id="toc-day-4">Day 4</a></li> 55 + <li><a href="2.3-day-5.html#day-5" id="toc-day-5">Day 5</a></li> 56 + </ul></li> 57 + </ul> 58 + </nav> 59 + 60 + </body> 61 + </html>
+1
out/sitemap.json
··· 1 + {"section":{"id":"","level":"0","number":null,"path":"index.html","title":""},"subsections":[{"section":{"id":"section","level":"1","number":"1","path":"1-section.html#section","title":"2016"},"subsections":[{"section":{"id":"day-1","level":"2","number":"1.1","path":"1.1-day-1.html#day-1","title":"Day 1"},"subsections":[{"section":{"id":"part-1","level":"3","number":"1.1.1","path":"1.1-day-1.html#part-1","title":"Part 1"},"subsections":[]},{"section":{"id":"part-2","level":"3","number":"1.1.2","path":"1.1-day-1.html#part-2","title":"Part 2"},"subsections":[]}]},{"section":{"id":"day-2","level":"2","number":"1.2","path":"1.2-day-2.html#day-2","title":"Day 2"},"subsections":[{"section":{"id":"part-1-1","level":"3","number":"1.2.1","path":"1.2-day-2.html#part-1-1","title":"Part 1"},"subsections":[]}]}]},{"section":{"id":"section-1","level":"1","number":"2","path":"2-section-1.html#section-1","title":"2025"},"subsections":[{"section":{"id":"day-2-1","level":"2","number":"2.1","path":"2.1-day-2-1.html#day-2-1","title":"Day 2"},"subsections":[{"section":{"id":"part-1-2","level":"3","number":"2.1.1","path":"2.1-day-2-1.html#part-1-2","title":"Part 1"},"subsections":[]},{"section":{"id":"part-2-1","level":"3","number":"2.1.2","path":"2.1-day-2-1.html#part-2-1","title":"Part 2"},"subsections":[]}]},{"section":{"id":"day-4","level":"2","number":"2.2","path":"2.2-day-4.html#day-4","title":"Day 4"},"subsections":[{"section":{"id":"part-1-3","level":"3","number":"2.2.1","path":"2.2-day-4.html#part-1-3","title":"Part 1"},"subsections":[]},{"section":{"id":"part-2-2","level":"3","number":"2.2.2","path":"2.2-day-4.html#part-2-2","title":"Part 2"},"subsections":[]}]},{"section":{"id":"day-5","level":"2","number":"2.3","path":"2.3-day-5.html#day-5","title":"Day 5"},"subsections":[{"section":{"id":"part-1-4","level":"3","number":"2.3.1","path":"2.3-day-5.html#part-1-4","title":"Part 1"},"subsections":[]},{"section":{"id":"part-2-3","level":"3","number":"2.3.2","path":"2.3-day-5.html#part-2-3","title":"Part 2"},"subsections":[]}]}]}]}
+85
out/style.css
··· 1 + body { 2 + max-width: 1000px; 3 + margin-left: auto; 4 + margin-right: auto; 5 + box-sizing: border-box; 6 + padding: 0 1vw; 7 + font-size-adjust: ex-height 0.53; 8 + } 9 + 10 + .sitenav { 11 + display: flex; 12 + justify-content: space-between; 13 + } 14 + 15 + p { 16 + text-align: justify; 17 + } 18 + 19 + .row { 20 + display: grid; 21 + grid-template-columns: 1fr 1fr; 22 + align-items: stretch; 23 + margin-left: auto; 24 + margin-right: auto; 25 + column-gap: 2rem; 26 + } 27 + 28 + .code { 29 + padding-bottom: 2rem; 30 + } 31 + 32 + #output-panel { 33 + position: fixed; 34 + bottom: 0; 35 + left: max(calc((100vw - 1000px) / 2), 1vw); 36 + right: max(calc((100vw - 1000px) / 2), 1vw); 37 + box-sizing: border-box; 38 + border: 1px solid black; 39 + } 40 + 41 + #panel-actions { 42 + display: flex; 43 + list-style: none; 44 + padding: 0.5rem; 45 + background-color: #D0D0F7; 46 + } 47 + 48 + #panel-actions::before { 49 + content: "+"; 50 + margin-right: 0.5rem; 51 + } 52 + 53 + details[open] #panel-actions::before { 54 + content: "−"; 55 + } 56 + 57 + #output-content { 58 + white-space: pre-wrap; 59 + word-wrap: break-word; 60 + font-family: monospace; 61 + padding: 0.5rem; 62 + max-height: 50lvh; 63 + background-color: white; 64 + overflow-y: auto; 65 + } 66 + 67 + .output-error { 68 + color: #8B0000; 69 + } 70 + 71 + @media (max-width: 768px) { 72 + body { 73 + max-width: 100%; 74 + } 75 + 76 + .row { 77 + grid-template-columns: 1fr; 78 + gap: 1rem; 79 + } 80 + 81 + .code { 82 + padding: 0; 83 + } 84 + } 85 +
+3
sync.sh
··· 1 + #! /usr/bin/env bash 2 + ssh kombu git -C /var/www/aoc pull 3 +