#!/usr/bin/env python3 import re, sys def dic(l): # get nice dictonary from line(s) ssf = l.split() # whitespace (' ' or '\n') separated fields dic = {a: b for a, b in (x.split(':') for x in ssf)} return dic def ok(dic): nec = 'byr iyr eyr hgt hcl ecl pid'.split() return all(n in dic for n in nec) def inrange(x, min, max): return x >= min and x <= max def goodheight(h): try: unit = h[-2:] n = int(h[:-2]) return unit == 'in' and inrange(n, 59, 76) or \ unit == 'cm' and inrange(n, 150, 193) except: return False def ok2(dic): return True if \ (ok(dic) and all(inrange(int(dic[y]), a, b) for y, a, b in (('byr', 1920, 2002), ('iyr', 2010, 2020), ('eyr', 2020, 2030))) and goodheight(dic['hgt']) and re.match('^#[0-9a-f]{6}$', dic['hcl']) and dic['ecl'] in 'amb blu brn gry grn hzl oth'.split() and re.match('^[0-9]{9}$', dic['pid'])) else False fn = sys.argv[1] if len(sys.argv) > 1 else 'input4' with open(fn) as f: pgphs = f.read().split('\n\n') ct = sum(ok(dic(p)) for p in pgphs) print(ct) ct = sum(ok2(dic(p)) for p in pgphs) print(ct)