Let’s go for Day 2! As before, all my solutions are available in a Git repository: https://git.sr.ht/~schnouki/advent-of-code.
Today’s puzzle is about password policies. Our input is made of line with a simple structure: we can parse them with a simple regular expression, and store the result in a dataclass. (We could also use a namedtuple or even a tuple, but using a class we can add methods and properties, which is often useful.)
from dataclasses import dataclass import re RE_LINE = re.compile(r"^(?P<v1>\d+)-(?P<v2>\d+) (?P<char>\w): (?P<password>.+)$") @dataclass class Password: v1: int v2: int char: str password: str @classmethod def from_line(cls, line: str) -> "Password": mtch = RE_LINE.match(line) return cls( v1=int(mtch["v1"]), v2=int(mtch["v2"]), char=mtch["char"], password=mtch["password"], )
Now, let’s solve this puzzle.
A password is valid if the character in the password policy is present the right number of times in the password. OK, not a good password policy for the real world, but enough for the North Pole 😅
It’s probable tempting to use a regular expression here… but it’s also not needed at all: we can just use the string
count() method and check if it’s in the right range.
Let’s add this as a property in our dataclass:
@dataclass class Password: ... @property def is_valid_p1(self) -> bool: return self.v1 <= self.password.count(self.char) <= self.v2
Now we just have to count how many times it’s valid for our input.
data = [Password.from_line(line) for line in data.splitlines()] result = sum(1 for password in data if password.is_valid_p1)
Done. 0.25 ms.
Different rule: this time we need to check if the character from the policy is present in only one of the 2 given positions. One, or the other, but not both: did someone say XOR?
@dataclass class Password: ... @property def is_valid_p2(self) -> bool: ok1 = self.password[self.v1 - 1] == self.char ok2 = self.password[self.v2 - 1] == self.char return ok1 ^ ok2 data = [Password.from_line(line) for line in data.splitlines()] result = sum(1 for password in data if password.is_valid_p2)
Done as well. 0.23 ms.
That was easy. See you tomorrow! 👋