1
0
Fork 0

formatting and cosmetic updates to 2020.

This commit is contained in:
Gabe Venberg 2026-04-17 16:21:34 +02:00
parent 84c4cf9991
commit cd75e58f77
28 changed files with 320 additions and 287 deletions

View file

@ -1,10 +1,10 @@
#! /usr/bin/env python3
import pathlib
import sys
import re
import sys
from dataclasses import dataclass
from pprint import pprint
@dataclass
class Passport:
@ -17,105 +17,131 @@ class Passport:
passportId: str | None
countryId: str | None
def regexUnwrap(match, group:int)->str | None:
def regexUnwrap(match, group: int) -> str | None:
return match[group] if match is not None else None
def parse(puzzle_input: str)->list[Passport]:
def parse(puzzle_input: str) -> list[Passport]:
"""Parse input"""
rawRecords = [i.replace('\n', ' ') for i in puzzle_input.split('\n\n')]
rawRecords = [i.replace("\n", " ") for i in puzzle_input.split("\n\n")]
records = []
for rawRecord in rawRecords:
birthYear=re.search(r'byr:(\S+)', rawRecord)
issueYear=re.search(r'iyr:(\S+)', rawRecord)
expirationYear=re.search(r'eyr:(\S+)', rawRecord)
height=re.search(r'hgt:(\S+)', rawRecord)
hairColor=re.search(r'hcl:(\S+)', rawRecord)
eyeColor=re.search(r'ecl:(\S+)', rawRecord)
passportId=re.search(r'pid:(\S+)', rawRecord)
countryId=re.search(r'cid:(\S+)', rawRecord)
records.append(Passport(
int(birthYear[1]) if birthYear is not None else None,
int(issueYear[1]) if issueYear is not None else None,
int(expirationYear[1]) if expirationYear is not None else None,
regexUnwrap(height,1),
regexUnwrap(hairColor,1),
regexUnwrap(eyeColor,1),
regexUnwrap(passportId,1),
regexUnwrap(countryId,1),
))
birthYear = re.search(r"byr:(\S+)", rawRecord)
issueYear = re.search(r"iyr:(\S+)", rawRecord)
expirationYear = re.search(r"eyr:(\S+)", rawRecord)
height = re.search(r"hgt:(\S+)", rawRecord)
hairColor = re.search(r"hcl:(\S+)", rawRecord)
eyeColor = re.search(r"ecl:(\S+)", rawRecord)
passportId = re.search(r"pid:(\S+)", rawRecord)
countryId = re.search(r"cid:(\S+)", rawRecord)
records.append(
Passport(
int(birthYear[1]) if birthYear is not None else None,
int(issueYear[1]) if issueYear is not None else None,
int(expirationYear[1]) if expirationYear is not None else None,
regexUnwrap(height, 1),
regexUnwrap(hairColor, 1),
regexUnwrap(eyeColor, 1),
regexUnwrap(passportId, 1),
regexUnwrap(countryId, 1),
)
)
return records
def lazyCheckPassport(passport: Passport)->bool:
def lazyCheckPassport(passport: Passport) -> bool:
return (
passport.birthYear is not None
and passport.issueYear is not None
and passport.expirationYear is not None
and passport.height is not None
and passport.hairColor is not None
and passport.eyeColor is not None
and passport.passportId is not None
)
passport.birthYear is not None
and passport.issueYear is not None
and passport.expirationYear is not None
and passport.height is not None
and passport.hairColor is not None
and passport.eyeColor is not None
and passport.passportId is not None
)
def part1(data):
"""Solve part 1"""
return sum(1 for record in data if lazyCheckPassport(record))
def checkBirthYear(passport: Passport)->bool:
if passport.birthYear is None: return False
return (1920<=passport.birthYear<=2002)
def checkIssueYear(passport: Passport)->bool:
if passport.issueYear is None: return False
return (2010<=passport.issueYear<=2020)
def checkBirthYear(passport: Passport) -> bool:
if passport.birthYear is None:
return False
return 1920 <= passport.birthYear <= 2002
def checkExpirationYear(passport: Passport)->bool:
if passport.expirationYear is None: return False
return (2020<=passport.expirationYear<=2030)
def checkHeight(passport: Passport)->bool:
if passport.height is None: return False
rematch = re.match(r'(\d+)((?:in)|(?:cm))', passport.height)
if rematch is None: return False
def checkIssueYear(passport: Passport) -> bool:
if passport.issueYear is None:
return False
return 2010 <= passport.issueYear <= 2020
def checkExpirationYear(passport: Passport) -> bool:
if passport.expirationYear is None:
return False
return 2020 <= passport.expirationYear <= 2030
def checkHeight(passport: Passport) -> bool:
if passport.height is None:
return False
rematch = re.match(r"(\d+)((?:in)|(?:cm))", passport.height)
if rematch is None:
return False
number = int(rematch.group(1))
unit = rematch.group(2)
if unit == 'in':
return (59<=number<=76)
if unit == "in":
return 59 <= number <= 76
else:
return (150<=number<=193)
return 150 <= number <= 193
def checkHairColour(passport: Passport)->bool:
if passport.hairColor is None: return False
return (re.match(r'#[0123456789abcdef]{6}$', passport.hairColor) is not None)
def checkEyeColour(passport: Passport)->bool:
if passport.eyeColor is None: return False
return (passport.eyeColor == 'amb'
or passport.eyeColor == 'blu'
or passport.eyeColor == 'brn'
or passport.eyeColor == 'gry'
or passport.eyeColor == 'grn'
or passport.eyeColor == 'hzl'
or passport.eyeColor == 'oth'
)
def checkHairColour(passport: Passport) -> bool:
if passport.hairColor is None:
return False
return re.match(r"#[0123456789abcdef]{6}$", passport.hairColor) is not None
def checkPassportId(passport: Passport)->bool:
if passport.passportId is None: return False
return (re.match(r'[0-9]{9}$', passport.passportId) is not None)
def checkPassport(passport: Passport)->bool:
return (checkBirthYear(passport)
and checkIssueYear(passport)
and checkExpirationYear(passport)
and checkHeight(passport)
and checkHairColour(passport)
and checkEyeColour(passport)
and checkPassportId(passport)
)
def checkEyeColour(passport: Passport) -> bool:
if passport.eyeColor is None:
return False
return (
passport.eyeColor == "amb"
or passport.eyeColor == "blu"
or passport.eyeColor == "brn"
or passport.eyeColor == "gry"
or passport.eyeColor == "grn"
or passport.eyeColor == "hzl"
or passport.eyeColor == "oth"
)
def checkPassportId(passport: Passport) -> bool:
if passport.passportId is None:
return False
return re.match(r"[0-9]{9}$", passport.passportId) is not None
def checkPassport(passport: Passport) -> bool:
return (
checkBirthYear(passport)
and checkIssueYear(passport)
and checkExpirationYear(passport)
and checkHeight(passport)
and checkHairColour(passport)
and checkEyeColour(passport)
and checkPassportId(passport)
)
def part2(data):
"""Solve part 2"""
return sum(1 for record in data if checkPassport(record))
def solve(puzzle_input):
"""Solve the puzzle for the given input"""
data = parse(puzzle_input)
@ -124,6 +150,7 @@ def solve(puzzle_input):
return solution1, solution2
if __name__ == "__main__":
for path in sys.argv[1:]:
print(f"{path}:")