commit 6fbdad0ba52401ad8b286099882b60ab07701dec
parent 4d9011d5fcbe2e275a11b2688b261426b3bf50df
Author: Luís Ferreira <contact@lsferreira.net>
Date: Fri, 17 Dec 2021 23:09:19 +0000
posts: Add 'Solution in D for Advent of Code 2021, Day 4'
Signed-off-by: Luís Ferreira <contact@lsferreira.net>
Diffstat:
1 file changed, 87 insertions(+), 0 deletions(-)
diff --git a/content/posts/zet-5-aoc-2021-04.md b/content/posts/zet-5-aoc-2021-04.md
@@ -0,0 +1,87 @@
+---
+title: 'Zettelkasten #5: Solution in D for Advent of Code 2021, Day 4'
+date: '2021-12-17T22:04:00+01:00'
+tags: ['zettelkasten', 'zet', 'dlang', 'aoc', 'aoc2021', 'adventofcode']
+description: "This post describes my solution in the D programming language for
+the 4th puzzle of the Advent of Code 2021."
+---
+
+## The challenge
+
+> You're already almost 1.5km (almost a mile) below the surface of the ocean,
+> already so deep that you can't see any sunlight. What you can see, however,
+> is a giant squid that has attached itself to the outside of your submarine.
+>
+> Maybe it wants to play bingo?
+>
+> Bingo is played on a set of boards each consisting of a 5x5 grid of numbers.
+> Numbers are chosen at random, and the chosen number is marked on all boards
+> on which it appears. (Numbers may not appear on all boards.) If all numbers
+> in any row or any column of a board are marked, that board wins. (Diagonals
+> don't count.)
+>
+> [...]
+>
+> To guarantee victory against the giant squid, figure out which board will win
+> first. What will your final score be if you choose that board?
+
+You can read the challenge more in depth,
+[here](https://adventofcode.com/2021/day/4).
+
+## Part 1
+
+### Full solution
+
+```d
+auto input = [stdin.byLineCopy().array].map!(a => [ // input
+ a.front.splitter(",").map!(to!long).array, // parse numbers
+ a[1..$].map!`a.splitter(" ").filter!"!a.empty".map!(to!long)` // parse cards
+ .joiner.array]).front;
+immutable ncards = input[1].length / 25; // calc number of cards
+foreach(pos, i; input[0]) foreach(c; 0..ncards) { // for each number & card
+ foreach(n; 0..25) if(input[1][c*25 + n] == i) input[1][c*25 + n] = -1; // set matching numbers
+ auto e = evenChunks(input[1][c*25..c*25+25],5).array; // construct card RoR
+ foreach(el; zip(e, e.dup.transposed)) if(findSkip(el[0], repeat(-1L,5)) // find row
+ || findSkip(el[1], repeat(-1L,5))) { // find column
+ writeln(input[1][c*25..c*25+25].filter!"a != -1".sum * i); // calculate result
+ return; // hang
+ }
+}
+```
+
+## Part 2
+
+> On the other hand, it might be wise to try a different strategy: let the
+> giant squid win.
+>
+> You aren't sure how many bingo boards a giant squid could play at once, so
+> rather than waste time counting its arms, the safe thing to do is to figure
+> out which board will win last and choose that one. That way, no matter which
+> boards it picks, it will win for sure.
+>
+> [...]
+>
+> Figure out which board will win last. Once it wins, what would its final
+> score be?
+
+### Full solution
+
+```d
+auto input = [stdin.byLineCopy().array].map!(a => [ // input
+ a.front.splitter(",").map!(to!long).array, // parse numbers
+ a[1..$].map!`a.splitter(" ").filter!"!a.empty".map!(to!long)` // parse cards
+ .joiner.array]).front;
+immutable ncards = input[1].length / 25; // calc number of cards
+bool[] winners = new bool[ncards];
+foreach(pos, i; input[0]) foreach(c; 0..ncards) { // for each number & card
+ foreach(n; 0..25) if(input[1][c*25 + n] == i) input[1][c*25 + n] = -1; // set matching numbers
+ auto e = evenChunks(input[1][c*25..c*25+25],5).array; // construct card RoR
+ foreach(el; zip(e, e.dup.transposed)) if(findSkip(el[0], repeat(-1L,5)) // find row
+ || findSkip(el[1], repeat(-1L,5))) { // find column
+ winners[c] = true; if(winners.all) { // fill winners list & check
+ writeln(input[1][c*25..c*25+25].filter!"a != -1".sum * i); // calculate result
+ return; // hang
+ }
+ }
+}
+```