Skip to content

Commit c4288e1

Browse files
committed
Add solutions for day 6. This was a hard one.
1 parent 25e4618 commit c4288e1

File tree

4 files changed

+152
-20
lines changed

4 files changed

+152
-20
lines changed

Advent of Code 2018.ipynb

Lines changed: 99 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
"trusted": true
1515
},
1616
"cell_type": "code",
17-
"source": "import os\nimport re\n\nfrom collections import Counter, defaultdict\nfrom datetime import datetime\nfrom itertools import accumulate, combinations, cycle\n\nimport numpy as np\nimport pandas as pd\nimport requests",
18-
"execution_count": 62,
17+
"source": "import os\nimport re\nimport string\n\nfrom collections import Counter, defaultdict\nfrom datetime import datetime\nfrom itertools import accumulate, chain, combinations, cycle, zip_longest\n\nimport numpy as np\nimport pandas as pd\nimport requests\n\nfrom scipy.spatial.distance import cdist",
18+
"execution_count": 37,
1919
"outputs": []
2020
},
2121
{
@@ -28,7 +28,7 @@
2828
},
2929
"cell_type": "code",
3030
"source": "def input_for_day(day):\n file_name = f\"day{day:0>2}_input\"\n if os.path.exists(file_name):\n return os.path.abspath(file_name)\n with open(\"session\", \"r\") as session_file:\n response = requests.get(f\"https://adventofcode.com/2018/day/{day}/input\",\n cookies={\"session\": session_file.read()})\n with open(file_name, \"w\") as input_file:\n print(response.text.strip(), file=input_file)\n return os.path.abspath(file_name)",
31-
"execution_count": 2,
31+
"execution_count": 3,
3232
"outputs": []
3333
},
3434
{
@@ -46,11 +46,11 @@
4646
},
4747
"cell_type": "code",
4848
"source": "%time\nwith open(input_for_day(1), \"r\") as input_file:\n print(f'Answer: {sum(map(int, input_file))}')",
49-
"execution_count": 3,
49+
"execution_count": 4,
5050
"outputs": [
5151
{
5252
"output_type": "stream",
53-
"text": "CPU times: user 2 µs, sys: 2 µs, total: 4 µs\nWall time: 9.54 µs\nAnswer: 538\n",
53+
"text": "CPU times: user 5 µs, sys: 2 µs, total: 7 µs\nWall time: 14.3 µs\nAnswer: 538\n",
5454
"name": "stdout"
5555
}
5656
]
@@ -70,11 +70,11 @@
7070
},
7171
"cell_type": "code",
7272
"source": "%%time\nfreq_set = {0}\nwith open(input_for_day(1), \"r\") as input_file:\n for freq in accumulate(cycle(int(line) for line in input_file)):\n if freq in freq_set or freq_set.add(freq):\n print(f\"Answer: {freq}\")\n break",
73-
"execution_count": 4,
73+
"execution_count": 5,
7474
"outputs": [
7575
{
7676
"output_type": "stream",
77-
"text": "Answer: 77271\nCPU times: user 50.5 ms, sys: 20.1 ms, total: 70.5 ms\nWall time: 86.7 ms\n",
77+
"text": "Answer: 77271\nCPU times: user 181 ms, sys: 287 ms, total: 468 ms\nWall time: 518 ms\n",
7878
"name": "stdout"
7979
}
8080
]
@@ -94,11 +94,11 @@
9494
},
9595
"cell_type": "code",
9696
"source": "%%time\nwith open(input_for_day(2), \"r\") as input_file:\n counters = [Counter(n.strip()).values() for n in input_file]\nchecksum = sum(2 in c for c in counters) * sum(3 in c for c in counters)\nprint(f\"Answer: {checksum}\")",
97-
"execution_count": 5,
97+
"execution_count": 6,
9898
"outputs": [
9999
{
100100
"output_type": "stream",
101-
"text": "Answer: 5976\nCPU times: user 10.3 ms, sys: 321 µs, total: 10.7 ms\nWall time: 154 ms\n",
101+
"text": "Answer: 5976\nCPU times: user 25.4 ms, sys: 1.95 ms, total: 27.4 ms\nWall time: 436 ms\n",
102102
"name": "stdout"
103103
}
104104
]
@@ -118,11 +118,11 @@
118118
},
119119
"cell_type": "code",
120120
"source": "%%time\nwith open(input_for_day(2), \"r\") as input_file:\n counters = {x: Counter(x).values() for x in (n.strip() for n in input_file)}\nfor x, y in combinations((n for n, c in counters.items() if any(s in c for s in (2, 3))), 2):\n if sum(a != b for a, b in zip(x, y)) == 1:\n print(f\"Answer: {''.join(a for a, b in zip(x, y) if a == b)}\")\n break",
121-
"execution_count": 6,
121+
"execution_count": 7,
122122
"outputs": [
123123
{
124124
"output_type": "stream",
125-
"text": "Answer: xretqmmonskvzupalfiwhcfdb\nCPU times: user 21.2 ms, sys: 676 µs, total: 21.8 ms\nWall time: 37.1 ms\n",
125+
"text": "Answer: xretqmmonskvzupalfiwhcfdb\nCPU times: user 59.2 ms, sys: 3.79 ms, total: 63 ms\nWall time: 123 ms\n",
126126
"name": "stdout"
127127
}
128128
]
@@ -138,11 +138,11 @@
138138
},
139139
"cell_type": "code",
140140
"source": "%%time\nexpr = re.compile(r\"#(\\d+)\\s@\\s(\\d+),(\\d+):\\s(\\d+)x(\\d+)\")\nfabric = np.zeros((1000, 1000), dtype=np.uint32)\nwith open(input_for_day(3), \"r\") as input_file:\n for claim in input_file:\n _, x, y, w, h = map(int, expr.match(claim).groups())\n fabric[y:y+h, x:x+w] += 1\n print(f\"Answer: {np.sum(fabric > 1)}\")",
141-
"execution_count": 7,
141+
"execution_count": 8,
142142
"outputs": [
143143
{
144144
"output_type": "stream",
145-
"text": "Answer: 117948\nCPU times: user 23.4 ms, sys: 0 ns, total: 23.4 ms\nWall time: 127 ms\n",
145+
"text": "Answer: 117948\nCPU times: user 80.5 ms, sys: 158 ms, total: 239 ms\nWall time: 392 ms\n",
146146
"name": "stdout"
147147
}
148148
]
@@ -158,11 +158,11 @@
158158
},
159159
"cell_type": "code",
160160
"source": "%%time\nexpr = re.compile(r\"#(\\d+)\\s@\\s(\\d+),(\\d+):\\s(\\d+)x(\\d+)\")\nfabric = np.zeros((1000, 1000), dtype=np.uint32)\nwith open(input_for_day(3), \"r\") as input_file:\n claims = [list(map(int, expr.match(claim).groups())) for claim in input_file]\nfor claim in claims:\n _, x, y, w, h = claim\n fabric[y:y+h, x:x+w] += 1\nfor claim in claims:\n claim_id, x, y, w, h = claim\n if np.all(fabric[y:y+h, x:x+w] == 1):\n print(f\"Answer: {claim_id}\")\n break",
161-
"execution_count": 8,
161+
"execution_count": 9,
162162
"outputs": [
163163
{
164164
"output_type": "stream",
165-
"text": "Answer: 567\nCPU times: user 19.4 ms, sys: 9.32 ms, total: 28.7 ms\nWall time: 54.3 ms\n",
165+
"text": "Answer: 567\nCPU times: user 77.3 ms, sys: 68.9 ms, total: 146 ms\nWall time: 199 ms\n",
166166
"name": "stdout"
167167
}
168168
]
@@ -178,11 +178,11 @@
178178
},
179179
"cell_type": "code",
180180
"source": "%%time\nentry_expr = re.compile(r\"\\[(.+)\\]\\s(.*)\")\nguard_expr = re.compile(\"Guard\\s#(\\d+)\")\n\nguards = defaultdict(Counter)\nwith open(input_for_day(4), \"r\") as input_file:\n lines = (entry_expr.match(entry).groups() for entry in sorted(input_file))\nfor timestamp, event in ((datetime.strptime(t, \"%Y-%m-%d %H:%M\"), e) for t, e in lines):\n if event.startswith(\"Guard\"):\n guard = int(guard_expr.match(event).group(1))\n elif event.startswith(\"falls\"):\n start = timestamp\n elif event.startswith(\"wakes\"):\n duration = int((timestamp - start).total_seconds()) // 60\n guards[guard].update(Counter(start.minute + i for i in range(duration)))\n\n_, guard = max((sum(c.values()), g) for g, c in guards.items())\n\nprint(f\"Answer: {guard * guards[guard].most_common()[0][0]}\")",
181-
"execution_count": 113,
181+
"execution_count": 10,
182182
"outputs": [
183183
{
184184
"output_type": "stream",
185-
"text": "Answer: 4716\nCPU times: user 32 ms, sys: 1.84 ms, total: 33.8 ms\nWall time: 71 ms\n",
185+
"text": "Answer: 4716\nCPU times: user 118 ms, sys: 1.6 ms, total: 120 ms\nWall time: 349 ms\n",
186186
"name": "stdout"
187187
}
188188
]
@@ -198,11 +198,91 @@
198198
},
199199
"cell_type": "code",
200200
"source": "%%time\nentry_expr = re.compile(r\"\\[(.+)\\]\\s(.*)\")\nguard_expr = re.compile(\"Guard\\s#(\\d+)\")\n\nguards = defaultdict(Counter)\nwith open(input_for_day(4), \"r\") as input_file:\n lines = (entry_expr.match(entry).groups() for entry in sorted(input_file))\nfor timestamp, event in ((datetime.strptime(t, \"%Y-%m-%d %H:%M\"), e) for t, e in lines):\n if event.startswith(\"Guard\"):\n guard = int(guard_expr.match(event).group(1))\n elif event.startswith(\"falls\"):\n start = timestamp\n elif event.startswith(\"wakes\"):\n duration = int((timestamp - start).total_seconds()) // 60\n guards[guard].update(Counter(start.minute + i for i in range(duration)))\n\n(_, minute), guard = max((c.most_common()[0][::-1], g) for g, c in guards.items())\n\nprint(f\"Answer: {guard * minute}\")",
201-
"execution_count": 112,
201+
"execution_count": 11,
202+
"outputs": [
203+
{
204+
"output_type": "stream",
205+
"text": "Answer: 117061\nCPU times: user 111 ms, sys: 0 ns, total: 111 ms\nWall time: 210 ms\n",
206+
"name": "stdout"
207+
}
208+
]
209+
},
210+
{
211+
"metadata": {},
212+
"cell_type": "markdown",
213+
"source": "## Day 5\n### Part One\nHow many units remain after fully reacting the polymer you scanned?"
214+
},
215+
{
216+
"metadata": {
217+
"trusted": true
218+
},
219+
"cell_type": "code",
220+
"source": "%%time\ndef collapse(s):\n p = [\"_\"]\n for u in s:\n v = p[-1]\n p.pop() if v != u and v.lower() == u.lower() else p.append(u)\n \n return len(p) - 1\n\nwith open(input_for_day(5), \"r\") as input_file:\n print(f\"Answer: {collapse(input_file.read().strip())}\")",
221+
"execution_count": 12,
222+
"outputs": [
223+
{
224+
"output_type": "stream",
225+
"text": "Answer: 11252\nCPU times: user 67.2 ms, sys: 2.33 ms, total: 69.5 ms\nWall time: 558 ms\n",
226+
"name": "stdout"
227+
}
228+
]
229+
},
230+
{
231+
"metadata": {},
232+
"cell_type": "markdown",
233+
"source": "### Part Two\nWhat is the length of the shortest polymer you can produce by removing all units of exactly one type and fully reacting the result?"
234+
},
235+
{
236+
"metadata": {
237+
"trusted": true
238+
},
239+
"cell_type": "code",
240+
"source": "%%time\ndef collapse(s):\n p = [\"_\"]\n for u in s:\n v = p[-1]\n p.pop() if v != u and v.lower() == u.lower() else p.append(u)\n \n return len(p) - 1\n\nwith open(input_for_day(5), \"r\") as input_file:\n data = input_file.read().strip()\nmin_length = min(collapse(s) for s in (data.replace(l, \"\").replace(l.swapcase(), \"\") for l in string.ascii_lowercase))\nprint(f\"Answer: {min_length}\")",
241+
"execution_count": 13,
242+
"outputs": [
243+
{
244+
"output_type": "stream",
245+
"text": "Answer: 6118\nCPU times: user 1.63 s, sys: 0 ns, total: 1.63 s\nWall time: 1.68 s\n",
246+
"name": "stdout"
247+
}
248+
]
249+
},
250+
{
251+
"metadata": {},
252+
"cell_type": "markdown",
253+
"source": "## Day 6\n### Part One\nWhat is the size of the largest area that isn't infinite?"
254+
},
255+
{
256+
"metadata": {
257+
"trusted": true
258+
},
259+
"cell_type": "code",
260+
"source": "%%time\nwith open(input_for_day(6), \"r\") as input_file:\n points = np.fromiter(chain.from_iterable(map(int, l.strip().split(\",\")) for l in input_file), np.uint).reshape(50, 2)\n\n# Boundaries\ntl = np.min(points, axis=0)\nbr = np.max(points, axis=0) + 1\n\n# Index grid\nxx, yy = np.mgrid[tl[0]:br[0], tl[1]:br[1]]\npositions = np.vstack([xx.ravel(), yy.ravel()]).T\n\n# Manhatten distances\ndists = cdist(positions, points, metric='cityblock')\nmin_dists = np.min(dists, axis=1)\n\n# Mapping to pointts\nindex_array = (min_dists[..., np.newaxis] == dists)\n\n# Non ambigious distances\nnon_ambigious_index = (np.sum(index_array, axis=1) == 1)\nindex_array = index_array[non_ambigious_index]\n\n# Borders to filter infinit regions\nborder_index = np.any(np.vstack([tl, br-1])[:,np.newaxis] == positions, axis=(0, 2))\nborder_index = border_index[non_ambigious_index]\nborder_index = np.any(index_array[border_index], axis=0)\n\n# Compute arrea for all points\narea = np.sum(index_array, axis=0)\n\n# Remove points that areas touch the borders\narea[border_ids] = -1\n\nprint(f\"Answer: {np.max(area)}\")",
261+
"execution_count": 179,
262+
"outputs": [
263+
{
264+
"output_type": "stream",
265+
"text": "Answer: 4754\nCPU times: user 171 ms, sys: 62 ms, total: 233 ms\nWall time: 623 ms\n",
266+
"name": "stdout"
267+
}
268+
]
269+
},
270+
{
271+
"metadata": {},
272+
"cell_type": "markdown",
273+
"source": "### Part Two\nWhat is the size of the region containing all locations which have a total distance to all given coordinates of less than 10000?"
274+
},
275+
{
276+
"metadata": {
277+
"trusted": true
278+
},
279+
"cell_type": "code",
280+
"source": "print(f\"Answer: {np.sum(np.sum(dists, axis=1) < 10000)}\")",
281+
"execution_count": 176,
202282
"outputs": [
203283
{
204284
"output_type": "stream",
205-
"text": "Answer: 117061\nCPU times: user 31.1 ms, sys: 0 ns, total: 31.1 ms\nWall time: 77.9 ms\n",
285+
"text": "Answer: 42344\n",
206286
"name": "stdout"
207287
}
208288
]

day05_input

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

day06_input

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
137, 282
2+
229, 214
3+
289, 292
4+
249, 305
5+
90, 289
6+
259, 316
7+
134, 103
8+
96, 219
9+
92, 308
10+
269, 59
11+
141, 132
12+
71, 200
13+
337, 350
14+
40, 256
15+
236, 105
16+
314, 219
17+
295, 332
18+
114, 217
19+
43, 202
20+
160, 164
21+
245, 303
22+
339, 277
23+
310, 316
24+
164, 44
25+
196, 335
26+
228, 345
27+
41, 49
28+
84, 298
29+
43, 51
30+
158, 347
31+
121, 51
32+
176, 187
33+
213, 120
34+
174, 133
35+
259, 263
36+
210, 205
37+
303, 233
38+
265, 98
39+
359, 332
40+
186, 340
41+
132, 99
42+
174, 153
43+
206, 142
44+
341, 162
45+
180, 166
46+
152, 249
47+
221, 118
48+
95, 227
49+
152, 186
50+
72, 330

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
autopep8
33
isort
44
# Real requirements
5-
numpy
5+
numpy
6+
scipy

0 commit comments

Comments
 (0)