This repository has been archived by the owner on Nov 17, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathfeed.xml
1357 lines (1311 loc) · 296 KB
/
feed.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
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
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="UTF-16"?>
<!--This file generated by build script at ./Build.hs in solutions repository-->
<rss version="2.0">
<channel>
<title>Justin Le's Advent of Code 2018 Reflections</title>
<description>Reflections for my Advent of Code solutions as I try to solve them all in fun ways using Haskell!</description>
<link>https://github.com/mstksg/advent-of-code-2018/blob/master/reflections.md</link>
<copyright>Copyright 2018 Justin Le</copyright>
<language>en-us</language>
<lastBuildDate>Wed, 1 Dec 2021 23:58:55 EST</lastBuildDate>
<managingEditor>[email protected]</managingEditor>
<pubDate>Wed, 1 Dec 2021 23:58:55 EST</pubDate>
<webMaster>[email protected]</webMaster>
<generator>Shake + Template</generator>
<item>
<title>Day 20</title>
<description><h2 id="day-20">Day 20</h2>
<!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day20.md`. If you want to edit this, edit
that file instead!
-->
<p><em><a href="https://adventofcode.com/2018/day/20">Prompt</a></em> / <em><a href="https://github.com/mstksg/advent-of-code-2018/blob/master/src/AOC/Challenge/Day20.hs">Code</a></em> / <em><a href="https://mstksg.github.io/advent-of-code-2018/src/AOC.Challenge.Day20.html">Rendered</a></em></p>
<p>Like Day 4, this one is made pretty simple with parser combinators! :D</p>
<p>Just for clarity, we will tokenize the stream first – but it’s not strictly necessary.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Dir</span> <span class="ot">=</span> <span class="dt">DN</span> <span class="op">|</span> <span class="dt">DE</span> <span class="op">|</span> <span class="dt">DS</span> <span class="op">|</span> <span class="dt">DW</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span> (<span class="dt">Show</span>, <span class="dt">Eq</span>, <span class="dt">Ord</span>)</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">RegTok</span> <span class="ot">=</span> <span class="dt">RTStart</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="dt">RTDir</span> <span class="dt">Dir</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="dt">RTRParen</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="dt">RTOr</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="dt">RTLParen</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="dt">RTEnd</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span> (<span class="dt">Show</span>, <span class="dt">Eq</span>, <span class="dt">Ord</span>)</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="ot">parseToks ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> [<span class="dt">RegTok</span>]</span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>parseToks <span class="ot">=</span> mapMaybe <span class="op">$</span> \<span class="kw">case</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a> <span class="ch">&#39;^&#39;</span> <span class="ot">-&gt;</span> <span class="dt">Just</span> <span class="dt">RTStart</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a> <span class="ch">&#39;N&#39;</span> <span class="ot">-&gt;</span> <span class="dt">Just</span> <span class="op">$</span> <span class="dt">RTDir</span> <span class="dt">DN</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a> <span class="ch">&#39;E&#39;</span> <span class="ot">-&gt;</span> <span class="dt">Just</span> <span class="op">$</span> <span class="dt">RTDir</span> <span class="dt">DE</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a> <span class="ch">&#39;W&#39;</span> <span class="ot">-&gt;</span> <span class="dt">Just</span> <span class="op">$</span> <span class="dt">RTDir</span> <span class="dt">DW</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a> <span class="ch">&#39;S&#39;</span> <span class="ot">-&gt;</span> <span class="dt">Just</span> <span class="op">$</span> <span class="dt">RTDir</span> <span class="dt">DS</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a> <span class="ch">&#39;|&#39;</span> <span class="ot">-&gt;</span> <span class="dt">Just</span> <span class="dt">RTOr</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a> <span class="ch">&#39;(&#39;</span> <span class="ot">-&gt;</span> <span class="dt">Just</span> <span class="dt">RTRParen</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a> <span class="ch">&#39;)&#39;</span> <span class="ot">-&gt;</span> <span class="dt">Just</span> <span class="dt">RTLParen</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a> <span class="ch">&#39;$&#39;</span> <span class="ot">-&gt;</span> <span class="dt">Just</span> <span class="dt">RTEnd</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a> _ <span class="ot">-&gt;</span> <span class="dt">Nothing</span></span></code></pre></div>
<p>Now, to write our parser! We will parse our <code>[RegTok]</code> stream into a set of edges.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Linear</span> (<span class="dt">V2</span>(..))</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Text.Parsec</span> <span class="kw">as</span> <span class="dt">P</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="co">-- V2 Int = (Int, Int), essentially</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Point</span> <span class="ot">=</span> <span class="dt">V2</span> <span class="dt">Int</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Edge</span> <span class="ot">=</span> <span class="dt">E</span> <span class="dt">Point</span> <span class="dt">Point</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span> (<span class="dt">Show</span>, <span class="dt">Eq</span>, <span class="dt">Ord</span>)</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a><span class="co">-- | Make an edge. Normalizes so we can compare for uniqueness.</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a><span class="ot">mkEdge ::</span> <span class="dt">Point</span> <span class="ot">-&gt;</span> <span class="dt">Point</span> <span class="ot">-&gt;</span> <span class="dt">Edge</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>mkEdge x y</span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> x <span class="op">&lt;=</span> y <span class="ot">=</span> <span class="dt">E</span> x y</span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="fu">otherwise</span> <span class="ot">=</span> <span class="dt">E</span> y x</span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a><span class="co">-- | Parse a stream of `RegTok`. We have a State of the &quot;current point&quot;.</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Parser</span> <span class="ot">=</span> <span class="dt">P.Parsec</span> [<span class="dt">RegTok</span>] <span class="dt">Point</span></span></code></pre></div>
<p>We either have a “normal step”, or a “branching step”. The entire way, we accumulate a set of all edges.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">tok ::</span> <span class="dt">RegTok</span> <span class="ot">-&gt;</span> <span class="dt">Parser</span> ()</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>tok t <span class="ot">=</span> P.try <span class="op">$</span> guard <span class="op">.</span> (<span class="op">==</span> t) <span class="op">=&lt;&lt;</span> P.anyToken</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="co">-- | `anySteps` is many normal steps or branch steps. Each of these gives an</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="co">-- edge, so we union all of their edges together.</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="ot">anySteps ::</span> <span class="dt">Parser</span> (<span class="dt">Set</span> <span class="dt">Edge</span>)</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>anySteps <span class="ot">=</span> <span class="fu">fmap</span> S.unions <span class="op">.</span> P.many <span class="op">$</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a> P.try normalStep <span class="op">P.&lt;|&gt;</span> branchStep</span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a><span class="co">-- | `normalStep` is a normal step without any branching. It is an `RTDir`</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a><span class="co">-- token, followed by `anySteps`. We add the newly discovered edge to the</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a><span class="co">-- edges in `anySteps`.</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a><span class="ot">normalStep ::</span> <span class="dt">Parser</span> (<span class="dt">Set</span> <span class="dt">Edge</span>)</span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>normalStep <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a> currPos <span class="ot">&lt;-</span> P.getState</span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a> <span class="dt">RTDir</span> d <span class="ot">&lt;-</span> P.anyToken</span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> newPos <span class="ot">=</span> currPos <span class="op">+</span> <span class="kw">case</span> d <span class="kw">of</span></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a> <span class="dt">DN</span> <span class="ot">-&gt;</span> <span class="dt">V2</span> <span class="dv">0</span> (<span class="op">-</span><span class="dv">1</span>)</span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a> <span class="dt">DE</span> <span class="ot">-&gt;</span> <span class="dt">V2</span> <span class="dv">1</span> <span class="dv">0</span></span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true" tabindex="-1"></a> <span class="dt">DS</span> <span class="ot">-&gt;</span> <span class="dt">V2</span> <span class="dv">0</span> <span class="dv">1</span></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true" tabindex="-1"></a> <span class="dt">DW</span> <span class="ot">-&gt;</span> <span class="dt">V2</span> (<span class="op">-</span><span class="dv">1</span>) <span class="dv">0</span></span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true" tabindex="-1"></a> P.setState newPos</span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true" tabindex="-1"></a> S.insert (mkEdge currPos newPos) <span class="op">&lt;$&gt;</span> anySteps</span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true" tabindex="-1"></a><span class="co">-- | `branchStep` is many `anySteps`, each separated by an `RTOr` token. It is</span></span>
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true" tabindex="-1"></a><span class="co">-- located between `RTRParen` and `RTLParen`.</span></span>
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true" tabindex="-1"></a><span class="ot">branchStep ::</span> <span class="dt">Parser</span> (<span class="dt">Set</span> <span class="dt">Edge</span>)</span>
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true" tabindex="-1"></a>branchStep <span class="ot">=</span> (tok <span class="dt">RTRParen</span> <span class="ot">`P.between`</span> tok <span class="dt">RTLParen</span>) <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb3-29"><a href="#cb3-29" aria-hidden="true" tabindex="-1"></a> initPos <span class="ot">&lt;-</span> P.getState</span>
<span id="cb3-30"><a href="#cb3-30" aria-hidden="true" tabindex="-1"></a> <span class="fu">fmap</span> S.unions <span class="op">.</span> (<span class="ot">`P.sepBy`</span> tok <span class="dt">RTOr</span>) <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb3-31"><a href="#cb3-31" aria-hidden="true" tabindex="-1"></a> P.setState initPos</span>
<span id="cb3-32"><a href="#cb3-32" aria-hidden="true" tabindex="-1"></a> anySteps</span></code></pre></div>
<p>Our final regexp parser is just <code>anySteps</code> seperated by the start and end tokens:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ot">buildEdges ::</span> <span class="dt">Parser</span> (<span class="dt">Set</span> <span class="dt">Edge</span>)</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>buildEdges <span class="ot">=</span> (tok <span class="dt">RTStart</span> <span class="ot">`P.between`</span> tok <span class="dt">RTEnd</span>) anySteps</span></code></pre></div>
<p>Now that we have successfully parsed the “regexp” into a set of edges, we need to follow all of the edges into all of the rooms. We can do this using recursive descent.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ot">neighbs ::</span> <span class="dt">Point</span> <span class="ot">-&gt;</span> [<span class="dt">Point</span>]</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>neighbs p <span class="ot">=</span> (p <span class="op">+</span>) <span class="op">&lt;$&gt;</span> [ <span class="dt">V2</span> <span class="dv">0</span> (<span class="op">-</span><span class="dv">1</span>), <span class="dt">V2</span> <span class="dv">1</span> <span class="dv">0</span>, <span class="dt">V2</span> <span class="dv">0</span> <span class="dv">1</span>, <span class="dt">V2</span> (<span class="op">-</span><span class="dv">1</span>) <span class="dv">0</span> ]</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="ot">roomDistances ::</span> <span class="dt">Set</span> <span class="dt">Edge</span> <span class="ot">-&gt;</span> [<span class="dt">Int</span>]</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>roomDistances es <span class="ot">=</span> go <span class="dv">0</span> S.empty (<span class="dt">V2</span> <span class="dv">0</span> <span class="dv">0</span>)</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a><span class="ot"> go ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Set</span> <span class="dt">Point</span> <span class="ot">-&gt;</span> <span class="dt">Point</span> <span class="ot">-&gt;</span> [<span class="dt">Int</span>]</span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a> go n seen p <span class="ot">=</span> (n <span class="op">:</span>) <span class="op">$</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a> <span class="fu">concatMap</span> (go (n <span class="op">+</span> <span class="dv">1</span>) (S.insert p seen)) allNeighbs</span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a> allNeighbs <span class="ot">=</span> <span class="fu">filter</span> ((<span class="ot">`S.member`</span> es) <span class="op">.</span> mkEdge p)</span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> <span class="fu">filter</span> (<span class="ot">`S.notMember`</span> seen)</span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a> <span class="op">$</span> neighbs p</span></code></pre></div>
<p>We have to make sure to keep track of the “already seen” rooms. On my first attempt, I forgot to do this!</p>
<p>Anyway, here’s Part 1 and Part 2:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ot">day20a ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>day20a inp <span class="ot">=</span> <span class="fu">maximum</span> (roomDistances edges)</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a> <span class="dt">Right</span> edges <span class="ot">=</span> P.runParser buildEdges (<span class="dt">V2</span> <span class="dv">0</span> <span class="dv">0</span>) <span class="st">&quot;&quot;</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a> (parseToks inp)</span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a><span class="ot">day20b ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>day20b inp <span class="ot">=</span> <span class="fu">length</span> <span class="op">.</span> <span class="fu">filter</span> (<span class="op">&gt;=</span> <span class="dv">1000</span>) <span class="op">$</span> roomDistances edges</span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a> <span class="dt">Right</span> edges <span class="ot">=</span> P.runParser buildEdges (<span class="dt">V2</span> <span class="dv">0</span> <span class="dv">0</span>) <span class="st">&quot;&quot;</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a> (parseToks inp)</span></code></pre></div>
<h3 id="day-20-benchmarks">Day 20 Benchmarks</h3>
<pre><code>&gt;&gt; Day 20a
benchmarking...
time 48.76 ms (47.74 ms .. 50.18 ms)
0.996 R² (0.989 R² .. 0.999 R²)
mean 48.25 ms (47.39 ms .. 49.76 ms)
std dev 2.059 ms (1.481 ms .. 3.110 ms)
variance introduced by outliers: 14% (moderately inflated)
&gt;&gt; Day 20b
benchmarking...
time 504.4 ms (450.3 ms .. 538.3 ms)
0.999 R² (0.996 R² .. 1.000 R²)
mean 470.3 ms (455.0 ms .. 485.7 ms)
std dev 18.07 ms (14.42 ms .. 20.91 ms)
variance introduced by outliers: 19% (moderately inflated)</code></pre>
</description>
<link>https://github.com/mstksg/advent-of-code-2018/blob/master/reflections.md#day-20</link>
<pubDate>Thu, 20 Dec 2018 01:00:00 EST</pubDate>
</item>
<item>
<title>Day 16</title>
<description><h2 id="day-16">Day 16</h2>
<!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day16.md`. If you want to edit this, edit
that file instead!
-->
<p><em><a href="https://adventofcode.com/2018/day/16">Prompt</a></em> / <em><a href="https://github.com/mstksg/advent-of-code-2018/blob/master/src/AOC/Challenge/Day16.hs">Code</a></em> / <em><a href="https://mstksg.github.io/advent-of-code-2018/src/AOC.Challenge.Day16.html">Rendered</a></em></p>
<p>Today was fun because I got to re-use some techniques I discussed in a blog post I’ve written in the past: <a href="https://blog.jle.im/entry/unique-sample-drawing-searches-with-list-and-statet.html">Send More Money: List and StateT</a>. I talk about using <code>StateT</code> over <code>[]</code> to do implement prolog-inspired constraint satisfaction searches while taking advantage of laziness.</p>
<p>First of all, our types. I’ll be using the <em><a href="https://hackage.haskell.org/package/vector-sized">vector-sized</a></em> library with <em><a href="https://hackage.haskell.org/package/finite-typelits">finite-typelits</a></em> to help us do safe indexing. A <code>Vector n a</code> is a vector of <code>n</code> <code>a</code>s, and a <code>Finite n</code> is a legal index into such a vector. For example, a <code>Vector 4 Int</code> is a vector of 4 <code>Int</code>s, and <code>Finite 4</code> is 0, 1, 2, or 3.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Vector.Sized</span> (<span class="dt">Vector</span>)</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Finite</span> (<span class="dt">Finite</span>)</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Reg</span> <span class="ot">=</span> <span class="dt">Vector</span> <span class="dv">4</span> <span class="dt">Int</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Instr</span> a <span class="ot">=</span> <span class="dt">I</span> {<span class="ot"> _iOp ::</span> a</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> _iInA ::</span> <span class="dt">Finite</span> <span class="dv">4</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> _iInB ::</span> <span class="dt">Finite</span> <span class="dv">4</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> _iOut ::</span> <span class="dt">Finite</span> <span class="dv">4</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a> }</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span> (<span class="dt">Show</span>, <span class="dt">Functor</span>)</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Trial</span> <span class="ot">=</span> <span class="dt">T</span> {<span class="ot"> _tBefore ::</span> <span class="dt">Reg</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> _tInstr ::</span> <span class="dt">Instr</span> (<span class="dt">Finite</span> <span class="dv">16</span>)</span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> _tAfter ::</span> <span class="dt">Reg</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a> }</span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span> <span class="dt">Show</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">OpCode</span> <span class="ot">=</span> <span class="dt">OAddR</span> <span class="op">|</span> <span class="dt">OAddI</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="dt">OMulR</span> <span class="op">|</span> <span class="dt">OMulI</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="dt">OBanR</span> <span class="op">|</span> <span class="dt">OBanI</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="dt">OBorR</span> <span class="op">|</span> <span class="dt">OBorI</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="dt">OSetR</span> <span class="op">|</span> <span class="dt">OSetI</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="dt">OGtIR</span> <span class="op">|</span> <span class="dt">OGtRI</span> <span class="op">|</span> <span class="dt">OGtRR</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="dt">OEqIR</span> <span class="op">|</span> <span class="dt">OEqRI</span> <span class="op">|</span> <span class="dt">OEqRR</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span> (<span class="dt">Show</span>, <span class="dt">Eq</span>, <span class="dt">Ord</span>, <span class="dt">Enum</span>, <span class="dt">Bounded</span>)</span></code></pre></div>
<p>We can leave <code>Instr</code> parameterized over the opcode type so that we can use it with <code>Finite 16</code> initially, and <code>OpCode</code> later.</p>
<p>We do need to implement the functionality of each op, which we can do by pattern matching on an <code>OpCode</code>. We use some lens functionality to simplify some of the editing of indices, but we could also just manually modify indices.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">runOp ::</span> <span class="dt">Instr</span> <span class="dt">OpCode</span> <span class="ot">-&gt;</span> <span class="dt">Reg</span> <span class="ot">-&gt;</span> <span class="dt">Reg</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>runOp <span class="dt">I</span>{<span class="op">..</span>} <span class="ot">=</span> <span class="kw">case</span> _iOp <span class="kw">of</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a> <span class="dt">OAddR</span> <span class="ot">-&gt;</span> \r <span class="ot">-&gt;</span> r <span class="op">&amp;</span> V.ix _iOut <span class="op">.~</span> r <span class="op">^.</span> V.ix _iInA <span class="op">+</span> r <span class="op">^.</span> V.ix _iInB</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a> <span class="dt">OAddI</span> <span class="ot">-&gt;</span> \r <span class="ot">-&gt;</span> r <span class="op">&amp;</span> V.ix _iOut <span class="op">.~</span> r <span class="op">^.</span> V.ix _iInA <span class="op">+</span> <span class="fu">fromIntegral</span> _iInB</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a> <span class="dt">OMulR</span> <span class="ot">-&gt;</span> \r <span class="ot">-&gt;</span> r <span class="op">&amp;</span> V.ix _iOut <span class="op">.~</span> r <span class="op">^.</span> V.ix _iInA <span class="op">*</span> r <span class="op">^.</span> V.ix _iInB</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a> <span class="dt">OMulI</span> <span class="ot">-&gt;</span> \r <span class="ot">-&gt;</span> r <span class="op">&amp;</span> V.ix _iOut <span class="op">.~</span> r <span class="op">^.</span> V.ix _iInA <span class="op">*</span> <span class="fu">fromIntegral</span> _iInB</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a> <span class="dt">OBanR</span> <span class="ot">-&gt;</span> \r <span class="ot">-&gt;</span> r <span class="op">&amp;</span> V.ix _iOut <span class="op">.~</span> r <span class="op">^.</span> V.ix _iInA <span class="op">.&amp;.</span> r <span class="op">^.</span> V.ix _iInB</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a> <span class="dt">OBanI</span> <span class="ot">-&gt;</span> \r <span class="ot">-&gt;</span> r <span class="op">&amp;</span> V.ix _iOut <span class="op">.~</span> r <span class="op">^.</span> V.ix _iInA <span class="op">.&amp;.</span> <span class="fu">fromIntegral</span> _iInB</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a> <span class="dt">OBorR</span> <span class="ot">-&gt;</span> \r <span class="ot">-&gt;</span> r <span class="op">&amp;</span> V.ix _iOut <span class="op">.~</span> r <span class="op">^.</span> V.ix _iInA <span class="op">.|.</span> r <span class="op">^.</span> V.ix _iInB</span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a> <span class="dt">OBorI</span> <span class="ot">-&gt;</span> \r <span class="ot">-&gt;</span> r <span class="op">&amp;</span> V.ix _iOut <span class="op">.~</span> r <span class="op">^.</span> V.ix _iInA <span class="op">.|.</span> <span class="fu">fromIntegral</span> _iInB</span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a> <span class="dt">OSetR</span> <span class="ot">-&gt;</span> \r <span class="ot">-&gt;</span> r <span class="op">&amp;</span> V.ix _iOut <span class="op">.~</span> r <span class="op">^.</span> V.ix _iInA</span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a> <span class="dt">OSetI</span> <span class="ot">-&gt;</span> \r <span class="ot">-&gt;</span> r <span class="op">&amp;</span> V.ix _iOut <span class="op">.~</span> <span class="fu">fromIntegral</span> _iInA</span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a> <span class="dt">OGtIR</span> <span class="ot">-&gt;</span> \r <span class="ot">-&gt;</span> r <span class="op">&amp;</span> V.ix _iOut <span class="op">.</span> enum <span class="op">.~</span> (<span class="fu">fromIntegral</span> _iInA <span class="op">&gt;</span> r <span class="op">^.</span> V.ix _iInB )</span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a> <span class="dt">OGtRI</span> <span class="ot">-&gt;</span> \r <span class="ot">-&gt;</span> r <span class="op">&amp;</span> V.ix _iOut <span class="op">.</span> enum <span class="op">.~</span> (r <span class="op">^.</span> V.ix _iInA <span class="op">&gt;</span> <span class="fu">fromIntegral</span> _iInB)</span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a> <span class="dt">OGtRR</span> <span class="ot">-&gt;</span> \r <span class="ot">-&gt;</span> r <span class="op">&amp;</span> V.ix _iOut <span class="op">.</span> enum <span class="op">.~</span> (r <span class="op">^.</span> V.ix _iInA <span class="op">&gt;</span> r <span class="op">^.</span> V.ix _iInB )</span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a> <span class="dt">OEqIR</span> <span class="ot">-&gt;</span> \r <span class="ot">-&gt;</span> r <span class="op">&amp;</span> V.ix _iOut <span class="op">.</span> enum <span class="op">.~</span> (<span class="fu">fromIntegral</span> _iInA <span class="op">==</span> r <span class="op">^.</span> V.ix _iInB )</span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a> <span class="dt">OEqRI</span> <span class="ot">-&gt;</span> \r <span class="ot">-&gt;</span> r <span class="op">&amp;</span> V.ix _iOut <span class="op">.</span> enum <span class="op">.~</span> (r <span class="op">^.</span> V.ix _iInA <span class="op">==</span> <span class="fu">fromIntegral</span> _iInB)</span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a> <span class="dt">OEqRR</span> <span class="ot">-&gt;</span> \r <span class="ot">-&gt;</span> r <span class="op">&amp;</span> V.ix _iOut <span class="op">.</span> enum <span class="op">.~</span> (r <span class="op">^.</span> V.ix _iInA <span class="op">==</span> r <span class="op">^.</span> V.ix _iInB )</span></code></pre></div>
<p>Now, from a <code>Trial</code>, we can get a set of <code>OpCode</code>s that are plausible candidates if the output matches the expected output for a given <code>OpCode</code>, for the given input.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">plausible ::</span> <span class="dt">Trial</span> <span class="ot">-&gt;</span> <span class="dt">Set</span> <span class="dt">OpCode</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>plausible <span class="dt">T</span>{<span class="op">..</span>} <span class="ot">=</span> S.fromList (<span class="fu">filter</span> tryTrial [<span class="dt">OAddR</span> <span class="op">..</span>])</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="ot"> tryTrial ::</span> <span class="dt">OpCode</span> <span class="ot">-&gt;</span> <span class="dt">Bool</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a> tryTrial o <span class="ot">=</span> runOp (_tInstr { _iOp <span class="ot">=</span> o }) _tBefore <span class="op">==</span> _tAfter</span></code></pre></div>
<p>Part 1 is, then, just counting the trials with three or more plausible candidates:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ot">day16a ::</span> [<span class="dt">Trial</span>] <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>day16a <span class="ot">=</span> <span class="fu">length</span> <span class="op">.</span> <span class="fu">filter</span> ((<span class="op">&gt;=</span> <span class="dv">3</span>) <span class="op">.</span> S.size <span class="op">.</span> plausible)</span></code></pre></div>
<p>Part 2 is where we can implement our constraint satisfaction search. Following <a href="https://blog.jle.im/entry/unique-sample-drawing-searches-with-list-and-statet.html">this blog post</a>, we can write a search using <code>StateT (Set OpCode) []</code>. Our state will be the <code>OpCode</code>s that we have already used. We fill up a vector step-by-step, by picking only <code>OpCode</code>s that have not been used yet:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ot">fillIn ::</span> <span class="dt">Set</span> <span class="dt">OpCode</span> <span class="ot">-&gt;</span> <span class="dt">StateT</span> (<span class="dt">Set</span> <span class="dt">OpCode</span>) [] <span class="dt">OpCode</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>fillIn candidates <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a> unseen <span class="ot">&lt;-</span> gets (candidates <span class="ot">`S.difference`</span>) <span class="co">-- filter only unseen candidates</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a> pick <span class="ot">&lt;-</span> lift <span class="op">$</span> toList unseen <span class="co">-- branch on all unseen candidates</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a> modify <span class="op">$</span> S.insert pick <span class="co">-- in this branch, &#39;pick&#39; is seen</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a> <span class="fu">pure</span> pick <span class="co">-- return our pick for the branch</span></span></code></pre></div>
<p>Now, if we have a map of <code>Finite 16</code> (op code numbers) to their candidates (a <code>Map (Finite 16) (Set OpCode)</code>), we can populate all legal configurations. We’ll use <code>Vector 16 OpCode</code> to represent our configuration: <code>0</code> will represent the first item, <code>1</code> will represent the second, etc. We can use <code>V.generate :: (Finite n -&gt; m a) -&gt; m (Vector n a)</code>, and run our <code>fillIn</code> action for every <code>Finite n</code>.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>fillVector</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="ot"> ::</span> <span class="dt">Map</span> (<span class="dt">Finite</span> <span class="dv">16</span>) (<span class="dt">Set</span> <span class="dt">OpCode</span>)</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a> <span class="ot">-&gt;</span> <span class="dt">StateT</span> (<span class="dt">Set</span> <span class="dt">OpCode</span>) [] (<span class="dt">Vector</span> <span class="dv">16</span> <span class="dt">OpCode</span>)</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>fillVector candmap <span class="ot">=</span> V.generateM <span class="op">$</span> \i <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a> <span class="dt">Just</span> cands <span class="ot">&lt;-</span> <span class="fu">pure</span> <span class="op">$</span> M.lookup i candmap</span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a> fillIn cands</span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>fromClues</span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a><span class="ot"> ::</span> <span class="dt">Map</span> (<span class="dt">Finite</span> <span class="dv">16</span>) (<span class="dt">Set</span> <span class="dt">OpCode</span>)</span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a> <span class="ot">-&gt;</span> <span class="dt">Maybe</span> (<span class="dt">Vector</span> <span class="dv">16</span> <span class="dt">OpCode</span>)</span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>fromClues m <span class="ot">=</span> listToMaybe <span class="op">$</span> evalStateT (fillVector m) S.empty</span></code></pre></div>
<p>If this part is confusing, the <a href="https://blog.jle.im/entry/unique-sample-drawing-searches-with-list-and-statet.html">blog post</a> explains how <code>StateT</code> and <code>[]</code>, together, give you this short-circuting search behavior!</p>
<p>So our Part 2 is using <code>fromClues</code> from all of the candidates (making sure to do a set intersection if we get more than one clue for an opcode number), and a <code>foldl'</code> over our instruction list:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ot">day16b ::</span> [<span class="dt">Trial</span>] <span class="ot">-&gt;</span> [<span class="dt">Instr</span> (<span class="dt">Finite</span> <span class="dv">16</span>)] <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>day16b ts <span class="ot">=</span> V.head <span class="op">.</span> foldl&#39; step (V.replicate <span class="dv">0</span>)</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a> candmap <span class="ot">=</span> M.fromListWith S.intersection</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a> <span class="op">$</span> [ (_iOp (_tInstr t), plausible t)</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> t <span class="ot">&lt;-</span> ts</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a> ]</span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a> <span class="dt">Just</span> opMap <span class="ot">=</span> fromClues candmap</span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a> step r i <span class="ot">=</span> runOp i&#39; r</span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a> i&#39; <span class="ot">=</span> (opMap <span class="ot">`V.index`</span>) <span class="op">&lt;$&gt;</span> i</span></code></pre></div>
<h3 id="day-16-benchmarks">Day 16 Benchmarks</h3>
<pre><code>&gt;&gt; Day 16a
benchmarking...
time 11.21 ms (10.00 ms .. 12.44 ms)
0.954 R² (0.919 R² .. 0.983 R²)
mean 11.38 ms (10.93 ms .. 12.14 ms)
std dev 1.474 ms (810.9 μs .. 2.543 ms)
variance introduced by outliers: 66% (severely inflated)
&gt;&gt; Day 16b
benchmarking...
time 354.1 ms (249.7 ms .. 408.0 ms)
0.989 R² (0.976 R² .. 1.000 R²)
mean 370.6 ms (354.2 ms .. 384.5 ms)
std dev 17.15 ms (14.76 ms .. 19.76 ms)
variance introduced by outliers: 19% (moderately inflated)</code></pre>
</description>
<link>https://github.com/mstksg/advent-of-code-2018/blob/master/reflections.md#day-16</link>
<pubDate>Sun, 16 Dec 2018 01:00:00 EST</pubDate>
</item>
<item>
<title>Day 15</title>
<description><h2 id="day-15">Day 15</h2>
<!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day15.md`. If you want to edit this, edit
that file instead!
-->
<p><em><a href="https://adventofcode.com/2018/day/15">Prompt</a></em> / <em><a href="https://github.com/mstksg/advent-of-code-2018/blob/master/src/AOC/Challenge/Day15.hs">Code</a></em> / <em><a href="https://mstksg.github.io/advent-of-code-2018/src/AOC.Challenge.Day15.html">Rendered</a></em></p>
<p>This one feels complex at first (a generate-check-generate-check loop)…if you take a generate-check loop, you also have to be sure to make sure you check the case of 1 or 2 added digits.</p>
<p>However, it becomes much simpler if you separate the act of generation and checking as two different things. Luckily, with Haskell, this is fairly easy with lazily linked lists.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">chocolatePractice ::</span> [<span class="dt">Int</span>]</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>chocolatePractice <span class="ot">=</span> <span class="dv">3</span> <span class="op">:</span> <span class="dv">7</span> <span class="op">:</span> go <span class="dv">0</span> <span class="dv">1</span> (Seq.fromList [<span class="dv">3</span>,<span class="dv">7</span>])</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a> go <span class="op">!</span>p1 <span class="op">!</span>p2 <span class="op">!</span>tp <span class="ot">=</span> newDigits <span class="op">++</span> go p1&#39; p2&#39; tp&#39;</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a> sc1 <span class="ot">=</span> tp <span class="ot">`Seq.index`</span> p1</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a> sc2 <span class="ot">=</span> tp <span class="ot">`Seq.index`</span> p2</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a> newDigits <span class="ot">=</span> digitize <span class="op">$</span> sc1 <span class="op">+</span> sc2</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a> tp&#39; <span class="ot">=</span> tp <span class="op">&lt;&gt;</span> Seq.fromList newDigits</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a> p1&#39; <span class="ot">=</span> (p1 <span class="op">+</span> sc1 <span class="op">+</span> <span class="dv">1</span>) <span class="ot">`mod`</span> <span class="fu">length</span> tp&#39;</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a> p2&#39; <span class="ot">=</span> (p2 <span class="op">+</span> sc2 <span class="op">+</span> <span class="dv">1</span>) <span class="ot">`mod`</span> <span class="fu">length</span> tp&#39;</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="ot">digitize ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> [<span class="dt">Int</span>]</span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>digitize ((<span class="ot">`divMod`</span> <span class="dv">10</span>)<span class="ot">-&gt;</span>(x,y))</span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> x <span class="op">==</span> <span class="dv">0</span> <span class="ot">=</span> [y]</span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="fu">otherwise</span> <span class="ot">=</span> [x,y]</span></code></pre></div>
<p>We use <code>go</code> to lazily generate new items as they are demanded. Once the user consumes all of the <code>newDigits</code> asks for more, <code>go</code> will be asked to generate new digits. The important thing is that this is demand-driven.</p>
<p>We keep track of the current tape using <code>Seq</code> from <em>Data.Sequence</em> for its O(1) appends and O(log) indexing – the two things we do the most. We could also get away with pre-allocation with vectors for amortized O(1) suffix appends and O(1) indexing, as well.</p>
<p>Note that <code>chocolatePractice</code> is effectively the same for every per-user input data. It’s just a (lazily generated) list of all of the chocolate practice digits.</p>
<p>Part 1 then is just a <code>drop</code> then a <code>take</code>:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">day14a ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> [<span class="dt">Int</span>]</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>day14a n <span class="ot">=</span> <span class="fu">take</span> <span class="dv">10</span> (<span class="fu">drop</span> n chocolatePractice)</span></code></pre></div>
<p>Part 2, we can use <code>isPrefixOf</code> from <em>Data.List</em> and check every <code>tails</code> until we get one that <em>does</em> have our digit list as a prefix:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">substrLoc ::</span> [<span class="dt">Int</span>] <span class="ot">-&gt;</span> [<span class="dt">Int</span>] <span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">Int</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>substrLoc xs <span class="ot">=</span> <span class="fu">length</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> <span class="fu">takeWhile</span> (<span class="fu">not</span> <span class="op">.</span> (xs <span class="ot">`isPrefixOf`</span>))</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> tails</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="ot">day14b ::</span> [<span class="dt">Int</span>] <span class="ot">-&gt;</span> [<span class="dt">Int</span>]</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>day14b xs <span class="ot">=</span> xs <span class="ot">`substrLoc`</span> cholcatePractice</span></code></pre></div>
<p>Note that <code>chocolatePractice</code> is essentially just a futumorphism, so this whole thing can be stated in terms of a chronomorphism. I don’t know if there would be any advantage in doing so. But it’s interesting to me that I solved Day 13 using a hylomorphism, and now Day 14 using what is essentially a chronomorphism … so maybe recursion-schemes is the killer app for Advent of Code? :)</p>
<p>A note on benchmarks – it’s very difficult to benchmark Day 14, because I couldn’t get ghc to stop memoizing <code>chocolatePractice</code>. This means my repeated benchmarks kept on re-using the stored list.</p>
<p>However, using <code>time</code>, I timed Part 1 to about 180ms, and Part 2 to 10s.</p>
<h3 id="day-15-benchmarks">Day 15 Benchmarks</h3>
<pre><code>&gt;&gt; Day 15a
benchmarking...
time 4.062 s (3.493 s .. 4.752 s)
0.997 R² (0.988 R² .. 1.000 R²)
mean 4.567 s (4.331 s .. 4.916 s)
std dev 363.0 ms (67.59 ms .. 477.4 ms)
variance introduced by outliers: 21% (moderately inflated)
&gt;&gt; Day 15b
benchmarking...
time 25.70 s (22.49 s .. 27.53 s)
0.998 R² (0.996 R² .. NaN R²)
mean 24.17 s (23.50 s .. 24.86 s)
std dev 821.5 ms (417.6 ms .. 1.132 s)
variance introduced by outliers: 19% (moderately inflated)</code></pre>
</description>
<link>https://github.com/mstksg/advent-of-code-2018/blob/master/reflections.md#day-15</link>
<pubDate>Sat, 15 Dec 2018 01:00:00 EST</pubDate>
</item>
<item>
<title>Day 13</title>
<description><h2 id="day-13">Day 13</h2>
<!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day13.md`. If you want to edit this, edit
that file instead!
-->
<p><em><a href="https://adventofcode.com/2018/day/13">Prompt</a></em> / <em><a href="https://github.com/mstksg/advent-of-code-2018/blob/master/src/AOC/Challenge/Day13.hs">Code</a></em> / <em><a href="https://mstksg.github.io/advent-of-code-2018/src/AOC.Challenge.Day13.html">Rendered</a></em></p>
<p>Day 13 is fun because it can be stated in terms of a <em><a href="https://en.wikipedia.org/wiki/Hylomorphism_(computer_science)">hylomorphism</a></em>!</p>
<p>First, our data types:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Point</span> <span class="ot">=</span> <span class="dt">V2</span> <span class="dt">Int</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Turn</span> <span class="ot">=</span> <span class="dt">TurnNW</span> <span class="co">-- ^ a forward-slash mirror @/@</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="dt">TurnNE</span> <span class="co">-- ^ a backwards-slash mirror @\\@</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="dt">TurnInter</span> <span class="co">-- ^ a four-way intersection</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span> (<span class="dt">Eq</span>, <span class="dt">Show</span>, <span class="dt">Ord</span>)</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Dir</span> <span class="ot">=</span> <span class="dt">DN</span> <span class="op">|</span> <span class="dt">DE</span> <span class="op">|</span> <span class="dt">DS</span> <span class="op">|</span> <span class="dt">DW</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span> (<span class="dt">Eq</span>, <span class="dt">Show</span>, <span class="dt">Ord</span>, <span class="dt">Enum</span>, <span class="dt">Bounded</span>)</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Cart</span> <span class="ot">=</span> <span class="dt">C</span> {<span class="ot"> _cDir ::</span> <span class="dt">Dir</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a> ,<span class="ot"> _cTurns ::</span> <span class="dt">Int</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a> }</span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span> (<span class="dt">Eq</span>, <span class="dt">Show</span>)</span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>makeLenses &#39;<span class="dt">&#39;Cart</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">ScanPoint</span> <span class="ot">=</span> <span class="dt">SP</span> {<span class="ot"> _getSP ::</span> <span class="dt">Point</span> }</span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span> (<span class="dt">Eq</span>, <span class="dt">Show</span>, <span class="dt">Num</span>)</span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Ord</span> <span class="dt">ScanPoint</span> <span class="kw">where</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a> <span class="fu">compare</span> <span class="ot">=</span> comparing (view _y <span class="op">.</span> _getSP)</span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a> <span class="op">&lt;&gt;</span> comparing (view _x <span class="op">.</span> _getSP)</span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">World</span> <span class="ot">=</span> <span class="dt">Map</span> <span class="dt">Point</span> <span class="dt">Turn</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Carts</span> <span class="ot">=</span> <span class="dt">Map</span> <span class="dt">ScanPoint</span> <span class="dt">Cart</span></span></code></pre></div>
<p>We will be using <code>Map ScanPoint Cart</code> as our priority queue; <code>ScanPoint</code> newtype-wraps a <code>Point</code> in a way that its <code>Ord</code> instance will give us the lowest <code>y</code> first, <em>then</em> the lowest <code>x</code> to break ties.</p>
<p>Note that we don’t ever have to store any of the “track” positions, <code>|</code> or <code>-</code>. That’s because they don’t affect the carts in any way.</p>
<p>Next, we can implement the actual logic of moving a single <code>Cart</code>:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">stepCart ::</span> <span class="dt">World</span> <span class="ot">-&gt;</span> <span class="dt">ScanPoint</span> <span class="ot">-&gt;</span> <span class="dt">Cart</span> <span class="ot">-&gt;</span> (<span class="dt">ScanPoint</span>, <span class="dt">Cart</span>)</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>stepCart w (<span class="dt">SP</span> p) c <span class="ot">=</span> (<span class="dt">SP</span> p&#39;, <span class="fu">maybe</span> <span class="fu">id</span> turner (M.lookup p&#39; w) c)</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a> p&#39; <span class="ot">=</span> p <span class="op">+</span> <span class="kw">case</span> c <span class="op">^.</span> cDir <span class="kw">of</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a> <span class="dt">DN</span> <span class="ot">-&gt;</span> <span class="dt">V2</span> <span class="dv">0</span> (<span class="op">-</span><span class="dv">1</span>)</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a> <span class="dt">DE</span> <span class="ot">-&gt;</span> <span class="dt">V2</span> <span class="dv">1</span> <span class="dv">0</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a> <span class="dt">DS</span> <span class="ot">-&gt;</span> <span class="dt">V2</span> <span class="dv">0</span> <span class="dv">1</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a> <span class="dt">DW</span> <span class="ot">-&gt;</span> <span class="dt">V2</span> (<span class="op">-</span><span class="dv">1</span>) <span class="dv">0</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a> turner <span class="ot">=</span> \<span class="kw">case</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a> <span class="dt">TurnNW</span> <span class="ot">-&gt;</span> over cDir <span class="op">$</span> \<span class="kw">case</span> <span class="dt">DN</span> <span class="ot">-&gt;</span> <span class="dt">DE</span>; <span class="dt">DE</span> <span class="ot">-&gt;</span> <span class="dt">DN</span>; <span class="dt">DS</span> <span class="ot">-&gt;</span> <span class="dt">DW</span>; <span class="dt">DW</span> <span class="ot">-&gt;</span> <span class="dt">DS</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a> <span class="dt">TurnNE</span> <span class="ot">-&gt;</span> over cDir <span class="op">$</span> \<span class="kw">case</span> <span class="dt">DN</span> <span class="ot">-&gt;</span> <span class="dt">DW</span>; <span class="dt">DW</span> <span class="ot">-&gt;</span> <span class="dt">DN</span>; <span class="dt">DS</span> <span class="ot">-&gt;</span> <span class="dt">DE</span>; <span class="dt">DE</span> <span class="ot">-&gt;</span> <span class="dt">DS</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a> <span class="dt">TurnInter</span> <span class="ot">-&gt;</span> over cTurns (<span class="op">+</span> <span class="dv">1</span>) <span class="op">.</span> over cDir (turnWith (c <span class="op">^.</span> cTurns))</span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a> turnWith i <span class="ot">=</span> <span class="kw">case</span> i <span class="ot">`mod`</span> <span class="dv">3</span> <span class="kw">of</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a> <span class="dv">0</span> <span class="ot">-&gt;</span> turnLeft</span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a> <span class="dv">1</span> <span class="ot">-&gt;</span> <span class="fu">id</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a> _ <span class="ot">-&gt;</span> turnLeft <span class="op">.</span> turnLeft <span class="op">.</span> turnLeft</span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a> turnLeft <span class="dt">DN</span> <span class="ot">=</span> <span class="dt">DW</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a> turnLeft <span class="dt">DE</span> <span class="ot">=</span> <span class="dt">DN</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a> turnLeft <span class="dt">DS</span> <span class="ot">=</span> <span class="dt">DE</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a> turnLeft <span class="dt">DW</span> <span class="ot">=</span> <span class="dt">DS</span></span></code></pre></div>
<p>There are ways we can the turning and <code>Dir</code> manipulations, but this way already is pretty clean, I think! We use lens combinators like <code>over</code> to simplify our updating of carts. If there is no turn at a given coordinate, then the cart just stays the same, and only the position updates.</p>
<p>Now, to separate out the <em>running</em> of the simulation from the <em>consumption</em> of the results, we can make a type that emits the result of a single step in the world:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">CartLog</span> a <span class="ot">=</span> <span class="dt">CLCrash</span> <span class="dt">Point</span> a <span class="co">-- ^ A crash, at a given point</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="dt">CLTick</span> a <span class="co">-- ^ No crashes, just a normal timestep</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="dt">CLDone</span> <span class="dt">Point</span> <span class="co">-- ^ Only one car left, at a given point</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span> (<span class="dt">Show</span>, <span class="dt">Functor</span>)</span></code></pre></div>
<p>And we can use that to implement <code>stepCarts</code>, which takes a “waiting, done” queue of carts and:</p>
<ol type="1">
<li>If <code>waiting</code> is empty, we dump <code>done</code> back into <code>waiting</code> and emit <code>CLTick</code> with our updated state. However, if <code>done</code> is empty, then we are done; emit <code>CLDone</code> with no new state.</li>
<li>Otherwise, pop an cart from <code>waiting</code> and move it. If there is a crash, emit <code>CLCrash</code> with the updated state (with things deleted).</li>
</ol>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>stepCarts</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="ot"> ::</span> <span class="dt">World</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a> <span class="ot">-&gt;</span> (<span class="dt">Carts</span>, <span class="dt">Carts</span>)</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a> <span class="ot">-&gt;</span> <span class="dt">CartLog</span> (<span class="dt">Carts</span>, <span class="dt">Carts</span>)</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>stepCarts w (waiting, done) <span class="ot">=</span> <span class="kw">case</span> M.minViewWithKey waiting <span class="kw">of</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a> <span class="dt">Nothing</span> <span class="ot">-&gt;</span> <span class="kw">case</span> M.minViewWithKey done <span class="kw">of</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a> <span class="dt">Just</span> ((<span class="dt">SP</span> lastPos, _), M.null<span class="ot">-&gt;</span><span class="dt">True</span>) <span class="ot">-&gt;</span> <span class="dt">CLDone</span> lastPos</span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a> _ <span class="ot">-&gt;</span> <span class="dt">CLTick</span> (done, M.empty)</span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a> <span class="dt">Just</span> (<span class="fu">uncurry</span> (stepCart w) <span class="ot">-&gt;</span> (p, c), waiting&#39;) <span class="ot">-&gt;</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a> <span class="kw">case</span> M.lookup p (waiting&#39; <span class="op">&lt;&gt;</span> done) <span class="kw">of</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a> <span class="dt">Nothing</span> <span class="ot">-&gt;</span> <span class="dt">CLTick</span> (waiting&#39; , M.insert p c done)</span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a> <span class="dt">Just</span> _ <span class="ot">-&gt;</span> <span class="dt">CLCrash</span> (_getSP p) (M.delete p waiting&#39;, M.delete p done )</span></code></pre></div>
<p>Now, we can write our consumers. These will be fed the results of <code>stepCarts</code> as they are produced. However, the <code>a</code> parameters will actually be the “next results”, in a way:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- | Get the result of the first crash.</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="ot">firstCrash ::</span> <span class="dt">CartLog</span> (<span class="dt">Maybe</span> <span class="dt">Point</span>) <span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">Point</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>firstCrash (<span class="dt">CLCrash</span> p _) <span class="ot">=</span> <span class="dt">Just</span> p <span class="co">-- this is it, chief</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>firstCrash (<span class="dt">CLTick</span> p) <span class="ot">=</span> p <span class="co">-- no, we have to go deeper</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>firstCrash (<span class="dt">CLDone</span> _ ) <span class="ot">=</span> <span class="dt">Nothing</span> <span class="co">-- we reached the end of the line, no crash.</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a><span class="co">-- | Get the final point.</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a><span class="ot">lastPoint ::</span> <span class="dt">CartLog</span> <span class="dt">Point</span> <span class="ot">-&gt;</span> <span class="dt">Point</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>lastPoint (<span class="dt">CLCrash</span> _ p) <span class="ot">=</span> p <span class="co">-- we have to go deeper</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>lastPoint (<span class="dt">CLTick</span> p) <span class="ot">=</span> p <span class="co">-- even deeper</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>lastPoint (<span class="dt">CLDone</span> p ) <span class="ot">=</span> p <span class="co">-- we&#39;re here</span></span></code></pre></div>
<p>And now:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ot">day13a ::</span> <span class="dt">World</span> <span class="ot">-&gt;</span> <span class="dt">Carts</span> <span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">Point</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>day13a w c <span class="ot">=</span> (firstCrash <span class="ot">`hylo`</span> stepCarts w) (c, M.empty)</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="ot">day13b ::</span> <span class="dt">World</span> <span class="ot">-&gt;</span> <span class="dt">Carts</span> <span class="ot">-&gt;</span> <span class="dt">Point</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>day13b w c <span class="ot">=</span> (lastPoint <span class="ot">`hylo`</span> stepCarts w) (c, M.empty)</span></code></pre></div>
<p>The magic of <code>hylo</code> is that, as <code>firstCrash</code> and <code>lastPoint</code> “demand” new values or points, <code>hylo</code> will ask <code>stepCarts w</code> for them. So, <code>stepCarts w</code> is iterated as many times as <code>firstCrash</code> and <code>lastPoint</code> needs.</p>
<h3 id="day-13-benchmarks">Day 13 Benchmarks</h3>
<pre><code>&gt;&gt; Day 13a
benchmarking...
time 16.23 ms (15.45 ms .. 17.66 ms)
0.983 R² (0.964 R² .. 0.999 R²)
mean 16.09 ms (15.83 ms .. 16.65 ms)
std dev 887.0 μs (436.6 μs .. 1.361 ms)
variance introduced by outliers: 24% (moderately inflated)
&gt;&gt; Day 13b
benchmarking...
time 26.62 ms (23.94 ms .. 29.29 ms)
0.947 R² (0.904 R² .. 0.988 R²)
mean 23.62 ms (22.40 ms .. 25.28 ms)
std dev 3.184 ms (2.140 ms .. 4.860 ms)
variance introduced by outliers: 56% (severely inflated)</code></pre>
</description>
<link>https://github.com/mstksg/advent-of-code-2018/blob/master/reflections.md#day-13</link>
<pubDate>Thu, 13 Dec 2018 01:00:00 EST</pubDate>
</item>
<item>
<title>Day 12</title>
<description><h2 id="day-12">Day 12</h2>
<!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day12.md`. If you want to edit this, edit
that file instead!
-->
<p><em><a href="https://adventofcode.com/2018/day/12">Prompt</a></em> / <em><a href="https://github.com/mstksg/advent-of-code-2018/blob/master/src/AOC/Challenge/Day12.hs">Code</a></em> / <em><a href="https://mstksg.github.io/advent-of-code-2018/src/AOC.Challenge.Day12.html">Rendered</a></em></p>
<p>Day 12 is made a little more fun with everyone’s favorite Haskell data structures: maps and sets! (Note that I’ve pretty much used Maps and Sets for every challenge, more or less!)</p>
<p>We can represent a “context”, or neighborhood, as a <code>Set (Finite 5)</code>, where <code>Finite 5</code> can be thought of as a type that only contains the numbers 0, 1, 2, 3, and 4 (five elements only). We’ll treat 0 as “two to the left”, 1 as “one to the left”, 2 as “the current point”, 3 as “one to the right”, and 4 as “two to the right”. The set will <em>contain</em> the given finite if it is “on” in that position. So, for example, the context <code>#.##.</code> would be <code>S.fromList [0,2,3]</code>.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Ctx</span> <span class="ot">=</span> <span class="dt">Set</span> (<span class="dt">Finite</span> <span class="dv">5</span>)</span></code></pre></div>
<p>Our ruleset will be <code>Set Ctx</code>, or a set of neighborhoods. If a given neighborhood is <em>in</em> the set, then that means that the plant is meant to turn on. Otherwise, it means that the plant is meant to turn off. So, <code>#.##. =&gt; #</code> would mean that the item <code>S.fromList [0,2,3]</code> is in the ruleset, but <code>##..# =&gt; .</code> would mean that the item <code>S.fromList [0,1,4]</code> is <em>not</em> in the ruleset.</p>
<p>Finally, the type of our “world” is just <code>Set Int</code>. If a plant is “on”, then its index will be in the set. Otherwise, its index will <em>not</em> be in the set.</p>
<p>One nice thing about representing the world as <code>Set Int</code> is that getting the “sum of all plant IDs that are on” is just <code>sum :: Set Int -&gt; Int</code> :)</p>
<p>Writing our step function is going to be filtering all of the “candidate” positions for the ones that remain “on”. That’s it! We perform this filter by aggregating the neighborhood around each point and checking if the neighborhood is in the ruleset.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>step</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="ot"> ::</span> <span class="dt">Set</span> <span class="dt">Ctx</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a> <span class="ot">-&gt;</span> <span class="dt">Set</span> <span class="dt">Int</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a> <span class="ot">-&gt;</span> <span class="dt">Set</span> <span class="dt">Int</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>step ctxs w0 <span class="ot">=</span> S.fromDistinctAscList</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> <span class="fu">filter</span> go</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a> <span class="op">$</span> [S.findMin w0 <span class="op">-</span> <span class="dv">2</span> <span class="op">..</span> S.findMax w0 <span class="op">+</span> <span class="dv">2</span>]</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a> go i <span class="ot">=</span> neighbs <span class="ot">`S.member`</span> ctxs</span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a> neighbs <span class="ot">=</span> S.fromDistinctAscList <span class="op">.</span> <span class="fu">flip</span> <span class="fu">filter</span> finites <span class="op">$</span> \j <span class="ot">-&gt;</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a> (i <span class="op">-</span> <span class="dv">2</span> <span class="op">+</span> <span class="fu">fromIntegral</span> j) <span class="ot">`S.member`</span> w0</span></code></pre></div>
<p>Part 2 requires a bit of trickery. If we monitor our outputs, we can observe that the entire shape of the world starts to loop after a given amount of time. We can find this loop structure by stepping repeatedly and finding the first item that is repeated, by using a “seen items” set. We have to make sure to “normalize” our representation so that the same shame will be matched no matter what coordinate it starts at. I did this by subtracting out the minimum item in the set, so that the leftmost plant is always at zero.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>findLoop</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="ot"> ::</span> <span class="dt">Set</span> <span class="dt">Ctx</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a> <span class="ot">-&gt;</span> <span class="dt">Set</span> <span class="dt">Pos</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a> <span class="ot">-&gt;</span> (<span class="dt">Int</span>, <span class="dt">Int</span>, <span class="dt">Int</span>) <span class="co">-- time to loop, loop size, loop incr</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>findLoop ctxs w0 <span class="ot">=</span> go (M.singleton w0 (<span class="dv">0</span>, <span class="dv">0</span>)) <span class="dv">1</span> w0</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a> go <span class="op">!</span>seen <span class="op">!</span>i <span class="op">!</span>w <span class="ot">=</span> <span class="kw">case</span> M.lookup w&#39;Norm seen <span class="kw">of</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a> <span class="dt">Nothing</span> <span class="ot">-&gt;</span> go (M.insert w&#39;Norm (mn, i) seen) (i <span class="op">+</span> <span class="dv">1</span>) w&#39;</span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a> <span class="dt">Just</span> (seenMn, seenI) <span class="ot">-&gt;</span> (seenI, i <span class="op">-</span> seenI, mn <span class="op">-</span> seenMn)</span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a> w&#39; <span class="ot">=</span> step ctxs w</span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a> (mn, w&#39;Norm) <span class="ot">=</span> normalize w&#39;</span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a> normalize w <span class="ot">=</span> (mn, S.map (<span class="fu">subtract</span> mn) w)</span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a> mn <span class="ot">=</span> S.findMin w</span></code></pre></div>
<p>And now we can be a little clever using <code>divMod</code> to factor out 50 billion into the “initialization”, the “loop amount”, and the “amount to increase”:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>stepN</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="ot"> ::</span> <span class="dt">Int</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a> <span class="ot">-&gt;</span> <span class="dt">Set</span> <span class="dt">Pos</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a> <span class="ot">-&gt;</span> <span class="dt">Set</span> <span class="dt">Ctx</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a> <span class="ot">-&gt;</span> <span class="dt">Set</span> <span class="dt">Pos</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>stepN n w ctx <span class="ot">=</span> goN extra</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> S.map (<span class="op">+</span> (loopIncr <span class="op">*</span> looped))</span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> goN ttl</span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a> <span class="op">$</span> w</span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a> goN m <span class="ot">=</span> (<span class="op">!!!</span> m) <span class="op">.</span> <span class="fu">iterate</span> (step ctx)</span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a> (ttl, loopSize, loopIncr) <span class="ot">=</span> findLoop ctx w</span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a> (looped, extra) <span class="ot">=</span> (n <span class="op">-</span> ttl) <span class="ot">`divMod`</span> loopSize</span></code></pre></div>
<h3 id="day-12-benchmarks">Day 12 Benchmarks</h3>
<pre><code>&gt;&gt; Day 12a
benchmarking...
time 989.9 μs (956.8 μs .. 1.021 ms)
0.992 R² (0.988 R² .. 0.995 R²)
mean 903.4 μs (880.0 μs .. 934.1 μs)
std dev 77.26 μs (69.01 μs .. 83.18 μs)
variance introduced by outliers: 67% (severely inflated)
* parsing and formatting times excluded
&gt;&gt; Day 12b
benchmarking...
time 21.60 ms (20.06 ms .. 22.84 ms)
0.979 R² (0.950 R² .. 0.992 R²)
mean 22.90 ms (21.82 ms .. 26.10 ms)
std dev 3.973 ms (1.452 ms .. 7.201 ms)
variance introduced by outliers: 74% (severely inflated)
* parsing and formatting times excluded</code></pre>
</description>
<link>https://github.com/mstksg/advent-of-code-2018/blob/master/reflections.md#day-12</link>
<pubDate>Wed, 12 Dec 2018 01:00:00 EST</pubDate>
</item>
<item>
<title>Day 11</title>
<description><h2 id="day-11">Day 11</h2>
<!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day11.md`. If you want to edit this, edit
that file instead!
-->
<p><em><a href="https://adventofcode.com/2018/day/11">Prompt</a></em> / <em><a href="https://github.com/mstksg/advent-of-code-2018/blob/master/src/AOC/Challenge/Day11.hs">Code</a></em> / <em><a href="https://mstksg.github.io/advent-of-code-2018/src/AOC.Challenge.Day11.html">Rendered</a></em></p>
<p>Day 11 is a nice opportunity to demonstrate dynamic programming in a purely functional language like Haskell.</p>
<p>Once we define a function to get a power level based on a serial number:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Point</span> <span class="ot">=</span> <span class="dt">V2</span> <span class="dt">Int</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="ot">powerLevel ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Point</span> <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>powerLevel sid (<span class="dt">V2</span> x y) <span class="ot">=</span> hun ((rid <span class="op">*</span> y <span class="op">+</span> sid) <span class="op">*</span> rid) <span class="op">-</span> <span class="dv">5</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a> hun <span class="ot">=</span> (<span class="ot">`mod`</span> <span class="dv">10</span>) <span class="op">.</span> (<span class="ot">`div`</span> <span class="dv">100</span>)</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a> rid <span class="ot">=</span> x <span class="op">+</span> <span class="dv">10</span></span></code></pre></div>
<p>We can create a <code>Map</code> of of <code>Point</code> to power level, by creating the set of all points (using <code>range</code> from <em>Data.Ix</em>) and using <code>M.fromSet</code> with a function.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">mkMap ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Map</span> <span class="dt">Point</span> <span class="dt">Int</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>mkMap i <span class="ot">=</span> M.fromSet (powerLevel i)</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> S.fromList</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a> <span class="op">$</span> <span class="fu">range</span> (<span class="dt">V2</span> <span class="dv">1</span> <span class="dv">1</span>, <span class="dt">V2</span> <span class="dv">300</span> <span class="dv">300</span>)</span></code></pre></div>
<p>Now, both Part 1 and Part 2 involve finding sums of contiguous squares in the input. One popular way to do this quickly for many different sums is to build a [summed-area table][]</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">summedAreaTable ::</span> <span class="dt">Map</span> <span class="dt">Point</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Map</span> <span class="dt">Point</span> <span class="dt">Int</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>summedAreaTable mp <span class="ot">=</span> force sat</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a> sat <span class="ot">=</span> M.mapWithKey go mp</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a> go p0 v <span class="ot">=</span> (<span class="op">+</span> v) <span class="op">.</span> <span class="fu">sum</span> <span class="op">.</span> catMaybes <span class="op">$</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a> [ <span class="fu">negate</span> <span class="op">&lt;$&gt;</span> M.lookup (p0 <span class="op">-</span> <span class="dt">V2</span> <span class="dv">1</span> <span class="dv">1</span>) sat</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a> , M.lookup (p0 <span class="op">-</span> <span class="dt">V2</span> <span class="dv">1</span> <span class="dv">0</span>) sat</span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a> , M.lookup (p0 <span class="op">-</span> <span class="dt">V2</span> <span class="dv">0</span> <span class="dv">1</span>) sat</span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a> ]</span></code></pre></div>
<p>This is where the dynamic programming happens: our summed area is <code>sat</code>, and we define <code>sat</code> in a self-recursive way, using <code>M.mapWithKey go</code>. <code>M.mapWithKey go</code> lazily generates each cell of <code>sat</code> by <em>referring to other cells in <code>sat</code></em>. Because of laziness, <code>mapWithKey</code> doesn’t do any actual “mapping”; but, rather, allocates thunks at each value in the map. As soon as these thunks are asked for, they resolve and are kept as resolved values.</p>
<p>For example, note that <code>go (V2 1 1) v11</code> does not refer to any other value. So, the map at <code>V2 1 1</code> is just <code>v11</code>.</p>
<p>However, <code>go (V2 2 1) v21</code> depends on one other value: <code>M.lookup (V2 1 1) sat</code>. But, because we already have evaluated this to <code>v11</code>, all is well; our answer is <code>v21 + v11</code>.</p>
<p>Now, <code>go (V2 2 2) v22</code> depends on three other values: it depends on <code>M.lookup (V 1 1) sat</code>, <code>M.lookup (V2 1 2) sat</code>, and <code>M.lookup (V2 1 2) sat</code>. GHC will go and evaluate the ones it needs to evaluate, caching them in the values of the map, and then just now return the pre-evaluated results.</p>
<p>In this way, we build the summed area table “lazily” in a self-recursive way. At the end of it all, we return <code>force sat</code>, which makes sure the entire <code>sat</code> map is filled out all the way (getting rid of all thunks) when the user actually tries to <em>use</em> the summed area table.</p>
<p>The rest of this involves just making a list of all possible sums of squares, and finding the maximum of all of them. Because all of our sums of squares are now calculable in O(1) on the size of the square (after we generate our table), the search is very manageable.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ot">fromSAT ::</span> <span class="dt">Map</span> <span class="dt">Point</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Point</span> <span class="ot">-&gt;</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>fromSAT sat (<span class="fu">subtract</span> (<span class="dt">V2</span> <span class="dv">1</span> <span class="dv">1</span>)<span class="ot">-&gt;</span>p) n <span class="ot">=</span> <span class="fu">sum</span> <span class="op">.</span> catMaybes <span class="op">$</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a> [ M.lookup p sat</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a> , M.lookup (p <span class="op">+</span> <span class="dt">V2</span> n n) sat</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a> , <span class="fu">negate</span> <span class="op">&lt;$&gt;</span> M.lookup (p <span class="op">+</span> <span class="dt">V2</span> <span class="dv">0</span> n) sat</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a> , <span class="fu">negate</span> <span class="op">&lt;$&gt;</span> M.lookup (p <span class="op">+</span> <span class="dt">V2</span> n <span class="dv">0</span>) sat</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a> ]</span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a><span class="ot">findMaxAny ::</span> <span class="dt">Map</span> <span class="dt">Point</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> (<span class="dt">Point</span>, <span class="dt">Int</span>)</span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>findMaxAny mp <span class="ot">=</span> <span class="fu">fst</span> <span class="op">.</span> maximumBy (comparing <span class="fu">snd</span>)</span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a> <span class="op">$</span> [ ((p, n), fromSAT sat p n)</span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a> , n <span class="ot">&lt;-</span> [<span class="dv">1</span> <span class="op">..</span> <span class="dv">300</span>]</span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a> , p <span class="ot">&lt;-</span> <span class="fu">range</span> (<span class="dt">V2</span> <span class="dv">1</span> <span class="dv">1</span>, <span class="dt">V2</span> (<span class="dv">300</span> <span class="op">-</span> n <span class="op">+</span> <span class="dv">1</span>) (<span class="dv">300</span> <span class="op">-</span> n <span class="op">+</span> <span class="dv">1</span>))</span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a> ]</span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a> sat <span class="ot">=</span> summedAreaTable mp</span></code></pre></div>
<p>Note the benchmarks below are actually using an early-cut-off version of <code>findMaxAny</code> that I implemented after thinking about ways of optimization.</p>
<h3 id="day-11-benchmarks">Day 11 Benchmarks</h3>
<pre><code>&gt;&gt; Day 11a
benchmarking...
time 80.31 ms (77.70 ms .. 81.90 ms)
0.999 R² (0.997 R² .. 1.000 R²)
mean 82.27 ms (80.62 ms .. 86.64 ms)
std dev 4.393 ms (1.213 ms .. 7.294 ms)
* parsing and formatting times excluded
&gt;&gt; Day 11b
benchmarking...
time 825.4 ms (800.7 ms .. 865.9 ms)
1.000 R² (1.000 R² .. 1.000 R²)
mean 841.3 ms (832.8 ms .. 847.7 ms)
std dev 9.500 ms (5.115 ms .. 13.39 ms)
variance introduced by outliers: 19% (moderately inflated)
* parsing and formatting times excluded</code></pre>
</description>
<link>https://github.com/mstksg/advent-of-code-2018/blob/master/reflections.md#day-11</link>
<pubDate>Tue, 11 Dec 2018 01:00:00 EST</pubDate>
</item>
<item>
<title>Day 10</title>
<description><h2 id="day-10">Day 10</h2>
<!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day10.md`. If you want to edit this, edit
that file instead!
-->
<p><em><a href="https://adventofcode.com/2018/day/10">Prompt</a></em> / <em><a href="https://github.com/mstksg/advent-of-code-2018/blob/master/src/AOC/Challenge/Day10.hs">Code</a></em> / <em><a href="https://mstksg.github.io/advent-of-code-2018/src/AOC.Challenge.Day10.html">Rendered</a></em></p>
<p>I originally did this by running a simulation, parting the velocity and points into two lists and using <code>zipWith (+)</code> for the simulation. However, I found a much nicer closed-form version that [I wrote about in my blog][d10b]!</p>
<h3 id="day-10-benchmarks">Day 10 Benchmarks</h3>
<pre><code>&gt;&gt; Day 10a
benchmarking...
time 74.62 μs (72.83 μs .. 79.00 μs)
0.987 R² (0.967 R² .. 0.999 R²)
mean 79.63 μs (75.90 μs .. 91.32 μs)
std dev 21.99 μs (11.81 μs .. 38.03 μs)
variance introduced by outliers: 97% (severely inflated)
* parsing and formatting times excluded
&gt;&gt; Day 10b
benchmarking...
time 27.54 μs (26.86 μs .. 28.97 μs)
0.991 R² (0.982 R² .. 0.999 R²)
mean 27.77 μs (27.17 μs .. 29.87 μs)
std dev 3.265 μs (1.773 μs .. 6.063 μs)
variance introduced by outliers: 88% (severely inflated)
* parsing and formatting times excluded</code></pre>
</description>
<link>https://github.com/mstksg/advent-of-code-2018/blob/master/reflections.md#day-10</link>
<pubDate>Mon, 10 Dec 2018 01:00:00 EST</pubDate>
</item>
<item>
<title>Day 9</title>
<description><h2 id="day-9">Day 9</h2>
<!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day09.md`. If you want to edit this, edit
that file instead!
-->
<p><em><a href="https://adventofcode.com/2018/day/9">Prompt</a></em> / <em><a href="https://github.com/mstksg/advent-of-code-2018/blob/master/src/AOC/Challenge/Day09.hs">Code</a></em> / <em><a href="https://mstksg.github.io/advent-of-code-2018/src/AOC.Challenge.Day09.html">Rendered</a></em></p>
<p>And today features the re-introduction of an Advent of Code staple: the (circular) tape/zipper! I used this data structure last year for days 5, 17, 18 and 23, and I consider them near and dear to my heart as Advent of Code data structures :)</p>
<p>Last year, I wrote my own implementations on the spot, but since then I’ve come to appreciate the <em><a href="https://hackage.haskell.org/package/pointedlist">pointed-list</a></em> library. A circular tape is a circular data structure with a “focus” that you can move back and forth in. This is the data structure that implements exactly what the challenge talks about! It’s linear-time on “moving the focus”, and constant-time on insertions and deletions.</p>
<p>The center of everything is the <code>place</code> function, which takes a number to place and a tape to place it in, and returns an updated tape with the “score” accumulated for that round.</p>
<p>We see that it is mostly a straightforward translation of the problem statement. If <code>x</code> is a multiple of 23, then we move 7 spaces to the left, and return the resulting tape with the item deleted. The score is the deleted item plus <code>x</code>. Otherwise, we just move 2 spaces to the right and insert <code>x</code>, with a score of 0.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>place</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="ot"> ::</span> <span class="dt">Int</span> <span class="co">-- ^ number to place</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> <span class="ot">-&gt;</span> <span class="dt">PointedList</span> <span class="dt">Int</span> <span class="co">-- ^ tape</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a> <span class="ot">-&gt;</span> (<span class="dt">Int</span>, <span class="dt">PointedList</span> <span class="dt">Int</span>) <span class="co">-- ^ resulting tape, and scored points</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>place x l</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> x <span class="ot">`mod`</span> <span class="dv">23</span> <span class="op">==</span> <span class="dv">0</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> <span class="kw">let</span> l&#39; <span class="ot">=</span> PL.moveN (<span class="op">-</span><span class="dv">7</span>) l</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a> toAdd <span class="ot">=</span> _focus l&#39;</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a> <span class="kw">in</span> (toAdd <span class="op">+</span> x, fromJust (PL.deleteRight l&#39;))</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="fu">otherwise</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> (<span class="dv">0</span>, (PL.insertLeft x <span class="op">.</span> PL.moveN <span class="dv">2</span>) l)</span></code></pre></div>
<p>We wrap it all up with a <code>run</code> function, which is a strict fold over a list of <code>(currentPlayer, itemToPlace)</code> pairs, accumulating a <code>(scorecard, tape)</code> state (our scorecard will be a vector where each index is a different player’s score). At each step, we <code>place</code>, and use the result to update our scorecard and tape. The <em>lens</em> library offers some nice tool for incrementing a given index of a vector.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>run</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="ot"> ::</span> <span class="dt">Int</span> <span class="co">-- ^ number of players</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a> <span class="ot">-&gt;</span> <span class="dt">Int</span> <span class="co">-- ^ Max # of piece</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a> <span class="ot">-&gt;</span> <span class="dt">V.Vector</span> <span class="dt">Int</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>run numPlayers maxPiece <span class="ot">=</span> <span class="fu">fst</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> foldl&#39; go (V.replicate numPlayers <span class="dv">0</span>, PL.singleton <span class="dv">0</span>)</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a> <span class="op">$</span> <span class="fu">zip</span> players toInsert</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a> go (<span class="op">!</span>scores, <span class="op">!</span>tp) (<span class="op">!</span>player, <span class="op">!</span>x) <span class="ot">=</span> (scores <span class="op">&amp;</span> ix player <span class="op">+~</span> pts, tp&#39;)</span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a> (pts, tp&#39;) <span class="ot">=</span> place x tp</span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a> players <span class="ot">=</span> (<span class="ot">`mod`</span> numPlayers) <span class="op">&lt;$&gt;</span> [<span class="dv">0</span> <span class="op">..</span>]</span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a> toInsert <span class="ot">=</span> [<span class="dv">1</span><span class="op">..</span>maxPiece]</span></code></pre></div>
<p>And that’s it! The answer is just the maximal score in the final score vector:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">day09a ::</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>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>day09a numPlayers maxPiece <span class="ot">=</span> V.maximum (run numPlayers maxPiece)</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="ot">day09b ::</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>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>day09b numPlayers maxPiece <span class="ot">=</span> V.maximum (run numPlayers (maxPiece <span class="op">*</span> <span class="dv">100</span>))</span></code></pre></div>
<p>From this naive implementation, Part 1 takes 56.ms, and Part 2 takes 4.5s.</p>
<h3 id="day-9-benchmarks">Day 9 Benchmarks</h3>
<pre><code>&gt;&gt; Day 09a
benchmarking...
time 48.10 ms (43.29 ms .. 55.00 ms)
0.963 R² (0.916 R² .. 0.997 R²)
mean 46.84 ms (44.99 ms .. 50.53 ms)
std dev 4.997 ms (1.566 ms .. 6.993 ms)
variance introduced by outliers: 41% (moderately inflated)
* parsing and formatting times excluded
&gt;&gt; Day 09b
benchmarking...
time 6.997 s (2.875 s .. 11.89 s)
0.923 R² (0.902 R² .. 1.000 R²)
mean 5.830 s (4.820 s .. 6.585 s)
std dev 1.042 s (290.2 ms .. 1.293 s)
variance introduced by outliers: 47% (moderately inflated)
* parsing and formatting times excluded</code></pre>
</description>
<link>https://github.com/mstksg/advent-of-code-2018/blob/master/reflections.md#day-9</link>
<pubDate>Sun, 9 Dec 2018 01:00:00 EST</pubDate>
</item>
<item>
<title>Day 8</title>
<description><h2 id="day-8">Day 8</h2>
<!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day08.md`. If you want to edit this, edit
that file instead!
-->
<p><em><a href="https://adventofcode.com/2018/day/8">Prompt</a></em> / <em><a href="https://github.com/mstksg/advent-of-code-2018/blob/master/src/AOC/Challenge/Day08.hs">Code</a></em> / <em><a href="https://mstksg.github.io/advent-of-code-2018/src/AOC.Challenge.Day08.html">Rendered</a></em></p>
<p>Another nice one for Haskell! We’re just parsing a stream of <code>Int</code>s here :)</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Text.Parsec</span> <span class="kw">as</span> <span class="dt">P</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Parser</span> <span class="ot">=</span> <span class="dt">P.Parsec</span> [<span class="dt">Int</span>] ()</span></code></pre></div>
<p>with a <code>Parsec [Int] ()</code>, it means that our “tokens” are <code>Int</code>. That means <code>P.anyToken :: Parser Int</code> will pop the next <code>Int</code> from the stream.</p>
<p>Our Day 1 will be the <code>sum1</code>, which will parse a stream of <code>Int</code>s into the sum of all the metadatas.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">sum1 ::</span> <span class="dt">Parser</span> <span class="dt">Int</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>sum1 <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a> numChild <span class="ot">&lt;-</span> P.anyToken</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a> numMeta <span class="ot">&lt;-</span> P.anyToken</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a> childs <span class="ot">&lt;-</span> <span class="fu">sum</span> <span class="op">&lt;$&gt;</span> replicateM numChild sum1</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a> metas <span class="ot">&lt;-</span> <span class="fu">sum</span> <span class="op">&lt;$&gt;</span> replicateM numMeta P.anyToken</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a> <span class="fu">pure</span> <span class="op">$</span> childs <span class="op">+</span> metas</span></code></pre></div>
<p>And so part 1 is:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">day01a ::</span> [<span class="dt">Int</span>] <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>day01a xs <span class="ot">=</span> fromRight <span class="dv">0</span> <span class="op">.</span> P.parse sum1 <span class="st">&quot;&quot;</span></span></code></pre></div>
<p>Part 2 is similar. Again, we parse a stream of ints into a sum:</p>
<pre><code>sum2 :: Parser Int
sum2 = do
numChild &lt;- P.anyToken
numMeta &lt;- P.anyToken
childs &lt;- replicateM numChild sum2
metas &lt;- replicateM numMeta P.anyToken
pure $ if null childs
then sum metas
else sum . mapMaybe (\i -&gt; childs ^? ix (i - 1)) $ metas</code></pre>
<p>I’m using <code>xs ^? ix i</code> (from lens) as a “safe indexing”, that returns <code>Maybe a</code>. We need to remember to index into <code>i - 1</code> because our indexing starts at one!</p>
<p>And so part 2 is:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ot">day02a ::</span> [<span class="dt">Int</span>] <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>day02a <span class="ot">=</span> fromRight <span class="dv">0</span> <span class="op">.</span> P.parse sum1 <span class="st">&quot;&quot;</span></span></code></pre></div>
<p>We can get a list of <code>[Int]</code> from a string input using <code>map read . words</code>.</p>
<h3 id="day-8-benchmarks">Day 8 Benchmarks</h3>
<pre><code>&gt;&gt; Day 08a
benchmarking...
time 4.929 ms (4.859 ms .. 5.015 ms)
0.994 R² (0.983 R² .. 0.999 R²)
mean 4.872 ms (4.810 ms .. 5.000 ms)
std dev 238.5 μs (143.0 μs .. 412.6 μs)
variance introduced by outliers: 28% (moderately inflated)
* parsing and formatting times excluded
&gt;&gt; Day 08b
benchmarking...
time 1.849 ms (1.801 ms .. 1.918 ms)
0.991 R² (0.979 R² .. 0.998 R²)
mean 1.820 ms (1.787 ms .. 1.852 ms)
std dev 110.6 μs (74.26 μs .. 155.2 μs)
variance introduced by outliers: 44% (moderately inflated)
* parsing and formatting times excluded</code></pre>
</description>
<link>https://github.com/mstksg/advent-of-code-2018/blob/master/reflections.md#day-8</link>
<pubDate>Sat, 8 Dec 2018 01:00:00 EST</pubDate>
</item>
<item>
<title>Day 6</title>
<description><h2 id="day-6">Day 6</h2>
<!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day06.md`. If you want to edit this, edit
that file instead!
-->
<p><em><a href="https://adventofcode.com/2018/day/6">Prompt</a></em> / <em><a href="https://github.com/mstksg/advent-of-code-2018/blob/master/src/AOC/Challenge/Day06.hs">Code</a></em> / <em><a href="https://mstksg.github.io/advent-of-code-2018/src/AOC.Challenge.Day06.html">Rendered</a></em></p>
<p>Day 6 Part 1 has us build a <a href="https://en.wikipedia.org/wiki/Voronoi_diagram">Voronoi Diagram</a>, and inspect properties of it. Again, it’s all very functional already, since we just need, basically:</p>
<ol type="1">
<li>A function to get a voronoi diagram from a set of points</li>
<li>A function to query the diagram for properties we care about</li>
</ol>
<p>Along the way, types will help us write our programs, because we constantly will be asking the compiler for “what could go here” sort of things; it’ll also prevent us from putting the wrong pieces together!</p>
<p>We’re going to leverage the <em>[linear][]</em> library again, for its <code>V2 Int</code> type for our points. It has a very useful <code>Num</code> and <code>Foldable</code> instance, which we can use to write our <code>distance</code> function:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Point</span> <span class="ot">=</span> <span class="dt">V2</span> <span class="dt">Int</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="ot">distance ::</span> <span class="dt">Point</span> <span class="ot">-&gt;</span> <span class="dt">Point</span> <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>distance x y <span class="ot">=</span> <span class="fu">sum</span> <span class="op">$</span> <span class="fu">abs</span> (x <span class="op">-</span> y)</span></code></pre></div>
<p>We’re going to be representing our voronoi diagram using a <code>Map Point Point</code>: a map of points to the location of the “Site” they are assigned to.</p>
<p>We can generate such a map by getting a <code>Set Point</code> (a set of all points within our area of interest) and using <code>M.fromSet :: (Point -&gt; Point) -&gt; Set Point -&gt; Map Point Point</code>, to assign a Site to each point.</p>
<p>First, we build a bounding box so don’t need to generate an infinite map. The <code>boundingBox</code> function will take a non-empty list of points (from <code>Data.List.NonEmpty</code>) and return a <code>V2 Point</code>, which the lower-left and upper-right corners of our bounding box.</p>
<p>We need to iterate through the whole list and accumulate the minimum and maximums of x and y. We can do it all in one pass by taking advantage of the <code>(Semigroup a, Semigroup b) =&gt; Semigroup (a, b)</code> instance, the <code>Min</code> and <code>Max</code> newtype wrappers to give us the appropriate semigroups, and using <code>foldMap1 :: Semigroup m =&gt; (a -&gt; m) -&gt; NonEmpty a -&gt; m</code>:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.List.NonEmpty</span> (<span class="dt">NonEmpty</span>(..))</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Semigroup.Foldable</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Box</span> <span class="ot">=</span> <span class="dt">V2</span> <span class="dt">Point</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="ot">boundingBox ::</span> <span class="dt">NonEmpty</span> <span class="dt">Point</span> <span class="ot">-&gt;</span> <span class="dt">Box</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>boundingBox ps <span class="ot">=</span> <span class="dt">V2</span> xMin yMin <span class="ot">`V2`</span> <span class="dt">V2</span> xMax yMax</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a> (<span class="dt">Min</span> xMin, <span class="dt">Min</span> yMin, <span class="dt">Max</span> xMax, <span class="dt">Max</span> yMax) <span class="ot">=</span> <span class="fu">flip</span> foldMap1 ps <span class="op">$</span> \(<span class="dt">V2</span> x y) <span class="ot">-&gt;</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a> (<span class="dt">Min</span> x, <span class="dt">Min</span> y, <span class="dt">Max</span> x, <span class="dt">Max</span> y)</span></code></pre></div>
<p>(Note that we can just use <code>foldMap</code>, because <code>Min</code> and <code>Max</code> have a <code>Monoid</code> instance because <code>Int</code> is bounded. But that’s no fun! And besides, what if we had used <code>Integer</code>?)</p>
<p>(Also note that this could potentially blow up the stack, because tuples in Haskell are lazy. If we cared about performance, we’d use a strict tuple type instead of the lazy tuple. In this case, since we only have on the order of a few thousand points, it’s not a huge deal)</p>
<p>Next, we write a function that, given a non-empty set of sites and a point we wish to label, return the label (site location) of that point.</p>
<p>We do this by making a <code>NonEmpty (Point, Int)</code> <code>dists</code> that pair up sites to the distance between that site and the point.</p>
<p>We need now to find the <em>minimum</em> distance in that <code>NonEmpty</code>. But not only that, we need to find the <em>unique</em> minimum, or return <code>Nothing</code> if we don’t have a unique minimum.</p>
<p>To do this, we can use <code>NE.head . NE.groupWith1 snd . NE.sortWith snd</code>. This will sort the <code>NonEmpty</code> on the second item (the distance <code>Int</code>), which puts all of the minimal distances in the front. <code>NE.groupWith1 snd</code> will then group together the pairs with matching distances, moving all of the minimal distance to the first item in the list. Then we use the total <code>NE.head</code> to get the first item: the non-empty list with the minimal distances.</p>
<p>Then we can pattern match on <code>(closestSite, minDist) :| []</code> to prove that this “first list” has exactly one item, so the minimum is unique.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>labelVoronoi</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="ot"> ::</span> <span class="dt">NonEmpty</span> <span class="dt">Point</span> <span class="co">-- ^ set of sites</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a> <span class="ot">-&gt;</span> <span class="dt">Point</span> <span class="co">-- ^ point to label</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a> <span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">Point</span> <span class="co">-- ^ the label, if unique</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>labelVoronoi sites p <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a> (closestSite, _) <span class="op">:|</span> [] <span class="ot">&lt;-</span> <span class="dt">Just</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> NE.head</span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> NE.groupWith1 <span class="fu">snd</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> NE.sortWith <span class="fu">snd</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a> <span class="op">$</span> dists</span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a> <span class="fu">pure</span> closestSite</span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a> dists <span class="ot">=</span> sites <span class="op">&lt;&amp;&gt;</span> \site <span class="ot">-&gt;</span> (site, distance p site)</span></code></pre></div>
<p>Once we have our voronoi diagram <code>Map Point Point</code> (map of points to nearest-site locations), we can use our <code>freqs :: [Point] -&gt; Map Point Int</code> function that we’ve used many times to get a <code>Map Point Int</code>, or a map from Site points to Frequencies — essentially a map of Sites to the total area of the cells assigned to them. The problem asks us what the size of the largest cell is, so that’s the same as asking for the largest frequency, <code>maximum</code>.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ot">queryVoronoi ::</span> <span class="dt">Map</span> <span class="dt">Point</span> <span class="dt">Point</span> <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>queryVeronoi <span class="ot">=</span> <span class="fu">maximum</span> <span class="op">.</span> freqs <span class="op">.</span> M.elems</span></code></pre></div>
<p>One caveat: we need to ignore cells that are “infinite”. To that we can create the set of all Sitse that touch the border, and then filter out all points in the map that are associated with a Site that touches the border.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ot">cleanVoronoi ::</span> <span class="dt">Box</span> <span class="ot">-&gt;</span> <span class="dt">Map</span> <span class="dt">Point</span> <span class="dt">Point</span> <span class="ot">-&gt;</span> <span class="dt">Map</span> <span class="dt">Point</span> <span class="dt">Point</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>cleanVoronoi (<span class="dt">V2</span> (<span class="dt">V2</span> xMin yMin) (<span class="dt">V2</span> xMax yMax)) voronoi <span class="ot">=</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a> M.filter (<span class="ot">`S.notMember`</span> edges) voronoi</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a> edges <span class="ot">=</span> S.fromList</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> mapMaybe (\(point, site) <span class="ot">-&gt;</span> site <span class="op">&lt;$</span> guard (onEdge point))</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> M.toList</span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a> <span class="op">$</span> voronoi</span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a> onEdge (<span class="dt">V2</span> x y) <span class="ot">=</span> <span class="fu">or</span> [ x <span class="op">==</span> xMin, x <span class="op">==</span> xMax, y <span class="op">==</span> yMin, y <span class="op">==</span> yMax ]</span></code></pre></div>
<p>We turn <code>edges</code> into a <code>Set</code> (instead of just a list) because of the fast <code>S.notMember</code> function, to check if a Site ID is in the set of edge-touching ID’s.</p>
<p>Finally, we need to get a function from a bounding box <code>Box</code> to <code>[Point]</code>: all of the points in that bounding box. Luckily, this is exactly what the <code>Ix</code> instance of <code>V2 Int</code> gets us:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.Ix</span> <span class="kw">as</span> <span class="dt">Ix</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="ot">bbPoints ::</span> <span class="dt">Box</span> <span class="ot">-&gt;</span> [<span class="dt">Point</span>]</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>bbPoints (<span class="dt">V2</span> mins maxs) <span class="ot">=</span> <span class="dt">Ix</span><span class="op">.</span><span class="fu">range</span> (mins, maxs)</span></code></pre></div>
<p>And so Part 1 is:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ot">day06a ::</span> <span class="dt">NonEmpty</span> <span class="dt">Point</span> <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>day06a sites <span class="ot">=</span> queryVoronoi cleaned</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a> bb <span class="ot">=</span> boundingBox sites</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a> voronoi <span class="ot">=</span> catMaybes</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> M.fromSet (labelVoronoi sites)</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> S.fromList</span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a> <span class="op">$</span> bbPoints bb</span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a> cleaned <span class="ot">=</span> cleanVoronoi bb voronoi</span></code></pre></div>
<p>Basically, a series of somewhat complex queries (translated straight from the prompt) on a voronoi diagram generated by a set of points.</p>
<p>Part 2 is much simpler; it’s just filtering for all the points that have a given function, and then counting how many points there are.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ot">day06b ::</span> <span class="dt">NonEmpty</span> <span class="dt">Point</span> <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>day06b sites <span class="ot">=</span> <span class="fu">length</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> <span class="fu">filter</span> ((<span class="op">&lt;</span> <span class="dv">10000</span>) <span class="op">.</span> totalDist)</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> bbPoints</span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> boundingBox</span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a> <span class="op">$</span> sites</span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a> totalDist p <span class="ot">=</span> <span class="fu">sum</span> <span class="op">$</span> distance p <span class="op">&lt;$&gt;</span> sites</span></code></pre></div>
<ol type="1">
<li>Get the bounding box with <code>boundingBox</code></li>
<li>Generate all of the points in that bounding box with <code>bbPoints</code></li>
<li>Filter those points for just those where their <code>totalDist</code> is less than 10000</li>
<li>Find the number of such points</li>
</ol>
<p>Another situation where the Part 2 is much simpler than Part 1 :)</p>
<p>Our parser isn’t too complicated; it’s similar to the parsers from the previous parts:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="ot">parseLine ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">Point</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>parseLine <span class="ot">=</span> (packUp <span class="op">=&lt;&lt;</span>)</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> <span class="fu">traverse</span> readMaybe</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> <span class="fu">words</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> clearOut (<span class="fu">not</span> <span class="op">.</span> <span class="fu">isDigit</span>)</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a> packUp [x,y] <span class="ot">=</span> <span class="dt">Just</span> <span class="op">$</span> <span class="dt">V2</span> x y</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a> packUp _ <span class="ot">=</span> <span class="dt">Nothing</span></span></code></pre></div>
<h3 id="day-6-benchmarks">Day 6 Benchmarks</h3>
<pre><code>&gt;&gt; Day 06a
benchmarking...
time 357.1 ms (266.7 ms .. 474.3 ms)
0.983 R² (0.979 R² .. 1.000 R²)
mean 342.2 ms (320.2 ms .. 364.1 ms)
std dev 25.62 ms (21.74 ms .. 28.96 ms)
variance introduced by outliers: 21% (moderately inflated)
* parsing and formatting times excluded
&gt;&gt; Day 06b
benchmarking...
time 83.35 ms (81.71 ms .. 88.06 ms)
0.995 R² (0.984 R² .. 1.000 R²)
mean 82.90 ms (81.98 ms .. 86.21 ms)
std dev 2.605 ms (400.7 μs .. 4.282 ms)
* parsing and formatting times excluded</code></pre>
</description>
<link>https://github.com/mstksg/advent-of-code-2018/blob/master/reflections.md#day-6</link>
<pubDate>Thu, 6 Dec 2018 01:00:00 EST</pubDate>
</item>
<item>
<title>Day 5</title>
<description><h2 id="day-5">Day 5</h2>
<!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day05.md`. If you want to edit this, edit
that file instead!
-->
<p><em><a href="https://adventofcode.com/2018/day/5">Prompt</a></em> / <em><a href="https://github.com/mstksg/advent-of-code-2018/blob/master/src/AOC/Challenge/Day05.hs">Code</a></em> / <em><a href="https://mstksg.github.io/advent-of-code-2018/src/AOC.Challenge.Day05.html">Rendered</a></em></p>
<p><strong>My write-up for this is actually [on my blog, here][d05b]!</strong> It involves my group theory/free group/group homomorphism based solution. That’s my main reflection, but I also had a method that I wrote <em>before</em>, that I would still like to preserve.</p>
<p>So, preserved here was my original solution involving <code>funkcyCons</code> and <code>foldr</code>:</p>
<p>One of the first higher-order functions you learn about in Haskill is <code>foldr</code>, which is like a “skeleton transformation” of a list.</p>
<p>That’s because in Haskell, a (linked) list is one of two constructors: nil (<code>[]</code>) or cons (<code>:</code>). The list <code>[1,2,3]</code> is really <code>1:(2:(3:[]))</code>.</p>
<p><code>foldr f z</code> is a function that takes a list replaces all <code>:</code>s with <code>f</code>, and <code>[]</code>s with <code>z</code>s:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a> [<span class="dv">1</span>,<span class="dv">2</span>,<span class="dv">3</span>] <span class="ot">=</span> <span class="dv">1</span> <span class="op">:</span> (<span class="dv">2</span> <span class="op">:</span> (<span class="dv">3</span> <span class="op">:</span> []))</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="fu">foldr</span> f z [<span class="dv">1</span>,<span class="dv">2</span>,<span class="dv">3</span>] <span class="ot">=</span> <span class="dv">1</span> <span class="ot">`f`</span> (<span class="dv">2</span> <span class="ot">`f`</span> (<span class="dv">3</span> <span class="ot">`f`</span> z ))</span></code></pre></div>
<p>This leads to one of the most famous identities in Haskell: <code>foldr (:) [] xs = xs</code>. That’s because if we go in and replace all <code>(:)</code>s with <code>(:)</code>, and replace all <code>[]</code>s with <code>[]</code>… we get back the original list!</p>
<p>But something we can also do is give <code>foldr</code> a “custom cons”. A custom cons that will go in place of the normal cons.</p>
<p>This problem is well-suited for such a custom cons: instead of normal <code>(:)</code>, we’ll write a custom cons that respects the rules of reaction: we can’t have two “anti-letters” next to each other:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">anti ::</span> <span class="dt">Char</span> <span class="ot">-&gt;</span> <span class="dt">Char</span> <span class="ot">-&gt;</span> <span class="dt">Bool</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>anti x y <span class="ot">=</span> <span class="fu">toLower</span> x <span class="op">==</span> <span class="fu">toLower</span> y <span class="op">&amp;&amp;</span> x <span class="op">/=</span> y</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="ot">funkyCons ::</span> <span class="dt">Char</span> <span class="ot">-&gt;</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">String</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>x <span class="ot">`funkyCons`</span> (y<span class="op">:</span>xs)</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> anti x y <span class="ot">=</span> xs</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="fu">otherwise</span> <span class="ot">=</span> x<span class="op">:</span>y<span class="op">:</span>xs</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>x <span class="ot">`funkyCons`</span> [] <span class="ot">=</span> [x]</span></code></pre></div>
<p>So, <code>foldr funkyCons []</code> will go through a list and replace all <code>(:)</code> (cons) with <code>funkyCons</code>, which will “bubble up” the reaction.</p>
<p>So, that’s just the entire part 1!</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">day05a ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>day05a <span class="ot">=</span> <span class="fu">length</span> <span class="op">.</span> <span class="fu">foldr</span> funkyCons []</span></code></pre></div>
<p>For part 2 we can just find the minimum length after trying out every character.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ot">day05b ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>day05b xs <span class="ot">=</span> <span class="fu">minimum</span> [ <span class="fu">length</span> <span class="op">$</span> <span class="fu">foldr</span> funkyCons [] (remove c xs)</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> c <span class="ot">&lt;-</span> [<span class="ch">&#39;a&#39;</span> <span class="op">..</span> <span class="ch">&#39;z&#39;</span>]</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a> ]</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a> remove c <span class="ot">=</span> <span class="fu">filter</span> ((<span class="op">/=</span> c) <span class="op">.</span> <span class="fu">toLower</span>)</span></code></pre></div>
<p>(Note that in the actual input, there is a trailing newline, so in practice we have to strip it from the input.)</p>
<h3 id="day-5-benchmarks">Day 5 Benchmarks</h3>
<pre><code>&gt;&gt; Day 05a
benchmarking...
time 19.59 ms (19.16 ms .. 20.18 ms)
0.995 R² (0.986 R² .. 0.999 R²)
mean 19.76 ms (19.47 ms .. 20.23 ms)
std dev 820.0 μs (509.1 μs .. 1.093 ms)
variance introduced by outliers: 13% (moderately inflated)
&gt;&gt; Day 05b
benchmarking...
time 88.26 ms (83.86 ms .. 91.77 ms)
0.997 R² (0.991 R² .. 1.000 R²)
mean 88.37 ms (87.20 ms .. 90.73 ms)
std dev 2.997 ms (1.642 ms .. 4.574 ms)</code></pre>
</description>
<link>https://github.com/mstksg/advent-of-code-2018/blob/master/reflections.md#day-5</link>
<pubDate>Wed, 5 Dec 2018 01:00:00 EST</pubDate>
</item>
<item>
<title>Day 4</title>
<description><h2 id="day-4">Day 4</h2>
<!--
This section is generated and compiled by the build script at ./Build.hs from
the file `./reflections/day04.md`. If you want to edit this, edit
that file instead!
-->
<p><em><a href="https://adventofcode.com/2018/day/4">Prompt</a></em> / <em><a href="https://github.com/mstksg/advent-of-code-2018/blob/master/src/AOC/Challenge/Day04.hs">Code</a></em> / <em><a href="https://mstksg.github.io/advent-of-code-2018/src/AOC.Challenge.Day04.html">Rendered</a></em></p>
<p>Day 4 was fun because it’s something that, on the surface, sounds like it requires a state machine to run through a stateful log and accumulate a bunch of time sheets.</p>
<p>However, if we think of the log as just a stream of tokens, we can look at at it as <em>parsing</em> this stream of tokens into time sheets – no state or mutation required.</p>
<p>First, the types at play:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Minute</span> <span class="ot">=</span> <span class="dt">Finite</span> <span class="dv">60</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">TimeCard</span> <span class="ot">=</span> <span class="dt">Map</span> <span class="dt">Minute</span> <span class="dt">Int</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Time</span> <span class="ot">=</span> <span class="dt">T</span> {<span class="ot"> _tYear ::</span> <span class="dt">Integer</span></span>