-
Notifications
You must be signed in to change notification settings - Fork 1
/
day01.html
550 lines (498 loc) Β· 29.2 KB
/
day01.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
<!DOCTYPE html>
<html lang="en-us">
<head>
<title>2021/day01.nim</title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2280%22>π³</text></svg>">
<meta content="text/html; charset=utf-8" http-equiv="content-type">
<meta content="width=device-width, initial-scale=1" name="viewport">
<link rel='stylesheet' href='https://unpkg.com/normalize.css/'>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/kognise/water.css@latest/dist/dark.min.css">
<link rel='stylesheet' href='https://cdn.jsdelivr.net/gh/pietroppeter/nimib/assets/androidstudio.css'>
<style>
.nb-box {
display: flex;
align-items: center;
justify-content: space-between;
}
.nb-small {
font-size: 0.8rem;
}
button.nb-small {
float: right;
padding: 2px;
padding-right: 5px;
padding-left: 5px;
}
section#source {
display:none
}
</style>
<script async defer data-domain="pietroppeter.github.io/adventofnim" src="https://plausible.io/js/plausible.js"></script>
<style>
a {
text-decoration: none;
color: #009900;
}
a:hover {
color: #99ff99;
}
em {
color: #ffffff;
font-style: normal;
text-shadow: 0 0 5px #ffffff;
}
em.star {
font-style: normal;
color: #ffff66;
text-shadow: 0 0 5px #ffff66;
}
</style>
</head>
<body>
<header>
<div class="nb-box">
<span><a href="..">π‘</a></span>
<span><code>2021/day01.nim</code></span>
<span><a href="https://github.com/pietroppeter/adventofnim"><svg aria-hidden="true" width="1.2em" height="1.2em" style="vertical-align: middle; fill: #fff" preserveAspectRatio="xMidYMid meet" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path></svg></a></span>
</div>
<hr>
</header><main>
<h2>2021, day 1: <a href="https://adventofcode.com/2021/day/1">Sonar Sweep</a> β΄οΈπ</h2>
<p>Another year of <a href="https://forum.nim-lang.org/t/8657">Advent of Nim</a> ππ!</p>
<p><em>This year I would like to try and use cool nim libraries
for visualization</em> and similar stuff.
I will most likely be able to keep up only for a few days, but let's see.</p>
<p>But let's get to the first problem.
As usual we have a sequence of integers as input.</p>
<p>What is new this year is that,
<a href="https://nim-lang.org/blog/2021/10/19/version-160-released.html">thanks to 1.6</a>
we can use <code>toSeq</code> with method call syntax!</p>
<pre><code class="nim hljs"><span class="hljs-keyword">let</span> input: <span class="hljs-built_in">seq</span>[<span class="hljs-built_in">int</span>] = <span class="hljs-string">"2021/input01.txt"</span>.lines.toSeq.map(parseInt)
<span class="hljs-keyword">echo</span> input.len
<span class="hljs-keyword">echo</span> input[<span class="hljs-number">0</span> .. <span class="hljs-number">10</span>]
<span class="hljs-keyword">echo</span> input[^<span class="hljs-number">10</span> .. ^<span class="hljs-number">1</span>]</code></pre>
<pre><samp>2000
@[104, 105, 109, 120, 124, 113, 120, 121, 122, 123, 134]
@[7678, 7680, 7692, 7712, 7724, 7730, 7736, 7737, 7746, 7759]
</samp></pre>
<h3>Part 1</h3>
<blockquote>
<p>As the submarine drops below the surface of the ocean, it automatically performs a sonar sweep of the nearby sea floor. On a small screen, the sonar sweep report (your puzzle input) appears: each line is a measurement of the sea floor depth as the sweep looks further and further away from the submarine.</p>
<p>For example, suppose you had the following report:</p>
</blockquote>
<pre><code class="nim hljs"><span class="hljs-keyword">let</span> report = <span class="hljs-string">"""
199
200
208
210
200
207
240
269
260
263"""</span></code></pre>
<blockquote>
<p>This report indicates that, scanning outward from the submarine, the sonar sweep found depths of 199, 200, 208, 210, and so on.</p>
<p>The first order of business is to figure out how quickly the depth increases, ...</p>
<p>To do this, count the <em>number of times a depth measurement increases</em> from the previous measurement</p>
<p>... In this example, there are 7 measurements that are larger than the previous measurement.</p>
</blockquote>
<p>The solution for part1 (as expected) is pretty straightforward.
Just make sure you start from index 1:</p>
<pre><code class="nim hljs"><span class="hljs-keyword">func</span> countIncrease(s: <span class="hljs-built_in">seq</span>[<span class="hljs-built_in">int</span>]): <span class="hljs-built_in">int</span> =
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-number">1</span> .. s.<span class="hljs-keyword">high</span>:
<span class="hljs-keyword">if</span> s[i] > s[i - <span class="hljs-number">1</span>]:
inc <span class="hljs-literal">result</span>
<span class="hljs-keyword">let</span> testInput = report.splitLines.toSeq.map(parseInt)
doAssert testInput.countIncrease == <span class="hljs-number">7</span>
<span class="hljs-keyword">echo</span> countIncrease(input)</code></pre>
<pre><samp>1557
</samp></pre>
<p>That's the right answer! You are <em class="star">one gold star</em> closer to saving your vacation.</p>
<h3>Part 2</h3>
<blockquote>
<p>Considering every single measurement isn't as useful as you expected: there's just too much noise in the data.</p>
<p>Instead, consider <em>sums of a three-measurement sliding window</em>.</p>
<p>... Your goal now is to count <em>the number of times the sum of measurements in this sliding window increases</em> from the previous sum.</p>
<p>... In [test] example, there are 5 sums that are larger than the previous sum.</p>
</blockquote>
<p>let's create a function that copmutes the window function of a sequence,
then we will apply previous function to the result.</p>
<pre><code class="nim hljs"><span class="hljs-keyword">func</span> window(s: <span class="hljs-built_in">seq</span>[<span class="hljs-built_in">int</span>], size=<span class="hljs-number">3</span>): <span class="hljs-built_in">seq</span>[<span class="hljs-built_in">int</span>] =
<span class="hljs-keyword">assert</span> s.len >= size
<span class="hljs-keyword">var</span> sum = s[<span class="hljs-number">0</span> ..< size].sum
<span class="hljs-literal">result</span>.add sum
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> size .. s.<span class="hljs-keyword">high</span>:
sum = sum - s[i - size] + s[i]
<span class="hljs-literal">result</span>.add sum
<span class="hljs-keyword">echo</span> input[<span class="hljs-number">0</span> ..< <span class="hljs-number">10</span>]
<span class="hljs-keyword">echo</span> input[<span class="hljs-number">0</span> ..< <span class="hljs-number">10</span>].window</code></pre>
<pre><samp>@[104, 105, 109, 120, 124, 113, 120, 121, 122, 123]
@[318, 334, 353, 357, 357, 354, 363, 366]
</samp></pre>
<pre><code class="nim hljs">doAssert testInput.window.countIncrease == <span class="hljs-number">5</span>
<span class="hljs-keyword">echo</span> input.window.countIncrease</code></pre>
<pre><samp>1608
</samp></pre>
<p>That's the right answer! You are <em class="star">one gold star</em> closer to saving your vacation.</p>
<h3>Optimizing part 2</h3>
<p>As hinted by <a href="https://github.com/narimiran">narimiran</a> in our nim-aoc discord chat,
there is a simpler way to compute part 2 that also reveals that <em>the "window" approach
does not really denoise the signal</em>. Since two successive windows of 3 depths have 2 overlapping
depth, to check if there is an increase we only need to check first and last depth:</p>
<pre><code class="nim hljs"><span class="hljs-keyword">func</span> countIncrease2(s: <span class="hljs-built_in">seq</span>[<span class="hljs-built_in">int</span>], window=<span class="hljs-number">3</span>): <span class="hljs-built_in">int</span> =
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-number">0</span> ..< (s.len - window):
<span class="hljs-keyword">if</span> s[i + window] > s[i]:
inc <span class="hljs-literal">result</span>
<span class="hljs-keyword">echo</span> input.countIncrease2</code></pre>
<pre><samp>1608
</samp></pre>
<h3>Visualization</h3>
<p>I will use the excellent <a href="https://github.com/Vindaar/ggplotnim">ggplotnim</a>
to plot the depth profile and the dataframe library <a href="https://github.com/SciNim/Datamancer">datamancer</a>
(implictly imported through ggplotnim) to manage the data.
Thanks to <a href="https://github.com/Vindaar">Vindaar</a> for help in this section</p>
<pre><code class="nim hljs"><span class="hljs-keyword">import</span> ggplotnim
<span class="hljs-keyword">var</span> df = seqsToDf({<span class="hljs-string">"depth"</span>: input}) <span class="hljs-comment"># toDf(input): new column will be named input</span>
df[<span class="hljs-string">"x"</span>] = collect:
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-number">1</span> .. input.len:
i
<span class="hljs-keyword">echo</span> df
<span class="hljs-keyword">let</span>
dark = parseHex(<span class="hljs-string">"202b38"</span>)
gold = parseHex(<span class="hljs-string">"ffff66"</span>)
ggplot(df, aes(x=<span class="hljs-string">"x"</span>, y=<span class="hljs-string">"depth"</span>)) + scale_y_reverse() +
geom_line(color=some(gold)) + theme_void(color=dark) +
ggsave(<span class="hljs-string">"2021/01_depths.png"</span>)</code></pre>
<pre><samp>Dataframe with 2 columns and 2000 rows:
Idx depth x
dtype: int int
0 104 1
1 105 2
2 109 3
3 120 4
4 124 5
5 113 6
6 120 7
7 121 8
8 122 9
9 123 10
10 134 11
11 133 12
12 134 13
13 150 14
14 160 15
15 165 16
16 179 17
17 178 18
18 180 19
19 178 20
INFO: The integer column `x` has been automatically determined to be continuous. To overwrite this behavior add a `+ scale_x/y_discrete()` call to the plotting chain. Choose `x` or `y` depending on which axis this column refers to. Or apply a `factor` to the column name in the `aes` call, i.e. `aes(..., factor("x"), ...)`.
StatusSuccess output of write_to_png
</samp></pre>
<figure>
<img src="../2021/01_depths.png" alt="">
<figcaption></figcaption>
</figure>
<p>Note:</p>
<ul>
<li>we use <code>seqsToDf</code> and a table constructor in order to give a new name to input</li>
<li>we built (using sugar's collect) a dummy x axis in order to use it in the plots</li>
<li>we reverse y scale to give the idea of increasing depth of sea bottom</li>
<li>we use a gold line and same background as that of the page, removing all axis</li>
<li>colors come from <a href="https://github.com/treeform/chroma">chroma</a></li>
</ul>
<p>Interesting also to plot the depth differences
(and its average, which we can expect to be close to 4):</p>
<pre><code class="nim hljs">df[<span class="hljs-string">"diff_depth"</span>] = collect:
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-number">0</span> .. input.<span class="hljs-keyword">high</span>:
<span class="hljs-keyword">if</span> i == <span class="hljs-number">0</span>:
<span class="hljs-number">0</span>
<span class="hljs-keyword">else</span>:
input[i] - input[i-<span class="hljs-number">1</span>]
<span class="hljs-keyword">let</span> mean_diff_depth = mean(df[<span class="hljs-string">"diff_depth"</span>].toTensor(<span class="hljs-built_in">float</span>))
dump mean_diff_depth
<span class="hljs-keyword">echo</span> df
<span class="hljs-keyword">let</span>
green = parseHex(<span class="hljs-string">"009900"</span>)
red = parseHtmlName(<span class="hljs-string">"red"</span>)
<span class="hljs-keyword">let</span>
font_aoc = <span class="hljs-type">Font</span>(
family: <span class="hljs-string">"sans-serif"</span>,
size: <span class="hljs-number">12.0</span>,
bold: <span class="hljs-literal">false</span>,
slant: fsNormal,
color: green, <span class="hljs-comment"># only change with respect to default</span>
alignKind: taCenter
)
theme_aoc = <span class="hljs-type">Theme</span>(
canvasColor: some(dark),
plotBackgroundColor: some(dark),
gridLineColor: some(green),
labelFont: some(font_aoc),
tickLabelFont: some(font_aoc),
<span class="hljs-comment"># hideTicks: some(true) # with this line:</span>
<span class="hljs-comment"># fatal.nim(53Error: unhandled exception: index out of bounds, the container is empty [IndexDefect]</span>
)
ggplot(df, aes(x=<span class="hljs-string">"x"</span>, y=<span class="hljs-string">"diff_depth"</span>)) +
geom_line(color=some(gold)) + theme_aoc +
geom_linerange(aes = aes(y = mean_diff_depth, xMin = <span class="hljs-number">0</span>, xMax = <span class="hljs-number">2000</span>), color=some(red)) +
ggsave(<span class="hljs-string">"2021/01_relative_depth.png"</span>)</code></pre>
<pre><samp>mean_diff_depth = 3.8275
Dataframe with 3 columns and 2000 rows:
Idx depth x diff_depth
dtype: int int int
0 104 1 0
1 105 2 1
2 109 3 4
3 120 4 11
4 124 5 4
5 113 6 -11
6 120 7 7
7 121 8 1
8 122 9 1
9 123 10 1
10 134 11 11
11 133 12 -1
12 134 13 1
13 150 14 16
14 160 15 10
15 165 16 5
16 179 17 14
17 178 18 -1
18 180 19 2
19 178 20 -2
INFO: The integer column `x` has been automatically determined to be continuous. To overwrite this behavior add a `+ scale_x/y_discrete()` call to the plotting chain. Choose `x` or `y` depending on which axis this column refers to. Or apply a `factor` to the column name in the `aes` call, i.e. `aes(..., factor("x"), ...)`.
StatusSuccess output of write_to_png
</samp></pre>
<figure>
<img src="../2021/01_relative_depth.png" alt="">
<figcaption></figcaption>
</figure>
<p>Note:</p>
<ul>
<li>to compute the mean we use <code>toTensor</code> and we convert to float (otherwise the result will be an <code>int</code>)</li>
<li>we create a custom "aoc" theme setting appropriately colors</li>
<li>we are using <code>geom_linerange</code> to plot the horizontal line since <code>geom_hline</code> is not (yet) implemented</li>
</ul>
<h3>highlights from subreddit</h3>
<p>Among the different stuff that is published in advent of code
<a href="https://www.reddit.com/r/adventofcode/">subreddit</a>
I found interesting:</p>
<ul>
<li>a site that allows to <a href="https://aocweb.yulrizka.com/?year=2021&day=1&language=Nim">search all solutions</a>
posted in the solution megathread by programming language (<a href="https://www.reddit.com/r/adventofcode/comments/r6cmn1/aocweb_a_website_that_collects_solutions_from_the/">announcement</a>)</li>
<li>a <a href="https://www.reddit.com/r/adventofcode/comments/r6asn2/2021_day_1_part_1well_its_a_game_turing_complete/">visualization</a> of a solution built with
<a href="https://store.steampowered.com/app/1444480/Turing_Complete/">Turing Complete</a>,
a game coded in Nim</li>
</ul>
</main>
<footer>
<hr>
<div class="nb-box">
<span><span class="nb-small">made with <a href="https://pietroppeter.github.io/nimib/">nimib π³</a></span></span>
<span></span>
<span><button class="nb-small" id="show" onclick="toggleSourceDisplay()">Show Source</button></span>
</div>
</footer>
<section id="source">
<pre><code class="nim hljs"><span class="hljs-keyword">import</span> nimib, animu, nimoji
nbInit(theme=useAdventOfNim)
nbText: <span class="hljs-string">"""## 2021, day 1: [Sonar Sweep](https://adventofcode.com/2021/day/1) β΄οΈπ
Another year of [Advent of Nim](https://forum.nim-lang.org/t/8657) :christmas_tree::crown:!
_This year I would like to try and use cool nim libraries
for visualization_ and similar stuff.
I will most likely be able to keep up only for a few days, but let's see.
But let's get to the first problem.
As usual we have a sequence of integers as input.
What is new this year is that,
[thanks to 1.6](https://nim-lang.org/blog/2021/10/19/version-160-released.html)
we can use `toSeq` with method call syntax!
"""</span>.emojize
nbCode:
<span class="hljs-keyword">let</span> input: <span class="hljs-built_in">seq</span>[<span class="hljs-built_in">int</span>] = <span class="hljs-string">"2021/input01.txt"</span>.lines.toSeq.map(parseInt)
<span class="hljs-keyword">echo</span> input.len
<span class="hljs-keyword">echo</span> input[<span class="hljs-number">0</span> .. <span class="hljs-number">10</span>]
<span class="hljs-keyword">echo</span> input[^<span class="hljs-number">10</span> .. ^<span class="hljs-number">1</span>]
nbText: <span class="hljs-string">"""### Part 1
> As the submarine drops below the surface of the ocean, it automatically performs a sonar sweep of the nearby sea floor. On a small screen, the sonar sweep report (your puzzle input) appears: each line is a measurement of the sea floor depth as the sweep looks further and further away from the submarine.
>
> For example, suppose you had the following report:
"""</span>
nbCode:
<span class="hljs-keyword">let</span> report = <span class="hljs-string">"""
199
200
208
210
200
207
240
269
260
263"""</span>
nbText: <span class="hljs-string">"""
> This report indicates that, scanning outward from the submarine, the sonar sweep found depths of 199, 200, 208, 210, and so on.
>
> The first order of business is to figure out how quickly the depth increases, ...
>
> To do this, count the _number of times a depth measurement increases_ from the previous measurement
>
> ... In this example, there are 7 measurements that are larger than the previous measurement.
The solution for part1 (as expected) is pretty straightforward.
Just make sure you start from index 1:
"""</span>
nbCode:
<span class="hljs-keyword">func</span> countIncrease(s: <span class="hljs-built_in">seq</span>[<span class="hljs-built_in">int</span>]): <span class="hljs-built_in">int</span> =
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-number">1</span> .. s.<span class="hljs-keyword">high</span>:
<span class="hljs-keyword">if</span> s[i] > s[i - <span class="hljs-number">1</span>]:
inc <span class="hljs-literal">result</span>
<span class="hljs-keyword">let</span> testInput = report.splitLines.toSeq.map(parseInt)
doAssert testInput.countIncrease == <span class="hljs-number">7</span>
<span class="hljs-keyword">echo</span> countIncrease(input)
doAssert countIncrease(input) == <span class="hljs-number">1557</span>
gotTheStar
nbText: <span class="hljs-string">"""### Part 2
> Considering every single measurement isn't as useful as you expected: there's just too much noise in the data.
>
> Instead, consider _sums of a three-measurement sliding window_.
>
> ... Your goal now is to count _the number of times the sum of measurements in this sliding window increases_ from the previous sum.
>
> ... In [test] example, there are 5 sums that are larger than the previous sum.
let's create a function that copmutes the window function of a sequence,
then we will apply previous function to the result.
"""</span>
nbCode:
<span class="hljs-keyword">func</span> window(s: <span class="hljs-built_in">seq</span>[<span class="hljs-built_in">int</span>], size=<span class="hljs-number">3</span>): <span class="hljs-built_in">seq</span>[<span class="hljs-built_in">int</span>] =
<span class="hljs-keyword">assert</span> s.len >= size
<span class="hljs-keyword">var</span> sum = s[<span class="hljs-number">0</span> ..< size].sum
<span class="hljs-literal">result</span>.add sum
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> size .. s.<span class="hljs-keyword">high</span>:
sum = sum - s[i - size] + s[i]
<span class="hljs-literal">result</span>.add sum
<span class="hljs-keyword">echo</span> input[<span class="hljs-number">0</span> ..< <span class="hljs-number">10</span>]
<span class="hljs-keyword">echo</span> input[<span class="hljs-number">0</span> ..< <span class="hljs-number">10</span>].window
nbCode:
doAssert testInput.window.countIncrease == <span class="hljs-number">5</span>
<span class="hljs-keyword">echo</span> input.window.countIncrease
gotTheStar
doAssert input.window.countIncrease == <span class="hljs-number">1608</span>
nbText: <span class="hljs-string">"""### Optimizing part 2
As hinted by [narimiran](https://github.com/narimiran) in our nim-aoc discord chat,
there is a simpler way to compute part 2 that also reveals that _the "window" approach
does not really denoise the signal_. Since two successive windows of 3 depths have 2 overlapping
depth, to check if there is an increase we only need to check first and last depth:
"""</span>
nbCode:
<span class="hljs-keyword">func</span> countIncrease2(s: <span class="hljs-built_in">seq</span>[<span class="hljs-built_in">int</span>], window=<span class="hljs-number">3</span>): <span class="hljs-built_in">int</span> =
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-number">0</span> ..< (s.len - window):
<span class="hljs-keyword">if</span> s[i + window] > s[i]:
inc <span class="hljs-literal">result</span>
<span class="hljs-keyword">echo</span> input.countIncrease2
doAssert input.countIncrease2 == <span class="hljs-number">1608</span>
<span class="hljs-comment"># note that countIncrease2 is equivalent to countIncrease(..., window=1)</span>
nbText: <span class="hljs-string">"""### Visualization
I will use the excellent [ggplotnim](https://github.com/Vindaar/ggplotnim)
to plot the depth profile and the dataframe library [datamancer](https://github.com/SciNim/Datamancer)
(implictly imported through ggplotnim) to manage the data.
Thanks to [Vindaar](https://github.com/Vindaar) for help in this section
"""</span>
nbCode:
<span class="hljs-keyword">import</span> ggplotnim
<span class="hljs-keyword">var</span> df = seqsToDf({<span class="hljs-string">"depth"</span>: input}) <span class="hljs-comment"># toDf(input): new column will be named input</span>
df[<span class="hljs-string">"x"</span>] = collect:
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-number">1</span> .. input.len:
i
<span class="hljs-keyword">echo</span> df
<span class="hljs-keyword">let</span>
dark = parseHex(<span class="hljs-string">"202b38"</span>)
gold = parseHex(<span class="hljs-string">"ffff66"</span>)
ggplot(df, aes(x=<span class="hljs-string">"x"</span>, y=<span class="hljs-string">"depth"</span>)) + scale_y_reverse() +
geom_line(color=some(gold)) + theme_void(color=dark) +
ggsave(<span class="hljs-string">"2021/01_depths.png"</span>)
nbImage(<span class="hljs-string">"2021/01_depths.png"</span>)
nbText: <span class="hljs-string">"""
Note:
- we use `seqsToDf` and a table constructor in order to give a new name to input
- we built (using sugar's collect) a dummy x axis in order to use it in the plots
- we reverse y scale to give the idea of increasing depth of sea bottom
- we use a gold line and same background as that of the page, removing all axis
- colors come from [chroma](https://github.com/treeform/chroma)
Interesting also to plot the depth differences
(and its average, which we can expect to be close to 4):
"""</span>
nbCode:
df[<span class="hljs-string">"diff_depth"</span>] = collect:
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-number">0</span> .. input.<span class="hljs-keyword">high</span>:
<span class="hljs-keyword">if</span> i == <span class="hljs-number">0</span>:
<span class="hljs-number">0</span>
<span class="hljs-keyword">else</span>:
input[i] - input[i-<span class="hljs-number">1</span>]
<span class="hljs-keyword">let</span> mean_diff_depth = mean(df[<span class="hljs-string">"diff_depth"</span>].toTensor(<span class="hljs-built_in">float</span>))
dump mean_diff_depth
<span class="hljs-keyword">echo</span> df
<span class="hljs-keyword">let</span>
green = parseHex(<span class="hljs-string">"009900"</span>)
red = parseHtmlName(<span class="hljs-string">"red"</span>)
<span class="hljs-keyword">let</span>
font_aoc = <span class="hljs-type">Font</span>(
family: <span class="hljs-string">"sans-serif"</span>,
size: <span class="hljs-number">12.0</span>,
bold: <span class="hljs-literal">false</span>,
slant: fsNormal,
color: green, <span class="hljs-comment"># only change with respect to default</span>
alignKind: taCenter
)
theme_aoc = <span class="hljs-type">Theme</span>(
canvasColor: some(dark),
plotBackgroundColor: some(dark),
gridLineColor: some(green),
labelFont: some(font_aoc),
tickLabelFont: some(font_aoc),
<span class="hljs-comment"># hideTicks: some(true) # with this line:</span>
<span class="hljs-comment"># fatal.nim(53Error: unhandled exception: index out of bounds, the container is empty [IndexDefect]</span>
)
ggplot(df, aes(x=<span class="hljs-string">"x"</span>, y=<span class="hljs-string">"diff_depth"</span>)) +
geom_line(color=some(gold)) + theme_aoc +
geom_linerange(aes = aes(y = mean_diff_depth, xMin = <span class="hljs-number">0</span>, xMax = <span class="hljs-number">2000</span>), color=some(red)) +
ggsave(<span class="hljs-string">"2021/01_relative_depth.png"</span>)
nbImage(<span class="hljs-string">"2021/01_relative_depth.png"</span>)
nbText: <span class="hljs-string">"""
Note:
* to compute the mean we use `toTensor` and we convert to float (otherwise the result will be an `int`)
* we create a custom "aoc" theme setting appropriately colors
* we are using `geom_linerange` to plot the horizontal line since `geom_hline` is not (yet) implemented
### highlights from subreddit
Among the different stuff that is published in advent of code
[subreddit](https://www.reddit.com/r/adventofcode/)
I found interesting:
- a site that allows to [search all solutions](https://aocweb.yulrizka.com/?year=2021&day=1&language=Nim)
posted in the solution megathread by programming language ([announcement](https://www.reddit.com/r/adventofcode/comments/r6cmn1/aocweb_a_website_that_collects_solutions_from_the/))
- a [visualization](https://www.reddit.com/r/adventofcode/comments/r6asn2/2021_day_1_part_1well_its_a_game_turing_complete/) of a solution built with
[Turing Complete](https://store.steampowered.com/app/1444480/Turing_Complete/),
a game coded in Nim
"""</span>
<span class="hljs-comment">#[
add section of highlights from subreddit
- new theme: adventure time
- site with all solutions
- turing complete solution
- deep water visualization
- ...
]#</span>
nbSave</code></pre>
</section><script>
function toggleSourceDisplay() {
var btn = document.getElementById("show")
var source = document.getElementById("source");
if (btn.innerHTML=="Show Source") {
btn.innerHTML = "Hide Source";
source.style.display = "block";
} else {
btn.innerHTML = "Show Source";
source.style.display = "none";
}
}
</script></body>
</html>