94 lines
2.3 KiB
Python
94 lines
2.3 KiB
Python
|
def read_file():
|
||
|
with open("input.txt","r") as f:
|
||
|
# first, we split into separate passports.
|
||
|
raw_passports = f.read().split('\n\n')
|
||
|
# then, we split each passport into fields, by newline or space.
|
||
|
split_passports = []
|
||
|
for passport in raw_passports:
|
||
|
split_passports.append(passport.split())
|
||
|
# finally, we convert to a dictionary.
|
||
|
passports = []
|
||
|
for passport in split_passports:
|
||
|
passport_dict = {}
|
||
|
for field in passport:
|
||
|
key, value = field.split(':')
|
||
|
passport_dict[key] = value
|
||
|
passports.append(passport_dict)
|
||
|
# all passports should now be normalized to dicts.
|
||
|
return passports
|
||
|
|
||
|
def valid(passport):
|
||
|
required_fields = ['byr', 'iyr', 'eyr', 'hgt', 'hcl', 'ecl', 'pid']
|
||
|
for field in required_fields:
|
||
|
if field not in passport:
|
||
|
return False
|
||
|
return True
|
||
|
|
||
|
def part1(passports):
|
||
|
valid_passports = 0
|
||
|
for passport in passports:
|
||
|
if valid(passport):
|
||
|
valid_passports += 1
|
||
|
return valid_passports
|
||
|
|
||
|
def valid_data(passport):
|
||
|
# first, we need to check if all required fields are present.
|
||
|
if not valid(passport):
|
||
|
return False
|
||
|
# byr must be four digits 1920 - 2002
|
||
|
byr = int(passport['byr'])
|
||
|
if not (1920 <= byr <= 2002):
|
||
|
return False
|
||
|
# iyr must be four digits 2010 - 2020
|
||
|
iyr = int(passport['iyr'])
|
||
|
if not (2010 <= iyr <= 2020):
|
||
|
return False
|
||
|
#eyr must be four digits 2020 - 2030
|
||
|
eyr = int(passport['eyr'])
|
||
|
if not (2020 <= eyr <= 2030):
|
||
|
return False
|
||
|
# hgt must be 150-193cm or 59-76in
|
||
|
hgt = passport['hgt']
|
||
|
if hgt.endswith('cm'):
|
||
|
hgt = int(hgt[:-2])
|
||
|
if not (150 <= hgt <= 193):
|
||
|
return False
|
||
|
elif hgt.endswith('in'):
|
||
|
hgt = int(hgt[:-2])
|
||
|
if not (59 <= hgt <= 76):
|
||
|
return False
|
||
|
else:
|
||
|
return False
|
||
|
# hcl must be hexcode
|
||
|
hcl = passport['hcl']
|
||
|
import re
|
||
|
if not re.match(r'^#(?:[0-9a-fA-F]{1,2}){3}$', hcl):
|
||
|
return False
|
||
|
# ecl must be exactly one of: amb blu brn gry grn hzl oth.
|
||
|
valid_ecls = ['amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth']
|
||
|
ecl = passport['ecl']
|
||
|
if ecl not in valid_ecls:
|
||
|
return False
|
||
|
# pid must be 9 digits long
|
||
|
pid = passport['pid']
|
||
|
if len(pid) != 9:
|
||
|
return False
|
||
|
# cid is ignored
|
||
|
return True
|
||
|
|
||
|
|
||
|
def part2(passports):
|
||
|
valid_passports = 0
|
||
|
for passport in passports:
|
||
|
if valid_data(passport):
|
||
|
valid_passports += 1
|
||
|
return valid_passports
|
||
|
|
||
|
def main():
|
||
|
passports = read_file()
|
||
|
print(f'{part1(passports)=}')
|
||
|
print(f'{part2(passports)=}')
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
main()
|