Pages

2020/12/08

Advent of Code 2020 - Day 2

 This is a running series of posts on the Advent of Code 2020. The introductory post has the details, including the accompanying GitHub repo, in case you reached this directly.

Still on the warm-up phase, but we are already bringing in regular expressions. The patterns are easy enough to solve with basic string methods, but the regular expressions make it much clearer.

Part 1

We get a file in which each line is a constraint specification followed by a word, and we are asked to count how many lines are consistent (i.e. the word is valid according to the constraint). Each line is of the form:

n-m x: word

Here, n and m are integer numbers, and x is any single letter. The constraint is that the letter given by x must appear between n and m times in word.

So we have two tasks:

  1. Parse the file into paired costraint specifications and words
  2. Evaluate validity of each pair
The first task is straightforward matching on each line the regular expression:

(?P<min>\d+)-(?P<max>\d+) (?P<letter>[a-z]): (?P<pwd>[a-z]+)

We can then use the named groups to retrieve each relevant piece of information (and cast min and max to ints). With this small modification we can directly use the dictionary that we get from match.groupdict() as the specification.

Validation is equally straightforward. We can use a generator expression to compress counting the number of times the letter appears in the word while making it more readable than the equivalent loop:

sum(1 for c in spec['pwd'] if c == spec['letter'])

Compare it with:

total = 0
for c in spec['pwd']:
    if c == spec['letter']:
        total += 1

Part 2

For this part the validation rules change, so we keep the same parsing. The new validation rule is that the letter must appear in exactly one of the two given positions (interpreting n and m as 1-based indices).

The first gotcha is the 1-based indices. Not difficult, but easy to forget. Otherwise the validation seems to be quite direct as a XOR of the conditions that the letter at each of the two positions be the given letter:

(pwd[pos1] == letter) != (pwd[pos2] == letter)

However, this can lead to out-of-bounds errors, so there is some accounting to do before reaching this. If the word is so short that the first position is not even included, then it is not valid; if only the first position is within the word, the word is valid if the letter at that position is the given letter. If both are included, we fall back to the XOR.

No comments:

Post a Comment