2020-12-2

Created on Monday, December 23, 2024.

Day 2 Part 1 - Validating Passwords

import pytest
import ipytest
ipytest.autoconfig()

We start by parsing the string. Given it's <n>-<n> <c>: <l> we can split it by spaces, and then parse each subset

def parse(s):
    (m,c,l) = s.split()
    mn,mx = [int(i) for i in m.split('-')]
    return (mn,mx,c[0],l)
example1 = "1-3 a: abcde"
actual = parse(example1)
assert (1,3,"a","abcde") == actual
mn,mx,c,l = actual

Now we have to be able to test whether the password in l is actually valid It's only valid if it contains at least mn occurences of c, and no more than mx occurences.

def is_valid(mn,mx,c,l):
    occurrences = l.count(c)
    return mx >= occurrences >= mn
assert is_valid(mn,mx,c,l)

We need to count them, this should be simple, but lets make a function to do it anyway

def count_passwords(lines, validator):
    total = 0
    for line in lines:
        mn,mx,c,l = parse(line)
        if validator(mn,mx,c,l):
            total += 1
    return total

So let's count the number of correct passwords in the sample

sample = ("1-3 a: abcde",
"1-3 b: cdefg",
"2-9 c: ccccccccc")

assert 2 == count_passwords(sample, is_valid)

The actual data

input = open('day2.txt').readlines()
count_passwords(input, is_valid)

586

Part 2

Oh no, we are interpreting the password policy wrong, let's write a new function that confirms the real policy mn and mx are in fact p1 and p2, positions in the password l. the character c must appear at either of p1 and p2, but not at both and not at neither

def is_valid_position(p1,p2,c,l):
    if l[p1-1] == c and l[p2-1] != c:
        return True
    if l[p1-1] != c and l[p2-1] == c:
        return True
    return False
sample = ("1-3 a: abcde",
          "1-3 a: cbade",
"1-3 b: cdefg",
"2-9 c: ccccccccc")

assert 2 == count_passwords(sample, is_valid_position)

Now let's run that on the original password file

count_passwords(input, is_valid_position)

352

Next

2020-12-3

Previous

2020-12-1