-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathday04.py
More file actions
124 lines (86 loc) · 3.04 KB
/
day04.py
File metadata and controls
124 lines (86 loc) · 3.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import os
import re
from aocd import get_data
from dotenv import load_dotenv
from utils import generate_readme
day = int(os.getcwd()[-2:])
year = int(os.getcwd()[-10:][:4])
def get_session() -> str:
load_dotenv()
return os.getenv('SESSION_COOKIE')
def run(data: str = None, part: int = None):
if not data:
if part == 1:
return part1(get_data(get_session(), day=day, year=year).split('\n\n'))
else:
return part2(get_data(get_session(), day=day, year=year).split('\n\n'))
else:
if part == 1:
return part1(data.split('\n\n'))
else:
return part2(data.split('\n\n'))
def get_passports(passport):
values = {}
for i in passport.split(' '):
for j in i.split('\n'):
key, value = j.split(':')
values[key] = value
return values
def validate(passport):
keys = passport.keys()
return len(keys) == 8 or (len(keys) == 7 and 'cid' not in keys)
def part1(data):
passports = [get_passports(lines) for lines in data]
return len([passport for passport in passports if validate(passport)])
def check_range(value, low, high):
return low <= int(value) <= high
def check_dob(value):
return check_range(value, 1920, 2002)
def check_issue(value):
return check_range(value, 2010, 2020)
def check_expiration(value):
return check_range(value, 2020, 3030)
def check_height(value):
if value.find("cm") < 0:
if value.find("in") > 0:
height = int(value[:value.find("in")])
return check_range(height, 59, 76)
else:
height = int(value[:value.find("cm")])
return check_range(height, 150, 193)
def check_hair_colour(value: str) -> bool:
return re.compile(r'#[0-9a-f]{6}').match(value) is not None
def check_eye_colout(value: str) -> bool:
return value in ['amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth']
def check_pid(value: str) -> bool:
return re.compile(r'\d{9}$').match(value) is not None
def validate2(passport):
if not validate(passport):
return False
checks = []
for key, value in passport.items():
if key == 'byr':
checks.append(check_dob(value))
elif key == 'iyr':
checks.append(check_issue(value))
elif key == 'eyr':
checks.append(check_expiration(value))
elif key == 'hgt':
checks.append(check_height(value))
elif key == 'hcl':
checks.append(check_hair_colour(value))
elif key == 'ecl':
checks.append(check_eye_colout(value))
elif key == 'pid':
checks.append(check_pid(value))
elif key == 'cid':
checks.append(True)
return all(checks)
def part2(data):
passports = [get_passports(lines) for lines in data]
valid = [passport for passport in passports if validate2(passport)]
return len(valid)
if __name__ == '__main__':
print(f'Part 1: {run(data=None, part=1)}')
print(f'Part 2: {run(data=None, part=2)}')
generate_readme("README", year, day, '../')