tvl-depot/users/Profpatsch/advent-of-code/2020/04/main.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

105 lines
2.4 KiB
Python
Raw Normal View History

import sys
import itertools
import re
import pprint
def get_entry(fd):
def to_dict(keyval):
res = {}
for (k, v) in keyval:
assert k not in res
res[k] = v
return res
res = []
for line in fd:
if line == "\n":
yield to_dict(res)
res = []
else:
line = line.rstrip()
items = line.split(" ")
for i in items:
res.append(i.split(":", maxsplit=2))
def val_hgt(hgt):
m = re.fullmatch(r'([0-9]+)(cm|in)', hgt)
if m:
(i, what) = m.group(1,2)
i = int(i)
if what == "cm":
return i >= 150 and i <= 193
elif what == "in":
return i >= 59 and i <= 76
else:
return False
required_fields = [
{ "name": "byr",
"check": lambda s: int(s) >= 1920 and int(s) <= 2002
},
{ "name": "iyr",
"check": lambda s: int(s) >= 2010 and int(s) <= 2020
},
{ "name": "eyr",
"check": lambda s: int(s) >= 2020 and int(s) <= 2030,
},
{ "name": "hgt",
"check": lambda s: val_hgt(s)
},
{ "name": "hcl",
"check": lambda s: re.fullmatch(r'#[0-9a-f]{6}', s)
},
{ "name": "ecl",
"check": lambda s: re.fullmatch(r'amb|blu|brn|gry|grn|hzl|oth', s)
},
{ "name": "pid",
"check": lambda s: re.fullmatch(r'[0-9]{9}', s)
},
# we should treat it as not required
# "cid"
]
required_dict = {}
for f in required_fields:
required_dict[f["name"]] = f
def validate(keyval):
if keyval[0] not in required_dict:
return { "ok": keyval }
if required_dict[keyval[0]]["check"](keyval[1]):
return { "ok": keyval }
else:
return { "validation": keyval }
def all_fields(entry):
missing = []
for r in required_dict:
if r not in e:
missing.append(r)
if missing == []:
return { "ok": entry }
else:
return { "missing": missing }
count=0
for e in get_entry(sys.stdin):
a = all_fields(e)
if a.get("ok", False):
res = {}
bad = False
for keyval in e.items():
r = validate(keyval)
if r.get("validation", False):
bad = True
res[keyval[0]] = r
if bad:
pprint.pprint({ "validation": res })
else:
pprint.pprint({ "ok": e })
count = count+1
else:
pprint.pprint(a)
print(count)