···11+<!DOCTYPE html>
22+<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
33+<head>
44+ <meta charset="utf-8" />
55+ <meta name="generator" content="pandoc" />
66+ <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
77+ <meta name="author" content="@oppi.li" />
88+ <title>Day 1</title>
99+ <style>
1010+ code{white-space: pre-wrap;}
1111+ span.smallcaps{font-variant: small-caps;}
1212+ div.columns{display: flex; gap: min(4vw, 1.5em);}
1313+ div.column{flex: auto; overflow-x: auto;}
1414+ div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
1515+ /* The extra [class] is a hack that increases specificity enough to
1616+ override a similar rule in reveal.js */
1717+ ul.task-list[class]{list-style: none;}
1818+ ul.task-list li input[type="checkbox"] {
1919+ font-size: inherit;
2020+ width: 0.8em;
2121+ margin: 0 0.8em 0.2em -1.6em;
2222+ vertical-align: middle;
2323+ }
2424+ .display.math{display: block; text-align: center; margin: 0.5rem auto;}
2525+ /* CSS for syntax highlighting */
2626+ html { -webkit-text-size-adjust: 100%; }
2727+ pre > code.sourceCode { white-space: pre; position: relative; }
2828+ pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
2929+ pre > code.sourceCode > span:empty { height: 1.2em; }
3030+ .sourceCode { overflow: visible; }
3131+ code.sourceCode > span { color: inherit; text-decoration: inherit; }
3232+ div.sourceCode { margin: 1em 0; }
3333+ pre.sourceCode { margin: 0; }
3434+ @media screen {
3535+ div.sourceCode { overflow: auto; }
3636+ }
3737+ @media print {
3838+ pre > code.sourceCode { white-space: pre-wrap; }
3939+ pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
4040+ }
4141+ pre.numberSource code
4242+ { counter-reset: source-line 0; }
4343+ pre.numberSource code > span
4444+ { position: relative; left: -4em; counter-increment: source-line; }
4545+ pre.numberSource code > span > a:first-child::before
4646+ { content: counter(source-line);
4747+ position: relative; left: -1em; text-align: right; vertical-align: baseline;
4848+ border: none; display: inline-block;
4949+ -webkit-touch-callout: none; -webkit-user-select: none;
5050+ -khtml-user-select: none; -moz-user-select: none;
5151+ -ms-user-select: none; user-select: none;
5252+ padding: 0 4px; width: 4em;
5353+ }
5454+ pre.numberSource { margin-left: 3em; padding-left: 4px; }
5555+ div.sourceCode
5656+ { }
5757+ @media screen {
5858+ pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
5959+ }
6060+ code span.al { font-weight: bold; } /* Alert */
6161+ code span.an { font-style: italic; } /* Annotation */
6262+ code span.cf { font-weight: bold; } /* ControlFlow */
6363+ code span.co { font-style: italic; } /* Comment */
6464+ code span.cv { font-style: italic; } /* CommentVar */
6565+ code span.do { font-style: italic; } /* Documentation */
6666+ code span.dt { color: #8f4e8b; } /* DataType */
6767+ code span.er { font-weight: bold; } /* Error */
6868+ code span.in { font-style: italic; } /* Information */
6969+ code span.kw { font-weight: bold; } /* Keyword */
7070+ code span.pp { font-weight: bold; } /* Preprocessor */
7171+ code span.wa { font-style: italic; } /* Warning */
7272+ </style>
7373+ <link rel="stylesheet" href="style.css" />
7474+ <link rel="preconnect" href="https://fonts.googleapis.com">
7575+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
7676+ <link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@300..700&family=Libre+Baskerville:ital,wght@0,400..700;1,400..700&display=swap" rel="stylesheet">
7777+</head>
7878+<body>
7979+ <nav id="sitenav">
8080+ <div class="sitenav">
8181+ <span class="navlink">
8282+ <span class="navlink-label">Up:</span> <a href="2-section-1.html" accesskey="u" rel="up">2025</a>
8383+ </span>
8484+ <span class="navlink">
8585+ <span class="navlink-label">Top:</span> <a href="index.html" accesskey="t" rel="top">The Book of Solves</a>
8686+ </span>
8787+ </div>
8888+ <div class="sitenav">
8989+ <span class="navlink">
9090+ <span class="navlink-label">Previous:</span> <a href="2-section-1.html" accesskey="p" rel="previous">2025</a>
9191+ </span>
9292+ <span class="navlink">
9393+ <span class="navlink-label">Next:</span> <a href="2.2-day-2-1.html" accesskey="n" rel="next">Day 2</a>
9494+ </span>
9595+ </div>
9696+ </nav>
9797+9898+ <h2 data-number="2.1" id="day-1-1">Day 1</h2>
9999+ <div class="row">
100100+ <p>Parse the input:</p>
101101+ <div class="code">
102102+ <div class="sourceCode" id="cb1"><pre
103103+ class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">parse ::</span> <span class="dt">String</span> <span class="ot">-></span> [<span class="dt">Int</span>]</span>
104104+<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>parse <span class="ot">=</span> <span class="fu">map</span> f <span class="op">.</span> <span class="fu">lines</span></span>
105105+<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span> f (<span class="ch">'L'</span><span class="op">:</span>r) <span class="ot">=</span> <span class="fu">negate</span> (<span class="fu">read</span> r)</span>
106106+<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a> f (<span class="ch">'R'</span><span class="op">:</span>r) <span class="ot">=</span> <span class="fu">read</span> r</span></code></pre></div>
107107+ </div>
108108+ </div>
109109+ <h3 data-number="2.1.1" id="part-1-2">Part 1</h3>
110110+ <div class="row">
111111+ <p>Rotate the dial starting at 50, and count the number of times
112112+ we stop at zero on the way. Of note is that the dial cycles back
113113+ to zero after 100, so our check mustn’t just be <code>== 0</code>
114114+ but rather, <code>mod n 100 == 0</code>:</p>
115115+ <div class="code">
116116+ <div class="sourceCode" id="cb2"><pre
117117+ class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">count ::</span> (a <span class="ot">-></span> <span class="dt">Bool</span>) <span class="ot">-></span> [a] <span class="ot">-></span> <span class="dt">Int</span></span>
118118+<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>count <span class="fu">pred</span> <span class="ot">=</span> <span class="fu">length</span> <span class="op">.</span> <span class="fu">filter</span> <span class="fu">pred</span></span>
119119+<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a></span>
120120+<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="ot">clicks ::</span> [<span class="dt">Int</span>] <span class="ot">-></span> <span class="dt">Int</span></span>
121121+<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>clicks <span class="ot">=</span> count ((<span class="op">==</span> <span class="dv">0</span>) <span class="op">.</span> (<span class="ot">`mod`</span> <span class="dv">100</span>)) <span class="op">.</span> <span class="fu">scanl</span> (<span class="op">+</span>) <span class="dv">50</span></span></code></pre></div>
122122+ </div>
123123+ </div>
124124+ <div class="row">
125125+ <p>Thus, the solution to the first part is given by:</p>
126126+ <div class="code">
127127+ <div class="sourceCode" id="cb3"><pre
128128+ 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">-></span> <span class="dt">Int</span></span>
129129+<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>p1 <span class="ot">=</span> clicks</span></code></pre></div>
130130+ </div>
131131+ </div>
132132+ <h3 data-number="2.1.2" id="part-2-1">Part 2</h3>
133133+ <div class="row">
134134+ <p>This part is ever so slightly different, instead of the number
135135+ of times we <em>stop</em> are zero, we are required to
136136+ additionally calculate the number of times we <em>pass</em>
137137+ through zero.</p>
138138+ <div class="code">
139139+140140+ </div>
141141+ </div>
142142+ <div class="row">
143143+ <p>To think of this a bit differently, the first part has lower
144144+ degree of precision: we only perform the check after the dial is
145145+ fully rotated. The second part requires us to perform the check
146146+ with higher degree of precision: after each movement by 1. Thus,
147147+ if we modify our list to change one rotation of size N into N
148148+ rotations of size 1, we will be able to reuse our
149149+ <code>clicks</code> method:</p>
150150+ <div class="code">
151151+ <div class="sourceCode" id="cb4"><pre
152152+ class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ot">transform ::</span> <span class="dt">Int</span> <span class="ot">-></span> [<span class="dt">Int</span>]</span>
153153+<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>transform n <span class="ot">=</span> <span class="fu">replicate</span> (<span class="fu">abs</span> n) (<span class="fu">signum</span> n)</span>
154154+<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a></span>
155155+<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="ot">p2 ::</span> [<span class="dt">Int</span>] <span class="ot">-></span> <span class="dt">Int</span></span>
156156+<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>p2 <span class="ot">=</span> clicks <span class="op">.</span> <span class="fu">concatMap</span> transform</span></code></pre></div>
157157+ </div>
158158+ </div>
159159+ <div class="row">
160160+ <p>Finally, a main function to wrap it all up:</p>
161161+ <div class="code">
162162+ <div class="sourceCode" id="cb5"><pre
163163+ class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="kw">do</span></span>
164164+<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a> n <span class="ot"><-</span> parse <span class="op"><$></span> <span class="fu">getContents</span></span>
165165+<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">print</span> <span class="op">$</span> p1 n</span>
166166+<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">print</span> <span class="op">$</span> p2 n</span></code></pre></div>
167167+ </div>
168168+ </div>
169169+ </body>
170170+</html>
+5-5
out/2.1-day-2-1.html
out/2.2-day-2-1.html
···8787 </div>
8888 <div class="sitenav">
8989 <span class="navlink">
9090- <span class="navlink-label">Previous:</span> <a href="2-section-1.html" accesskey="p" rel="previous">2025</a>
9090+ <span class="navlink-label">Previous:</span> <a href="2.1-day-1-1.html" accesskey="p" rel="previous">Day 1</a>
9191 </span>
9292 <span class="navlink">
9393- <span class="navlink-label">Next:</span> <a href="2.2-day-4.html" accesskey="n" rel="next">Day 4</a>
9393+ <span class="navlink-label">Next:</span> <a href="2.3-day-4.html" accesskey="n" rel="next">Day 4</a>
9494 </span>
9595 </div>
9696 </nav>
97979898- <h2 data-number="2.1" id="day-2-1">Day 2</h2>
9898+ <h2 data-number="2.2" id="day-2-1">Day 2</h2>
9999 <div class="row">
100100 <p>Starting with the parse step, the input is of the form
101101 <code>11-22,15-17,...</code>. So we first split on commas, for
···116116117117 </div>
118118 </div>
119119- <h3 data-number="2.1.1" id="part-1-2">Part 1</h3>
119119+ <h3 data-number="2.2.1" id="part-1-3">Part 1</h3>
120120 <div class="row">
121121 <p>The check for invalidity for an integer in Part 1 requires us
122122 to simply split the string in half and ensure that the two halves
···143143<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>
144144 </div>
145145 </div>
146146- <h3 data-number="2.1.2" id="part-2-1">Part 2</h3>
146146+ <h3 data-number="2.2.2" id="part-2-2">Part 2</h3>
147147 <div class="row">
148148 <p>This part requires a slight modification to the invalidity
149149 check. We now need to check for any number of repeating
+5-5
out/2.2-day-4.html
out/2.3-day-4.html
···8787 </div>
8888 <div class="sitenav">
8989 <span class="navlink">
9090- <span class="navlink-label">Previous:</span> <a href="2.1-day-2-1.html" accesskey="p" rel="previous">Day 2</a>
9090+ <span class="navlink-label">Previous:</span> <a href="2.2-day-2-1.html" accesskey="p" rel="previous">Day 2</a>
9191 </span>
9292 <span class="navlink">
9393- <span class="navlink-label">Next:</span> <a href="2.3-day-5.html" accesskey="n" rel="next">Day 5</a>
9393+ <span class="navlink-label">Next:</span> <a href="2.4-day-5.html" accesskey="n" rel="next">Day 5</a>
9494 </span>
9595 </div>
9696 </nav>
97979898- <h2 data-number="2.2" id="day-4">Day 4</h2>
9898+ <h2 data-number="2.3" id="day-4">Day 4</h2>
9999 <div class="row">
100100 <p>As always, we start by parsing the input into something more
101101 manageable:</p>
···134134135135 </div>
136136 </div>
137137- <h3 data-number="2.2.1" id="part-1-3">Part 1</h3>
137137+ <h3 data-number="2.3.1" id="part-1-4">Part 1</h3>
138138 <div class="row">
139139 <p>This part requires us to first calculate all points adjacent to
140140 a roll, if there are more than 4 rolls at these adjacent
···177177 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>
178178 </div>
179179 </div>
180180- <h3 data-number="2.2.2" id="part-2-2">Part 2</h3>
180180+ <h3 data-number="2.3.2" id="part-2-3">Part 2</h3>
181181 <div class="row">
182182 <p>This part is very similar to the previous part. We need to
183183 sequentially remove liftable rolls until we can lift no more. A
+5-5
out/2.3-day-5.html
out/2.4-day-5.html
···8787 </div>
8888 <div class="sitenav">
8989 <span class="navlink">
9090- <span class="navlink-label">Previous:</span> <a href="2.2-day-4.html" accesskey="p" rel="previous">Day 4</a>
9090+ <span class="navlink-label">Previous:</span> <a href="2.3-day-4.html" accesskey="p" rel="previous">Day 4</a>
9191 </span>
9292 <span class="navlink">
9393- <span class="navlink-label">Next:</span> <a href="2.4-day-6.html" accesskey="n" rel="next">Day 6</a>
9393+ <span class="navlink-label">Next:</span> <a href="2.5-day-6.html" accesskey="n" rel="next">Day 6</a>
9494 </span>
9595 </div>
9696 </nav>
97979898- <h2 data-number="2.3" id="day-5">Day 5</h2>
9898+ <h2 data-number="2.4" id="day-5">Day 5</h2>
9999 <div class="row">
100100 <p>As always, we start by parsing the input into something more
101101 manageable.</p>
···132132<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">>=</span> start <span class="op">&&</span> e <span class="op"><=</span> end</span></code></pre></div>
133133 </div>
134134 </div>
135135- <h3 data-number="2.3.1" id="part-1-4">Part 1</h3>
135135+ <h3 data-number="2.4.1" id="part-1-5">Part 1</h3>
136136 <div class="row">
137137 <p>For part one, we need to count how many of the available
138138 ingredient IDs are fresh. An ID is fresh if it falls within
···143143<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">-></span> <span class="fu">any</span> (contains p) is)</span></code></pre></div>
144144 </div>
145145 </div>
146146- <h3 data-number="2.3.2" id="part-2-3">Part 2</h3>
146146+ <h3 data-number="2.4.2" id="part-2-4">Part 2</h3>
147147 <div class="row">
148148 <p>For part two, we need to count the total number of unique
149149 ingredient IDs covered by all the fresh ranges. The methodology
+5-5
out/2.4-day-6.html
out/2.5-day-6.html
···8787 </div>
8888 <div class="sitenav">
8989 <span class="navlink">
9090- <span class="navlink-label">Previous:</span> <a href="2.3-day-5.html" accesskey="p" rel="previous">Day 5</a>
9090+ <span class="navlink-label">Previous:</span> <a href="2.4-day-5.html" accesskey="p" rel="previous">Day 5</a>
9191 </span>
9292 <span class="navlink">
9393- <span class="navlink-label">Next:</span> <a href="2.5-day-9.html" accesskey="n" rel="next">Day 9</a>
9393+ <span class="navlink-label">Next:</span> <a href="2.6-day-9.html" accesskey="n" rel="next">Day 9</a>
9494 </span>
9595 </div>
9696 </nav>
97979898- <h2 data-number="2.4" id="day-6">Day 6</h2>
9898+ <h2 data-number="2.5" id="day-6">Day 6</h2>
9999 <div class="row">
100100 <p>This day is largely string munging, which is quite boring, but
101101 also quite easy to do with Haskell!</p>
···103103104104 </div>
105105 </div>
106106- <h3 data-number="2.4.1" id="part-1-5">Part 1</h3>
106106+ <h3 data-number="2.5.1" id="part-1-6">Part 1</h3>
107107 <div class="row">
108108 <p>This part needs us to consider each operation on a column.
109109 <code>Data.List.transpose</code> fortunately makes this very
···158158 </div>
159159 </div>
160160 <pre><code>[["+", "1", "2", "3"], ["*", "4", "5", "6"]]</code></pre>
161161- <h3 data-number="2.4.2" id="part-2-4">Part 2</h3>
161161+ <h3 data-number="2.5.2" id="part-2-5">Part 2</h3>
162162 <div class="row">
163163 <p>We are now tasked with lining up the digits in a columnar
164164 fashion to form a number:</p>
+4-4
out/2.5-day-9.html
out/2.6-day-9.html
···8787 </div>
8888 <div class="sitenav">
8989 <span class="navlink">
9090- <span class="navlink-label">Previous:</span> <a href="2.4-day-6.html" accesskey="p" rel="previous">Day 6</a>
9090+ <span class="navlink-label">Previous:</span> <a href="2.5-day-6.html" accesskey="p" rel="previous">Day 6</a>
9191 </span>
9292 <span class="navlink">
9393 </span>
9494 </div>
9595 </nav>
96969797- <h2 data-number="2.5" id="day-9">Day 9</h2>
9797+ <h2 data-number="2.6" id="day-9">Day 9</h2>
9898 <div class="row">
9999 <p>This day’s problem is based on simple coordinate geometry.</p>
100100 <div class="code">
···120120121121 </div>
122122 </div>
123123- <h3 data-number="2.5.1" id="part-1-6">Part 1</h3>
123123+ <h3 data-number="2.6.1" id="part-1-7">Part 1</h3>
124124 <div class="row">
125125 <p>This part requires us to simply find a rectangle with the
126126 largest area among the points given to us, so first write a method
···142142<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>p1 poly <span class="ot">=</span> <span class="fu">maximum</span> [area p p' <span class="op">|</span> p <span class="ot"><-</span> poly, p' <span class="ot"><-</span> poly]</span></code></pre></div>
143143 </div>
144144 </div>
145145- <h3 data-number="2.5.2" id="part-2-5">Part 2</h3>
145145+ <h3 data-number="2.6.2" id="part-2-6">Part 2</h3>
146146 <div class="row">
147147 <p>This part is a whole lot trickier. We now require only
148148 rectangles that fall <em>within</em> the polygon. Rectangles that
···11+# 2025
22+33+## Day 1
44+55+Parse the input:
66+77+```haskell
88+parse :: String -> [Int]
99+parse = map f . lines
1010+ where f ('L':r) = negate (read r)
1111+ f ('R':r) = read r
1212+```
1313+1414+### Part 1
1515+1616+Rotate the dial starting at 50, and count the number of times we stop at zero on the way. Of note is that the dial cycles back to zero after 100, so our check mustn't just be `== 0` but rather, `mod n 100 == 0`:
1717+1818+```haskell
1919+count :: (a -> Bool) -> [a] -> Int
2020+count pred = length . filter pred
2121+2222+clicks :: [Int] -> Int
2323+clicks = count ((== 0) . (`mod` 100)) . scanl (+) 50
2424+```
2525+2626+Thus, the solution to the first part is given by:
2727+2828+```haskell
2929+p1 :: [Int] -> Int
3030+p1 = clicks
3131+```
3232+3333+### Part 2
3434+3535+This part is ever so slightly different, instead of the number of times we *stop* are zero, we are required to additionally calculate the number of times we *pass* through zero.
3636+3737+To think of this a bit differently, the first part has lower degree of precision: we only perform the check after the dial is fully rotated. The second part requires us to perform the check with higher degree of precision: after each movement by 1. Thus, if we modify our list to change one rotation of size N into N rotations of size 1, we will be able to reuse our `clicks` method:
3838+3939+```haskell
4040+transform :: Int -> [Int]
4141+transform n = replicate (abs n) (signum n)
4242+4343+p2 :: [Int] -> Int
4444+p2 = clicks . concatMap transform
4545+```
4646+4747+Finally, a main function to wrap it all up:
4848+4949+```haskell
5050+main = do
5151+ n <- parse <$> getContents
5252+ print $ p1 n
5353+ print $ p2 n
5454+```
5555+