with open('data-2020-04.txt', 'r') as f:
inp = f.read()
# split by double end to separate passports
pp_split = inp.split("\n\n")
# separate items in each passport
pp_split = [x.replace("\n", " ") for x in pp_split]Advent of Code 2020 Day 4
— Day 4: Passport Processing —
We have to figure out some passport information from text based inputs.
Count the number of valid passports - those that have all required fields. Treat cid as optional. In your batch file, how many passports are valid?
Count how many fields there are in each set, and then how many have 7 (the correct number).
# mandatory items
mando = ['byr', 'iyr', 'eyr', 'hgt', 'hcl', 'ecl', 'pid']
# count how many are good
# this could be list comprehension, maybe
yes = []
for p in pp_split:
z = 0
for m in mando:
if m in p:
z += 1
yes.append(z)
# sum those up for part one
cnt = sum([y == 7 for y in yes])
cnt230
— Part Two —
Not only do we need to check for the fields, but we need to check for the content of the fields.
Count the number of valid passports - those that have all required fields and valid values. Continue to treat cid as optional. In your batch file, how many passports are valid?
# byr (Birth Year) - four digits; at least 1920 and at most 2002.
# iyr (Issue Year) - four digits; at least 2010 and at most 2020.
# eyr (Expiration Year) - four digits; at least 2020 and at most 2030.
# hgt (Height) - a number followed by either cm or in:
# If cm, the number must be at least 150 and at most 193.
# If in, the number must be at least 59 and at most 76.
# hcl (Hair Color) - a # followed by exactly six characters 0-9 or a-f.
# ecl (Eye Color) - exactly one of: amb blu brn gry grn hzl oth.
# pid (Passport ID) - a nine-digit number, including leading zeroes.
# cid (Country ID) - ignored, missing or not.
import re
def check_items(p, m):
# result for function
result = True
# get the required thing
patt = m + ':(#?[0-9a-z]+)'
itm = re.search(patt, p)
# print(p)
# print(m)
# print(itm)
# get out straight away if the field is not there
if itm is None:
result = False
else:
itm = itm.group(1)
try:
ii = int(re.search('\\d+', itm).group(0))
except:
ii = 0
# check it against rules
if m == 'byr':
result = (1920 <= ii and ii <= 2002)
elif m == 'iyr':
result = (2010 <= ii and ii <= 2020)
elif m == 'eyr':
result = (2020 <= ii and ii <= 2030)
elif m == 'hgt':
if "in" in itm:
result = (59 <= ii and ii <= 76)
elif "cm" in itm:
result = (150 <= ii and ii <= 193)
else:
result = False
elif m == 'hcl':
hh = "#[0-9a-f]{6}"
res = re.search(hh, itm)
if res is None: result = False
elif m == 'ecl':
result = (itm in ['amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth',])
elif m == 'pid':
result = len(itm) == 9 and itm.isnumeric()
# print(result)
# return, of course
return resultUse the above function
# loop through the list
# loop through items
yes = []
for p in pp_split:
p = p.lower()
z = True
for m in mando:
y = check_items(p, m)
z = z and y
yes.append(z)
# part two answer
cnt = sum([y for y in yes])
cnt156