Day 9 of Advent of Code is here and the task is the following. Take a list of numbers and find the first one, which is not the sum of two of the 25 preceding numbers.
my $window = 25; my @data = 'input.txt'.IO.lines.map: *.Int; say @data[($window ..^ @data).first({ @data[$_] != any(@data[$_ - $window ..^ $_].combinations(2).map: *.sum) })];
The numbers are read from a text file with IO.lines
, and are also mapped to integers. This mapping is not really necessary, but let us leave it here just for clarity.
Then, a tricky piece of code. Let me show it in a less concise way:
for $window ..^ @data -> $i { if @data[$i] != any(@data[$i - $window ..^ $i].combinations(2).map: *.sum) { say @data[$i]; last; } }
So, I am scanning the input array and test different two-number combination within a range $i - $window ..^ $I
, comparing their sums with the number at position $i
. The any-junction is used in comarison: @data[$i] != any(...)
. If there is at least one such combination, then we found the answer.
The second part of the task is to take the number found in the first part, and then find the first sequence of the numbers that, being added up, give that number. The expected result is the sum of the minimum and the maximum number in that sequence.
my $window = 25; my @data = 'input.txt'.IO.lines.map: *.Int; my $i = ($window ..^ @data).first({ @data[$_] != any(@data[$_ - $window ..^ $_].combinations(2).map: *.sum) }); my $n = @data[$i]; for ^$i -> $j { ([\,] @data[$j ..^ $i]).first: *.sum == $n andthen .sort andthen say(.[0] + .[*-1]) }
The first part of this code is similar to the previous solution with the only exception that I want to save both the index and the value itself.
In the second part, a few interesting Raku features are used. I believe, I used andthen
for the first time so far. It allows us to avoid temporary variables. If the result is Nil
, then we can safely ignore the code after andthen
as it will not be executed.
But before andthen
, there’s another construction that requires attention: [\,]
. This is a triangular metaoperator that creates a sequence of lists for the given range of input numbers: @data[$j ..^ $i]
. After we found such sequence that adds up to $n
, we sort it, compute the sum of the first and the last values, and we are done.
* * *
→ Browse the code on GitHub
→ See all blog posts on Advent of Code 2020
How cool!
I’ll make sure to check your solutions going forward. This is the first time I’m participating in the AoC and it’s being much fun. I’m programming in Perl and my son mostly in Rust. We’re comparing our solutions and teaching each other the nuts and cranks of our languages of choice.
I strive for succinctness (after all, succinctness is http://www.paulgraham.com/power.html) and I’m envying your solutions. 🙂
Kudos!