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