advent-of-code/2020-python/solutions/day_04.py

98 lines
2.3 KiB
Python
Raw Normal View History

2021-11-01 16:40:46 +01:00
import re
from solutions import BaseSolution
class Solution(BaseSolution):
input_file = "04.txt"
def __str__(self):
return "Day 4: Passport Processing"
def parse_input(self, data):
return [f"{' '.join(sorted(pp.split()))} " for pp in data.split("\n\n")]
def solve(self, puzzle_input):
return sum(map(has_required_fields, puzzle_input))
def solve_again(self, puzzle_input):
return sum(
map(
lambda pp: has_required_fields(pp) and has_valid_values(pp),
puzzle_input,
)
)
def has_required_fields(data):
return all(
f"{k}:" in data for k in ["byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid"]
)
def has_valid_values(data):
valid_hgt = lambda d: valid_height(d)
valid_byr = lambda d: valid_range(d, "byr", 1920, 2002)
valid_iyr = lambda d: valid_range(d, "iyr", 2010, 2020)
valid_eyr = lambda d: valid_range(d, "eyr", 2020, 2030)
valid_hcl = lambda d: valid_hex_color(data)
valid_ecl = lambda d: exactly_1_valid_eye_color(data)
valid_pid = lambda d: valid_password_id(d)
return all(
validator(data)
for validator in [
valid_byr,
valid_iyr,
valid_eyr,
valid_hgt,
valid_hcl,
valid_ecl,
valid_pid,
]
)
def valid_height(data):
values = re.findall(r"hgt:([\d+?]{2,3})(in|cm) ", data)
if len(values) != 1:
return False
value, unit = values[0]
if unit == "in":
return int(value) in range(59, 77)
elif unit == "cm":
return int(value) in range(150, 194)
return False
def valid_range(data, k, a, b):
value = re.search(k + r":([\d]{4}) ", data)
if not value:
return False
return int(value[1]) in range(a, b + 1)
def valid_hex_color(data):
return re.search(r"hcl:#([0-9abcdef]{6}) ", data) != None
def exactly_1_valid_eye_color(data):
return (
sum(
f"ecl:{cl} " in data
for cl in ["amb", "blu", "brn", "gry", "grn", "hzl", "oth"]
)
== 1
)
def valid_password_id(data):
value = re.search(r"pid:([\d+?]{9}) ", data)
if not value:
return False
return True
if __name__ == "__main__":
solution = Solution()
solution.show_results()