π π»π Day 1: Trebuchet?! ββ
We are all well aware (or should be) of the biggest problem humanity has ever faced: the global climate crisis. And it seems that Advent of Code wants to align as well: the excuse for this year’s adventure is a problem with the global snow production system. Well, what should we do?
The input is a calibration document that has been amended in a very creative way: it should contain only numbers, but some of them are spelled out with letters.
1abc2
pqr3stu8vwx
a1b2c3d4e5f
treb7uchet
The first task is relatively simple: for each row, we must reconstruct the number consisting of the first and last digits found on that row. So, in the example: 12
, 38
, 15
, 77
. The last number is repeated because the first and last digits coincide.
Itβs a one-liner without too much fuss1:
#[[{1, -1}]]& /* FromDigits /@
StringCases[StringSplit[day1, "\n"],
x: DigitCharacter :> ToExpression@x] // Total
Steps:
- The
StringCases[..., x: DigitCharacter :> ToExpression@x]
is doing the extraction part: any digit character (0-9) is converted into an expression β that is, an integer, in this case. The result will be a list in which each element contains the digits found on a certain row. #[[{1, -1}]]& /* FromDigits /@
itβs a single function mapped onto the list of lists obtained above. The symbol/*
is the right composition operator. It means that its right operand will be applied on the result obtained after applying its left operand.#[[{1, -1}]]&
takes the first and last elements. If itβs a single item list, it takes the element twice.FromDigits
constructs an integer from the list of its decimal digits.- The last bit is the map operator
/@
.
- Lastly, we compute the total of the reconstructed numbers.
Part 2
Obviously, something is wrong; it cannot be that simple. We also have to consider the digits 0 to 9 written in letters. And we have to consider all of them. What does that mean? For example, oneight
is 18
. We cannot simply replace one β 1
, two β 2
, etc. because we would miss the adjacent overlapping digits.
First, we need to extract all the digits from a certain string. Only then we replace the various one
with 1
, two
with 2
, and so on.
The replacement rules are easy:
numberRules = Thread[IntegerName /@ Range[9] -> Range[9]]
Now, my function that parses a string and extracts the digits is:
ToExpression /@ (StringTake[s,
StringPosition[s,
Join[ToString /@ Range[9], IntegerName[Range[9]]]]] /.
numberRules)
- Find the positions (
{start, end}
) of the digits 0-9, either as a number or in letters. - Extracts all portions of the string that correspond to the positions found in step 1.
- At this point, it can apply
numberRules
and convert everything to numeric digits.ToExpression
does the same thing as before: it normalizes strings representing numbers into integers.
The final solution is very similar to part 1, just with the insertion of the parsing function:
#[[{1, -1}]] &/*FromDigits /@
findLetterDigits /@ StringSplit[day1, "\n"] // Total
findLetterDigits
is the name I gave to the function.
I rated this first day 4 out of 10 in terms of difficulty. Pretty uncommon that part two of Day 1 is so difficult. Someone pointed out to me that it might have been on purpose to discourage a blatant use of AI to enter the global leaderboard.
I’ll collect my solutions in this public notebook on Wolfram Cloud.
-
By
dayN
I will henceforth denote the raw input of a given day, as it can be downloaded from Advent of Code website. ↩︎