92 lines
2.4 KiB
Python
92 lines
2.4 KiB
Python
import aoclib
|
|
import re
|
|
|
|
DAY = 4
|
|
TEST_SOLUTION_PART1 = 10
|
|
TEST_SOLUTION_PART2 = 6
|
|
|
|
required_fields = ['byr', 'iyr', 'eyr', 'hgt', 'hcl', 'ecl', 'pid'] # 'cid' possible, but ignored
|
|
re_color_match = re.compile(r'#[a-z0-9]{6}')
|
|
|
|
|
|
def getPassportData(passport_line):
|
|
data = {}
|
|
pairs = passport_line.split()
|
|
for pair in pairs:
|
|
key, value = pair.split(':')
|
|
data[key] = value
|
|
|
|
return data
|
|
|
|
|
|
def verifyPassportData(passport_data, verify_data=False):
|
|
for field in required_fields:
|
|
if field not in passport_data:
|
|
return False
|
|
|
|
if not verify_data:
|
|
return True
|
|
|
|
try:
|
|
birth_year = int(passport_data['byr'])
|
|
issue_year = int(passport_data['iyr'])
|
|
expire_year = int(passport_data['eyr'])
|
|
height = int(passport_data['hgt'][:-2])
|
|
int(passport_data['pid'])
|
|
except ValueError:
|
|
return False
|
|
|
|
# BYR
|
|
if len(passport_data['byr']) != 4 or birth_year < 1920 or birth_year > 2002:
|
|
return False
|
|
|
|
# IYR
|
|
if len(passport_data['iyr']) != 4 or issue_year < 2010 or issue_year > 2020:
|
|
return False
|
|
|
|
# EYR
|
|
if len(passport_data['eyr']) != 4 or expire_year < 2020 or expire_year > 2030:
|
|
return False
|
|
|
|
# HGT
|
|
if passport_data['hgt'][-2:] not in ['cm', 'in']:
|
|
return False
|
|
elif passport_data['hgt'].endswith('cm') and (height < 150 or height > 193):
|
|
return False
|
|
elif passport_data['hgt'].endswith('in') and (height < 59 or height > 76):
|
|
return False
|
|
|
|
# HCL
|
|
if not re.match(re_color_match, passport_data['hcl']):
|
|
return False
|
|
|
|
# ECL
|
|
if passport_data['ecl'] not in ['amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth']:
|
|
return False
|
|
|
|
# PID
|
|
if len(passport_data['pid']) != 9:
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
def part1(test_mode=False):
|
|
valid = 0
|
|
for passport_line in aoclib.getMultiLineInputAsArray(day=4, join_char=" ", test=test_mode):
|
|
passport_data = getPassportData(passport_line)
|
|
if verifyPassportData(passport_data):
|
|
valid = valid + 1
|
|
|
|
return valid
|
|
|
|
|
|
def part2(test_mode=False):
|
|
valid = 0
|
|
for passport_line in aoclib.getMultiLineInputAsArray(day=4, join_char=" ", test=test_mode):
|
|
passport_data = getPassportData(passport_line)
|
|
if verifyPassportData(passport_data, True):
|
|
valid = valid + 1
|
|
|
|
return valid
|