2020-12-02 - Password Philosophy
(original .ipynb)
Day 2 puzzle input is a list of password policy and password pairs (mine is here). Part 1 involves returning the number of passwords valid according to the policy (where x-y c: pass means "between x and y occurrences of the character c are in password pass"). Part 2 is broadly similar, but with a with slightly different policy logic (x-y c: pass means "either pass[x-1]==c XOR pass[y-1]==c")
def parse_line(line):
policy, password = line.split(": ")
minmax_letter, letter = policy.split(" ")
min_letter_str, max_letter_str = minmax_letter.split("-")
return (int(min_letter_str), int(max_letter_str), letter, password)
def is_password_valid(min_letter, max_letter, letter, password):
occurrences = len([ c for c in password if c == letter ])
return occurrences >= min_letter and occurrences <= max_letter
test_input_str = """1-3 a: abcde
1-3 b: cdefg
2-9 c: ccccccccc"""
real_input_str = open("puzzle_input/day2.txt").read()
def count_valid_passwords(input_str):
parsed_passwords = [ parse_line(l) for l in input_str.split("\n") ]
password_validity = [ p for p in parsed_passwords if is_password_valid(*p) ]
return len(password_validity)
assert 2 == count_valid_passwords(test_input_str)
count_valid_passwords(real_input_str)
620
def is_password_valid_new(position_one, position_two, letter, password):
# 0-index the positions
position_one -= 1
position_two -= 1
letter_one_match = password[position_one] == letter
letter_two_match = password[position_two] == letter
return (letter_one_match != letter_two_match) and (letter_one_match or letter_two_match)
def count_valid_passwords_new(input_str):
parsed_passwords = [ parse_line(l) for l in input_str.split("\n") ]
password_validity = [ p for p in parsed_passwords if is_password_valid_new(*p) ]
return len(password_validity)
assert 1 == count_valid_passwords_new(test_input_str)
count_valid_passwords_new(real_input_str)
727