2020-12-04 23:10:35 +01:00
|
|
|
import re
|
|
|
|
|
2020-12-05 00:04:09 +01:00
|
|
|
input_file = "input.txt"
|
2020-12-04 23:10:35 +01:00
|
|
|
|
|
|
|
height_re = re.compile(r'^([0-9]+)(in|cm)$')
|
|
|
|
passport_id_re = re.compile(r'^[0-9]{9}$')
|
|
|
|
color_re = re.compile(r'^#[0-9a-f]{6}$')
|
|
|
|
|
2020-12-05 00:04:09 +01:00
|
|
|
|
2020-12-04 23:10:35 +01:00
|
|
|
def check_limits(to_test, min_valid, max_valid):
|
|
|
|
return False if (to_test < min_valid or to_test > max_valid) else True
|
|
|
|
|
2020-12-05 00:04:09 +01:00
|
|
|
|
2020-12-04 23:10:35 +01:00
|
|
|
def validate_passport(record):
|
|
|
|
for field in record:
|
|
|
|
if field[0] == "byr":
|
|
|
|
if not check_limits(int(field[1]), 1920, 2002):
|
|
|
|
return False
|
|
|
|
elif field[0] == "iyr":
|
|
|
|
if not check_limits(int(field[1]), 2010, 2020):
|
|
|
|
return False
|
|
|
|
elif field[0] == "eyr":
|
|
|
|
if not check_limits(int(field[1]), 2020, 2030):
|
|
|
|
return False
|
|
|
|
elif field[0] == "hgt":
|
|
|
|
regex_match = height_re.match(field[1])
|
|
|
|
if not regex_match:
|
|
|
|
return False
|
2020-12-05 00:04:09 +01:00
|
|
|
if regex_match.groups()[1] == "cm" and not check_limits(int(regex_match.groups()[0]), 150, 193):
|
2020-12-04 23:10:35 +01:00
|
|
|
return False
|
2020-12-05 00:04:09 +01:00
|
|
|
elif regex_match.groups()[1] == "in" and not check_limits(int(regex_match.groups()[0]), 59, 76):
|
2020-12-04 23:10:35 +01:00
|
|
|
return False
|
|
|
|
elif field[0] == "hcl":
|
|
|
|
regex_match = color_re.match(field[1])
|
|
|
|
if not regex_match:
|
|
|
|
return False
|
|
|
|
elif field[0] == "ecl":
|
2020-12-05 00:04:09 +01:00
|
|
|
if field[1] not in ["amb", "blu", "brn", "gry", "grn", "hzl", "oth"]:
|
2020-12-04 23:10:35 +01:00
|
|
|
return False
|
|
|
|
elif field[0] == "pid":
|
|
|
|
regex_match = passport_id_re.match(field[1])
|
|
|
|
if not regex_match:
|
|
|
|
return False
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
records = [[]]
|
|
|
|
|
|
|
|
valid_passports = 0
|
|
|
|
|
|
|
|
with open(input_file) as passports:
|
|
|
|
line = passports.readline()
|
|
|
|
current_index = 0
|
|
|
|
while line:
|
|
|
|
if line == "\n":
|
|
|
|
records.append([])
|
|
|
|
current_index += 1
|
|
|
|
line = passports.readline()
|
|
|
|
continue
|
|
|
|
|
2020-12-05 00:04:09 +01:00
|
|
|
# rstrip() strips the string from end of line characters et alia.
|
2020-12-04 23:10:35 +01:00
|
|
|
for raw_entry in line.rstrip().split(" "):
|
2020-12-05 00:04:09 +01:00
|
|
|
# Split the different fields, then split them in (key,value) tuples
|
2020-12-04 23:10:35 +01:00
|
|
|
records[current_index].append(tuple(raw_entry.split(":")))
|
|
|
|
|
|
|
|
line = passports.readline()
|
|
|
|
|
|
|
|
for record in records:
|
|
|
|
if len(record) == 8:
|
|
|
|
if validate_passport(record):
|
|
|
|
valid_passports += 1
|
|
|
|
if len(record) == 7:
|
|
|
|
is_north_pole_credential = True
|
|
|
|
for field in record:
|
|
|
|
if field[0] == "cid":
|
|
|
|
is_north_pole_credential = False
|
|
|
|
break
|
|
|
|
if is_north_pole_credential and validate_passport(record):
|
|
|
|
valid_passports += 1
|
|
|
|
|
2020-12-05 00:04:09 +01:00
|
|
|
print(f"There are {valid_passports} valid passports out of {len(records)}")
|