about summary refs log tree commit diff
path: root/users/Profpatsch/advent-of-code/2020/04/main.py
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)