advent of code solutions aoc.oppi.li
haskell aoc

2025/06: clean up prose a bit, reduce 1 import

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

oppi.li c65bb314 7abe1780

verified
+87 -43
+50 -32
out/2.4-day-6.html
··· 119 119 <div class="row"> 120 120 <p>Thus, to solve the first part, we can break up our input using 121 121 <code>lines</code>. <code>rot</code> is a simple function that 122 - rotates a list forwards to move the last element to the first. By 123 - doing <code>rot . lines</code> upon our input, we have a list of 124 - the form <code>["+ *", "1 2 3", "4 5 6"]</code>. Next, we define 125 - an <code>align</code> function to line up the colums. This method 126 - simply breaks each item in the list by spaces, and then transposes 127 - them, so we end up with 128 - <code>[["+", "1", "2", "3"], ["*", "4", "5", "6"]]</code>:</p> 122 + rotates a list forwards to move the last element to the first.</p> 129 123 <div class="code"> 130 124 <div class="sourceCode" id="cb2"><pre 131 - class="sourceCode haskell haskell-top"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Char</span> (isSpace)</span> 132 - <span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.List</span> (transpose)</span> 133 - <span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.List.Split</span> (splitWhen)</span></code></pre></div> 134 - <div class="sourceCode" id="cb3"><pre 135 - class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>rot <span class="ot">=</span> liftA2 (<span class="op">:</span>) <span class="fu">last</span> <span class="fu">init</span></span> 136 - <span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a></span> 137 - <span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>p1 <span class="ot">=</span> <span class="fu">sum</span> <span class="op">.</span> <span class="fu">map</span> solve <span class="op">.</span> align <span class="op">.</span> rot <span class="op">.</span> <span class="fu">lines</span></span> 138 - <span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span> 139 - <span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a> align <span class="ot">=</span> transpose <span class="op">.</span> <span class="fu">map</span> <span class="fu">words</span></span></code></pre></div> 125 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>rot <span class="ot">=</span> liftA2 (<span class="op">:</span>) <span class="fu">last</span> <span class="fu">init</span></span></code></pre></div> 126 + </div> 127 + </div> 128 + <div class="row"> 129 + <p>By doing <code>rot . lines</code> upon our input, we have a 130 + list of the form:</p> 131 + <div class="code"> 132 + 133 + </div> 134 + </div> 135 + <pre><code>[&quot;+ *&quot;, &quot;1 2 3&quot;, &quot;4 5 6&quot;]</code></pre> 136 + <div class="row"> 137 + <p>Next, we define an <code>align</code> function to line up the 138 + columns, and define our solution to part 1 like so:</p> 139 + <div class="code"> 140 + <div class="sourceCode" id="cb4"><pre 141 + 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> (transpose)</span></code></pre></div> 142 + <div class="sourceCode" id="cb5"><pre 143 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a></span> 144 + <span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>p1 <span class="ot">=</span> <span class="fu">sum</span> <span class="op">.</span> <span class="fu">map</span> solve <span class="op">.</span> align <span class="op">.</span> rot <span class="op">.</span> <span class="fu">lines</span></span> 145 + <span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span> 146 + <span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a> align <span class="ot">=</span> transpose <span class="op">.</span> <span class="fu">map</span> <span class="fu">words</span></span></code></pre></div> 140 147 </div> 141 148 </div> 149 + <div class="row"> 150 + <p>This method simply breaks each item in the list by spaces, and 151 + then transposes them, so we end up with:</p> 152 + <div class="code"> 153 + 154 + </div> 155 + </div> 156 + <pre><code>[[&quot;+&quot;, &quot;1&quot;, &quot;2&quot;, &quot;3&quot;], [&quot;*&quot;, &quot;4&quot;, &quot;5&quot;, &quot;6&quot;]]</code></pre> 142 157 <h3 data-number="2.4.2" id="part-2-4">Part 2</h3> 143 158 <div class="row"> 144 159 <p>We are now tasked with lining up the digits in a columnar 145 - fashion to for a number:</p> 160 + fashion to form a number:</p> 146 161 <div class="code"> 147 162 148 163 </div> ··· 185 200 operators to the start. Our <code>align</code> function can now be 186 201 defined as below.</p> 187 202 <div class="code"> 188 - <div class="sourceCode" id="cb7"><pre 189 - 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> <span class="fu">sum</span> <span class="op">.</span> <span class="fu">map</span> solve <span class="op">.</span> align <span class="op">.</span> rot <span class="op">.</span> <span class="fu">lines</span></span> 190 - <span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span> 191 - <span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a> align <span class="ot">=</span></span> 192 - <span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">zipWith</span> (<span class="op">:</span>)</span> 193 - <span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a> <span class="op">&lt;$&gt;</span> (<span class="fu">words</span> <span class="op">.</span> <span class="fu">head</span>)</span> 194 - <span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a> <span class="op">&lt;*&gt;</span> (splitWhen (<span class="fu">all</span> <span class="fu">isSpace</span>) <span class="op">.</span> transpose <span class="op">.</span> <span class="fu">tail</span>)</span></code></pre></div> 203 + <div class="sourceCode" id="cb10"><pre 204 + class="sourceCode haskell haskell-top"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.List.Split</span> (splitWhen)</span></code></pre></div> 205 + <div class="sourceCode" id="cb11"><pre 206 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>p2 <span class="ot">=</span> <span class="fu">sum</span> <span class="op">.</span> <span class="fu">map</span> solve <span class="op">.</span> align <span class="op">.</span> rot <span class="op">.</span> <span class="fu">lines</span></span> 207 + <span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span> 208 + <span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a> align <span class="ot">=</span></span> 209 + <span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">zipWith</span> (<span class="op">:</span>)</span> 210 + <span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a> <span class="op">&lt;$&gt;</span> (<span class="fu">words</span> <span class="op">.</span> <span class="fu">head</span>)</span> 211 + <span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a> <span class="op">&lt;*&gt;</span> (splitWhen (<span class="fu">all</span> (<span class="ch">&#39; &#39;</span> <span class="op">==</span>)) <span class="op">.</span> transpose <span class="op">.</span> <span class="fu">tail</span>)</span></code></pre></div> 195 212 </div> 196 213 </div> 197 214 <div class="row"> ··· 205 222 <pre><code>[&quot;+&quot;, &quot;1&quot;, &quot;2&quot;, ...]</code></pre> 206 223 <div class="row"> 207 224 <p>Remember that this is the format <code>solve</code> 208 - accepts!.</p> 225 + accepts!</p> 209 226 <div class="code"> 210 227 211 228 </div> ··· 242 259 <pre><code>[&quot;1 &quot;,&quot;24 &quot;,&quot;356&quot;,&quot; &quot;,&quot;369&quot;,&quot;248&quot;,&quot;8 &quot;, ...]</code></pre> 243 260 <div class="row"> 244 261 <p>There is an element containing all spaces (which was present 245 - between each column!). This is what we use to separate each 246 - column.</p> 262 + between each column), <code>Data.List.Split.splitWhen</code> is 263 + employed to detect and chunk our list into runs of valid 264 + numbers.</p> 247 265 <div class="code"> 248 266 249 267 </div> ··· 251 269 <div class="row"> 252 270 <p>Finally, a main function to wrap it all up:</p> 253 271 <div class="code"> 254 - <div class="sourceCode" id="cb12"><pre 255 - class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span> 256 - <span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a> n <span class="ot">&lt;-</span> <span class="fu">getContents</span></span> 257 - <span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">print</span> <span class="op">$</span> p1 n</span> 258 - <span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">print</span> <span class="op">$</span> p2 n</span></code></pre></div> 272 + <div class="sourceCode" id="cb16"><pre 273 + class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span> 274 + <span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a> n <span class="ot">&lt;-</span> <span class="fu">getContents</span></span> 275 + <span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">print</span> <span class="op">$</span> p1 n</span> 276 + <span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">print</span> <span class="op">$</span> p2 n</span></code></pre></div> 259 277 </div> 260 278 </div> 261 279 </body>
+15 -5
readme.txt
··· 1 - aoc 2 - --- 1 + aoc.oppi.li 2 + ----------- 3 3 4 - solutions for aoc written in haskell 4 + solutions for aoc written in literate haskell, and exported 5 + to a "book of solves": aoc.oppi.li 5 6 6 - all solutions are (soon) to be written in literate haskell 7 - and exported to an interactive book using ./book/build.sh. 7 + to compile the unlit program: 8 + 9 + ghc unlit/unlit.hs -o bin/unlit 10 + 11 + to execute a solution: 12 + 13 + cat input | runhaskell --ghc-arg="-pgmL ./bin/unlit" 01.lhs 14 + 15 + to build the book of solves (requires pandoc): 16 + 17 + ./book/build.sh
+22 -6
src/2025/06.lhs
··· 11 11 solve ("*" : rest) = product . map read $ rest 12 12 ``` 13 13 14 - Thus, to solve the first part, we can break up our input using `lines`. `rot` is a simple function that rotates a list forwards to move the last element to the first. By doing `rot . lines` upon our input, we have a list of the form `["+ *", "1 2 3", "4 5 6"]`. Next, we define an `align` function to line up the colums. This method simply breaks each item in the list by spaces, and then transposes them, so we end up with `[["+", "1", "2", "3"], ["*", "4", "5", "6"]]`: 14 + Thus, to solve the first part, we can break up our input using `lines`. `rot` is a simple function that rotates a list forwards to move the last element to the first. 15 + 16 + ```haskell 17 + rot = liftA2 (:) last init 18 + ``` 19 + 20 + By doing `rot . lines` upon our input, we have a list of the form: 21 + 22 + ["+ *", "1 2 3", "4 5 6"] 23 + 24 + Next, we define an `align` function to line up the columns, and define our solution to part 1 like so: 15 25 16 26 ```haskell-top 17 - import Data.Char (isSpace) 18 27 import Data.List (transpose) 19 - import Data.List.Split (splitWhen) 20 28 ``` 21 29 22 30 ```haskell 23 - rot = liftA2 (:) last init 24 31 25 32 p1 = sum . map solve . align . rot . lines 26 33 where 27 34 align = transpose . map words 28 35 ``` 29 36 37 + This method simply breaks each item in the list by spaces, and then transposes them, so we end up with: 38 + 39 + [["+", "1", "2", "3"], ["*", "4", "5", "6"]] 40 + 41 + 30 42 ### Part 2 31 43 32 - We are now tasked with lining up the digits in a columnar fashion to for a number: 44 + We are now tasked with lining up the digits in a columnar fashion to form a number: 33 45 34 46 123 ... 35 47 45 ... ··· 52 64 53 65 Let us start with a similar base, using `lines` to break things up, and `rot` to move the line of operators to the start. Our `align` function can now be defined as below. 54 66 67 + ```haskell-top 68 + import Data.List.Split (splitWhen) 69 + ``` 70 + 55 71 ```haskell 56 72 p2 = sum . map solve . align . rot . lines 57 73 where 58 74 align = 59 75 zipWith (:) 60 76 <$> (words . head) 61 - <*> (splitWhen (all isSpace) . transpose . tail) 77 + <*> (splitWhen (all (' ' ==)) . transpose . tail) 62 78 ``` 63 79 64 80 We first start with `zipWith (:)` to join the operation `"+"` with the rest of the numbers to produce: