-
Notifications
You must be signed in to change notification settings - Fork 0
/
day13.py
executable file
·204 lines (162 loc) · 7.74 KB
/
day13.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
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
#!/usr/bin/env python3
"""
--- Day 13: Shuttle Search ---
Your ferry can make it safely to a nearby port, but it won't get much further.
When you call to book another ship, you discover that no ships embark from that
port to your vacation island. You'll need to get from the port to the nearest
airport.
Fortunately, a shuttle bus service is available to bring you from the sea port
to the airport! Each bus has an ID number that also indicates how often the bus
leaves for the airport.
Bus schedules are defined based on a timestamp that measures the number of
minutes since some fixed reference point in the past. At timestamp 0, every bus
simultaneously departed from the sea port. After that, each bus travels to the
airport, then various other locations, and finally returns to the sea port to
repeat its journey forever.
The time this loop takes a particular bus is also its ID number: the bus with ID
5 departs from the sea port at timestamps 0, 5, 10, 15, and so on. The bus with
ID 11 departs at 0, 11, 22, 33, and so on. If you are there when the bus
departs, you can ride that bus to the airport!
Your notes (your puzzle input) consist of two lines. The first line is your
estimate of the earliest timestamp you could depart on a bus. The second line
lists the bus IDs that are in service according to the shuttle company; entries
that show x must be out of service, so you decide to ignore them.
To save time once you arrive, your goal is to figure out the earliest bus you
can take to the airport. (There will be exactly one such bus.)
For example, suppose you have the following notes:
939
7,13,x,x,59,x,31,19
Here, the earliest timestamp you could depart is 939, and the bus IDs in service
are 7, 13, 59, 31, and 19. Near timestamp 939, these bus IDs depart at the times
marked D:
time bus 7 bus 13 bus 59 bus 31 bus 19
929 . . . . .
930 . . . D .
931 D . . . D
932 . . . . .
933 . . . . .
934 . . . . .
935 . . . . .
936 . D . . .
937 . . . . .
938 D . . . .
939 . . . . .
940 . . . . .
941 . . . . .
942 . . . . .
943 . . . . .
944 . . D . .
945 D . . . .
946 . . . . .
947 . . . . .
948 . . . . .
949 . D . . .
The earliest bus you could take is bus ID 59. It doesn't depart until timestamp
944, so you would need to wait 944 - 939 = 5 minutes before it departs.
Multiplying the bus ID by the number of minutes you'd need to wait gives 295.
What is the ID of the earliest bus you can take to the airport multiplied by the
number of minutes you'll need to wait for that bus?
--- Part Two ---
The shuttle company is running a contest: one gold coin for anyone that can find
the earliest timestamp such that the first bus ID departs at that time and each
subsequent listed bus ID departs at that subsequent minute. (The first line in
your input is no longer relevant.)
For example, suppose you have the same list of bus IDs as above:
7,13,x,x,59,x,31,19
An x in the schedule means there are no constraints on what bus IDs must depart
at that time.
This means you are looking for the earliest timestamp (called t) such that:
Bus ID 7 departs at timestamp t.
Bus ID 13 departs one minute after timestamp t.
There are no requirements or restrictions on departures at two or three minutes after timestamp t.
Bus ID 59 departs four minutes after timestamp t.
There are no requirements or restrictions on departures at five minutes after timestamp t.
Bus ID 31 departs six minutes after timestamp t.
Bus ID 19 departs seven minutes after timestamp t.
The only bus departures that matter are the listed bus IDs at their specific
offsets from t. Those bus IDs can depart at other times, and other bus IDs can
depart at those times. For example, in the list above, because bus ID 19 must
depart seven minutes after the timestamp at which bus ID 7 departs, bus ID 7
will always also be departing with bus ID 19 at seven minutes after timestamp t.
In this example, the earliest timestamp at which this occurs is 1068781:
time bus 7 bus 13 bus 59 bus 31 bus 19
1068773 . . . . .
1068774 D . . . .
1068775 . . . . .
1068776 . . . . .
1068777 . . . . .
1068778 . . . . .
1068779 . . . . .
1068780 . . . . .
1068781 D . . . .
1068782 . D . . .
1068783 . . . . .
1068784 . . . . .
1068785 . . D . .
1068786 . . . . .
1068787 . . . D .
1068788 D . . . D
1068789 . . . . .
1068790 . . . . .
1068791 . . . . .
1068792 . . . . .
1068793 . . . . .
1068794 . . . . .
1068795 D D . . .
1068796 . . . . .
1068797 . . . . .
In the above example, bus ID 7 departs at timestamp 1068788 (seven minutes after
t). This is fine; the only requirement on that minute is that bus ID 19 departs
then, and it does.
Here are some other examples:
The earliest timestamp that matches the list 17,x,13,19 is 3417.
67,7,59,61 first occurs at timestamp 754018.
67,x,7,59,61 first occurs at timestamp 779210.
67,7,x,59,61 first occurs at timestamp 1261476.
1789,37,47,1889 first occurs at timestamp 1202161486.
However, with so many bus IDs in your list, surely the actual earliest timestamp
will be larger than 100000000000000!
What is the earliest timestamp such that all of the listed bus IDs depart at
offsets matching their positions in the list?
"""
import argparse
parser = argparse.ArgumentParser(epilog=__doc__,
formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument('input', type=argparse.FileType('rt'))
parser.add_argument('--part-two', action='store_true')
args = parser.parse_args()
lines = [line.strip() for line in args.input]
start_time = int(lines[0])
busses = lines[1].split(',')
available_busses = {
offset: int(bus)
for offset, bus in enumerate(busses)
if bus != 'x'
}
if not args.part_two:
timestamp = start_time
earliest_bus = None
while not earliest_bus:
timestamp += 1
for bus in available_busses.values():
if timestamp % bus == 0:
earliest_bus = bus
break
wait_time = timestamp - start_time
print(earliest_bus * wait_time)
else:
busses_to_find = list(available_busses)
# start with minimal step to find first bus
step = 1
timestamp = 0
while busses_to_find:
timestamp += step
# check first bus in the list of remaining busses
offset = busses_to_find[0]
bus = available_busses[offset]
if (timestamp + offset) % bus == 0:
# found the frequency for this bus, so remove it
busses_to_find.pop(0)
# this only works because the bus IDs are all prime (apparently)
step *= bus
print(timestamp)