diff --git a/2020/README.md b/2020/README.md index 97d9f15..e816dd1 100644 --- a/2020/README.md +++ b/2020/README.md @@ -8,4 +8,5 @@ https://adventofcode.com/2020/ |---|--------|---------|------| | 1 | `**` | `**` | | | 2 | `**` | | `**` | -| 3 | `**` | | | +| 3 | `**` | `**` | | +| 4 | `**` | | | diff --git a/2020/day4/day4.py b/2020/day4/day4.py new file mode 100755 index 0000000..4571982 --- /dev/null +++ b/2020/day4/day4.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python + +def within(a, b, x): + return a <= x <= b + +PASSPORT_FIELDS = { + 'byr': lambda s: len(s) == 4 and within(1920, 2002, int(s)), + 'iyr': lambda s: len(s) == 4 and within(2010, 2020, int(s)), + 'eyr': lambda s: len(s) == 4 and within(2020, 2030, int(s)), + 'hgt': lambda s: within(*{'cm': (150, 193), 'in': (59, 76)}[s[-2:]], int(s[:-2])), + 'hcl': lambda s: len(s) == 7 and s[0] == '#' and all(c in "0123456789abcdef" for c in s[1:]), + 'ecl': lambda s: s in ('amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth'), + 'pid': lambda s: len(s) == 9 and s.isdigit(), +} + +def parse_passport(line): + d = {} + for entry in line.split(): + k, v = entry.split(':', maxsplit=1) + d[k] = v + return d + +def check_passport_fields_exist(passport): + return set(PASSPORT_FIELDS.keys()) <= set(passport.keys()) + +def check_passport_fields_valid(passport): + for name, spec in PASSPORT_FIELDS.items(): + try: + valid = spec(passport[name]) + except: + valid = False + + if not valid: + return False + return True + +def split_on(f, it): + current_part = [] + + for el in it: + if f(el): + yield current_part + current_part = [] + else: + current_part.append(el) + +if __name__ == '__main__': + with open('input.txt', 'r') as f: + lines = [line.strip() for line in f.readlines()] + + specs = list(' '.join(lines) for lines in split_on(lambda l: l == "", lines)) + + passports = [parse_passport(spec) for spec in specs] + print(len(list(filter(check_passport_fields_exist, passports)))) + print(len(list(filter(check_passport_fields_valid, passports))))