-
Notifications
You must be signed in to change notification settings - Fork 0
/
part_b.py
executable file
·97 lines (83 loc) · 2.97 KB
/
part_b.py
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
#!/usr/bin/env python3
import utils
from year_2020.day_05 import part_a
class Challenge(utils.BaseChallenge):
part_a_for_testing = part_a
def solve(self, _input, debug=False):
"""
>>> Challenge().default_solve()
617
"""
return BoardingPassesExtended.from_passes_text(_input)\
.find_missing_id_with_both_neighbours()
class BoardingPassExtended(part_a.BoardingPass):
@classmethod
def from_id(cls, _id):
"""
>>> BoardingPassExtended.from_id(357)
BoardingPassExtended(name='FBFBBFFRLR')
>>> BoardingPassExtended.from_id(28)
BoardingPassExtended(name='FFFFFBBRLL')
>>> BoardingPassExtended.from_id(842)
BoardingPassExtended(name='BBFBFFBLRL')
"""
binary_id_str = "{:010b}".format(_id, 'b')
binary_id_part_a, binary_id_part_b = \
binary_id_str[:-3], binary_id_str[-3:]
name_part_a = binary_id_part_a\
.replace("0", "F")\
.replace("1", "B")
name_part_b = binary_id_part_b\
.replace("0", "L")\
.replace("1", "R")
return cls(f"{name_part_a}{name_part_b}")
class BoardingPassesExtended(part_a.BoardingPasses):
boarding_pass_class = BoardingPassExtended
@classmethod
def from_ids(cls, ids):
return cls(list(map(BoardingPassExtended.from_id, ids)))
def find_missing_id_with_both_neighbours(self):
"""
>>> BoardingPassesExtended.from_ids([2, 3, 4, 5, 7, 8, 11, 12])\\
... .find_missing_id_with_both_neighbours()
6
>>> BoardingPassesExtended.from_ids([11, 2, 8, 5, 7, 3, 12, 4])\\
... .find_missing_id_with_both_neighbours()
6
>>> BoardingPassesExtended.from_ids([2, 3, 5, 6, 7, 9, 10, 11])\\
... .find_missing_id_with_both_neighbours()
Traceback (most recent call last):
...
Exception: Found two with both neighbours: 4 and 8
"""
ids = set(map(part_a.BoardingPass.get_seat_id, self.passes))
min_id = min(ids)
max_id = max(ids)
found = None
for current in range(min_id, max_id + 1):
if current in ids:
continue
if current - 1 not in ids:
continue
if current + 1 not in ids:
continue
if found is not None:
raise Exception(
f"Found two with both neighbours: {found} and {current}")
found = current
if not found:
raise Exception(f"Could not find with both neighbours")
return found
def triplets(self, items):
"""
>>> list(BoardingPassesExtended([]).triplets(range(5)))
[(0, 1, 2), (1, 2, 3), (2, 3, 4)]
"""
triplet = ()
for item in items:
triplet += (item,)
if len(triplet) == 3:
yield triplet
triplet = triplet[1:]
Challenge.main()
challenge = Challenge()