AoC
This commit is contained in:
@@ -8,6 +8,8 @@
|
||||
"\n",
|
||||
"# Advent of Code 2022\n",
|
||||
"\n",
|
||||
"# [Day 0](https://adventofcode.com/2022): Preparation\n",
|
||||
"\n",
|
||||
"I'm doing Advent of Code (AoC) again this year. On AoC eve, I prepared by loading up my [**AdventUtils.ipynb**](AdventUtils.ipynb) notebook:"
|
||||
]
|
||||
},
|
||||
@@ -30,10 +32,7 @@
|
||||
" 1. The puzzle we are answering, in the form *day*.*part*\n",
|
||||
" 2. The correct answer as verified by AoC \n",
|
||||
" 3. A function to call to compute the answer (passed as a function so we can time how long it takes to run)\n",
|
||||
"- **Solving Part Two**, e.g. `answer(1.2, ..., lambda: ...)`\n",
|
||||
"\n",
|
||||
"To understand each day's puzzle, you'll really have to read the day's puzzle description, which is linked in the header for each day, e.g. [**Day 1**](https://adventofcode.com/2022/day/1).\n",
|
||||
"\n"
|
||||
"- **Solving Part Two**, e.g. `answer(1.2, ..., lambda: ...)`"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -51,7 +50,7 @@
|
||||
"source": [
|
||||
"# [Day 1](https://adventofcode.com/2022/day/1): Calorie Counting\n",
|
||||
"\n",
|
||||
"There is a complex backstory involving food for the elves and calories, but computationally all we have to know is that the input is a sequence of paragraphs, where each paragraph contains some integers. My `parse` function handles this easily:"
|
||||
"There is a complex backstory involving food for the elves and calories (to fully understand each day's puzzle, you'll really have to read the day's puzzle description, which is linked in the header for each day, e.g. [**Day 1**](https://adventofcode.com/2022/day/1) above), but to computate today's puzzle solution all we have to know is that the input is a sequence of paragraphs, where each paragraph contains some integers. My `parse` function handles this easily:"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -151,10 +150,10 @@
|
||||
"To be clear, here is exactly what I did to solve the day's puzzle:\n",
|
||||
"\n",
|
||||
"1. Typed and executed `in1 = parse(1, ints, paragraphs)` in a Jupyter Notebook cell, and examined the output. Looked good to me.\n",
|
||||
"2. Solved Part 1: typed and executed `max(sum(elf) for elf in in1)` in a cell, and saw the output, `70116`.\n",
|
||||
"2. Solved Part 1: executed `max(sum(elf) for elf in in1)` in a cell, and saw the output, `70116`.\n",
|
||||
"3. Copy/pasted `70116` into the [AoC Day 1](https://adventofcode.com/2022/day/1) answer box and submitted it.\n",
|
||||
"4. Verified that AoC agreed the answer was correct. (Sometimes the first submission is wrong, and I need to repeat steps 2–4.)\n",
|
||||
"5. Typed and executed `answer(1.1, 70116, lambda: max(sum(elf) for elf in in1))` in a cell, for when I re-run the notebook.\n",
|
||||
"4. Verified that AoC agreed the answer was correct. (Sometimes my submission is wrong, and I need to repeat steps 2–4.)\n",
|
||||
"5. Put`answer(1.1, 70116, lambda: max(sum(elf) for elf in in1))` in a cell, to record the answer for when I re-run the notebook.\n",
|
||||
"6. Repeated steps 2–5 for Part 2."
|
||||
]
|
||||
},
|
||||
@@ -216,7 +215,7 @@
|
||||
"source": [
|
||||
"#### Part 1: What would your total score be if everything goes exactly according to your strategy guide?\n",
|
||||
"\n",
|
||||
"One confusing aspect: there are three different encodings. Rock/Paper/Scissors corresponds to A/B/C, and to X/Y/Z, and to scores of 1/2/3. I decided the least confusing approach would be to translate everything to 1/2/3:"
|
||||
"One confusing aspect: there are three different encodings. Rock/Paper/Scissors corresponds to A/B/C, and to X/Y/Z, and to scores of 1/2/3. I decided the least confusing approach would be to translate everything to 1/2/3. For Part 1 we are told that the correspondence between letters and Rock/Paper/Scissors is direct, and we are suppossed to compute the sum of the scores for each round."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -317,7 +316,7 @@
|
||||
"source": [
|
||||
"#### Part 1: Find the item type that appears in both compartments of each rucksack. What is the sum of the priorities of those item types?\n",
|
||||
"\n",
|
||||
"The two \"compartments\" are the two halves of the string. Find the common item by set intersection. My utility function `split_at` divides a string into two parts at an index, and `the` makes sure there is exactly one letter in the interesection:"
|
||||
"The two \"compartments\" are the two halves of the string. Find the common item by set intersection. My utility function `split_at` divides a string into two parts at an index, and `the` makes sure there is exactly one letter in the interesection. The priority of an item is 1–26 for a-z, and 27–52 for A–Z."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -329,7 +328,7 @@
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"0.000 seconds for correct answer: 8,401\n"
|
||||
"0.001 seconds for correct answer: 8,401\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -339,9 +338,9 @@
|
||||
" compartments = split_at(rucksack, len(rucksack) // 2)\n",
|
||||
" return the(intersection(compartments))\n",
|
||||
"\n",
|
||||
"priority = {c: i + 1 for i, c in enumerate(string.ascii_letters)}\n",
|
||||
"def priority(c) -> int: return string.ascii_letters.index(c) + 1\n",
|
||||
"\n",
|
||||
"answer(3.1, 8401, lambda: sum(priority[common_item(rucksack)] for rucksack in in3))"
|
||||
"answer(3.1, 8401, lambda: sum(priority(common_item(rucksack)) for rucksack in in3))"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -367,7 +366,7 @@
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"answer(3.2, 2641, lambda: sum(priority[the(intersection(group))] for group in batched(in3, 3)))"
|
||||
"answer(3.2, 2641, lambda: sum(priority(the(intersection(group))) for group in batched(in3, 3)))"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -383,7 +382,7 @@
|
||||
"source": [
|
||||
"# [Day 4](https://adventofcode.com/2022/day/4): Camp Cleanup\n",
|
||||
"\n",
|
||||
"Each input line represents a pair of ranges of ID numbers for sections of camp that a given elf is assigned to clean up. I'll parse each line into a 4-tuple of endpoints:"
|
||||
"Each input line represents a pair of ranges of ID numbers for sections of camp that a given elf is assigned to clean up. I could parse each line into a pair of `range` objects, but I decided to instead leave them as a 4-tuple of endpoint integers:"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -428,7 +427,7 @@
|
||||
"source": [
|
||||
"#### Part 1: In how many assignment pairs does one range fully contain the other?\n",
|
||||
"\n",
|
||||
"I could have turned each range into a set of integers and compared the sets, but a huge range would mean a huge set, so instead I directly compare the endpoints of the ranges:"
|
||||
"I could form sets and do set intersection, but directly comparing endpoints is easy, and works even fopr ranges with trillions of ID numbers: "
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -487,8 +486,8 @@
|
||||
"# [Day 5](https://adventofcode.com/2022/day/5): Supply Stacks\n",
|
||||
"\n",
|
||||
"My `parse` function is primarily intended for the case where every record is parsed the same way. In today's puzzle, the input has two **sections**, each of which should be parsed differently. The function `parse_sections` is designed to handle this case. It takes as input a list of parsers (in this case two of them), which will be applied to parse each corresponding section:\n",
|
||||
"- The first section is a **diagram**, which is parsed by picking out the characters in each stack; that is, in column 1 and every 4th column after: `line[1::4]`.\n",
|
||||
"- The second section is a list of **moves**, which can be parsed with `ints` to get a 3-tuple of (number-of-crates, start-stack, end-stack). \n"
|
||||
"- The first section is a **diagram**, in which each line is parsed by picking out the characters in the stacks; that is, the characters in column 1 and every 4th column after: `line[1::4]`.\n",
|
||||
"- The second section is a list of **moves**, in which each line can be parsed with `ints` to get a 3-tuple of (number-of-crates, start-stack, end-stack). \n"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -537,7 +536,7 @@
|
||||
"source": [
|
||||
"#### Part 1: After the rearrangement procedure completes, what crate ends up on top of each stack?\n",
|
||||
"\n",
|
||||
"Rearranging means repeatedly popping a crate from one stack and putting it on top of another stack, according to the move commands. I'll define `rearrange` to manipulate and return a dict of {column: [crate, ...]}. You never know what Part 2 will want, so `rearrange` will return the whole dict, and `tops` will pull out the top crate from each stack."
|
||||
"Rearranging means repeatedly popping a crate from one stack and putting it on top of another stack, according to the move commands. I'll define `rearrange` to manipulate and return a dict of {column: [crate, ...]}. You never know what Part 2 will want, so `rearrange` will return the whole dict, and `tops` will pull out the top crate from each stack, which will be the puzzle solution."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -574,7 +573,7 @@
|
||||
"source": [
|
||||
"#### Part 2: After the rearrangement procedure completes, what crate ends up on top of each stack?\n",
|
||||
"\n",
|
||||
"In part 1, when *n* crates were moved with a model 9000 crane, it was done one-at-a-time, so the stack ends up reversed at its destination. In part 2 we have the more advanced model 9001 crane, which can lift all *n* crates at once, and place them down without reversing them. I'll rewrite `rearrange` to handle either way. I'll rerun part 1 to make sure the new function definition is backwards compatible."
|
||||
"In Part 1, when *n* crates were moved with a CrateMover 9000 crane, it was done one-at-a-time, so the stack ends up being reversed at its destination. In Part 2 we have the more advanced CrateMover 9001 crane, which can lift all *n* crates at once, and place them down without reversing them. I'll rewrite `rearrange` to handle either way. I'll rerun part 1 to make sure the new function definition is backwards compatible."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -639,12 +638,12 @@
|
||||
"source": [
|
||||
"#### Part 1: How many characters need to be processed before the first start-of-packet marker is detected?\n",
|
||||
"\n",
|
||||
"A start-of-packet marker is when there are *n* distinct characters in a row. I initially made a mistake: I read the instructions hastily and assumed they were asking for the *start* of the start-of-packet marker, not the *end* of it. When AoC told me I had the wrong answer, I read the instructions more carefully and figured it out."
|
||||
"A start-of-packet marker is when there are *n* distinct characters in a row. We're asked to find the first place where that occurs. I initially made a mistake: I read the instructions hastily and assumed they were asking for the *start* of the start-of-packet marker, not the *end* of it. When AoC told me I had the wrong answer, I read the instructions more carefully and figured it out."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 18,
|
||||
"execution_count": 57,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
@@ -658,7 +657,7 @@
|
||||
"source": [
|
||||
"def first_marker(stream, n=4) -> int:\n",
|
||||
" \"\"\"The number of characters read before the first start-of-packet marker is detected.\"\"\"\n",
|
||||
" return first(i + n for i in range(len(stream)) if len(set(stream[i:i+n])) == n)\n",
|
||||
" return n + first(i for i in range(len(stream)) if len(set(stream[i:i+n])) == n)\n",
|
||||
"\n",
|
||||
"answer(6.1, 1987, lambda: first_marker(in6, 4))"
|
||||
]
|
||||
@@ -747,7 +746,7 @@
|
||||
"source": [
|
||||
"#### Part 1: Find all of the directories with a total size of at most 100000. What is the sum of the total sizes of those directories?\n",
|
||||
"\n",
|
||||
"I'll keep track of a stack of directories (as Unix/Linux does with the [dirs/pushd/popd](https://www.gnu.org/software/bash/manual/html_node/Directory-Stack-Builtins.html) commands). All I need to pay attention to is `cd` commands (which change the `dirs` stack) and file size listings. I can ignore `ls` command lines and \"`dir` *name*\" output. My `browse` function examines the lines of the transcript and returns a Counter of `{directory_name: total_size}`. From that Counter I can sum the directory sizes that are under 100,000. "
|
||||
"I'll keep track of a **stack** of directories (as Unix/Linux does with the [dirs/pushd/popd](https://www.gnu.org/software/bash/manual/html_node/Directory-Stack-Builtins.html) commands). All I need to pay attention to in the transcript are `cd` commands (which change the `dirs` stack) and file size output (which I will use to increment the size of the current directory and all the parent directories in the stack). I'm making the assumption that the transcript is a systematic exploration that will not visit a subdirectory and issue an `ls` command twice. Given that assumption, I can ignore `ls` command lines and \"`dir` *name*\" output. My `browse` function examines the lines of the transcript and returns a Counter of `{directory_name: total_size}`. From that Counter I can sum the directory sizes that are under 100,000. "
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -789,7 +788,9 @@
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"#### Part 2: Find the smallest directory that, if deleted, would free up enough space on the filesystem to run the update. What is the total size of that directory?"
|
||||
"#### Part 2: Find the smallest directory that, if deleted, would free up enough space on the filesystem to run the update. What is the total size of that directory?\n",
|
||||
"\n",
|
||||
"I'm glad I chose to return the complete directory size Counter in Part 1; with that I can quickly find the smallest directory that frees up enough space:"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -826,7 +827,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 23,
|
||||
"execution_count": 59,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
@@ -866,19 +867,19 @@
|
||||
"source": [
|
||||
"#### Part 1: Consider your map; how many trees are visible from outside the grid?\n",
|
||||
"\n",
|
||||
"In the worst case this is *O*(*n*<sup>2</sup>), so I don't feel too bad about taking the brute force approach of considering every location in the grid, and checking if for **any** direction, **all** the points in that direction have a shorter tree:"
|
||||
"A tree is visible if all the trees in front of it, from the viewing direction, are shorter. With only 10,000 total trees, I'll take the brute force approach of considering every location in the grid, and checking if it is visible: if, for **any** direction, **all** the points in that direction have a shorter tree:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 24,
|
||||
"execution_count": 67,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"0.050 seconds for correct answer: 1,829\n"
|
||||
"0.074 seconds for correct answer: 1,829\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -886,18 +887,18 @@
|
||||
"def visible_from_outside(grid) -> int:\n",
|
||||
" \"\"\"How many points on grid are visible from the outside?\n",
|
||||
" Points such that, for some direction, all the points in that direction have a shorter tree.\"\"\"\n",
|
||||
" return quantify(any(all(grid[p] < grid[loc] for p in go_in_direction(loc, dir, grid))\n",
|
||||
" for dir in directions4)\n",
|
||||
" for loc in grid)\n",
|
||||
" def is_visible(loc) -> bool: \n",
|
||||
" return any(all(grid[p] < grid[loc] for p in go_in_direction(loc, dir, grid))\n",
|
||||
" for dir in directions4)\n",
|
||||
" return quantify(grid, is_visible)\n",
|
||||
"\n",
|
||||
"def go_in_direction(start, direction, grid) -> Iterable[Point]:\n",
|
||||
" \"\"\"All the points in grid that are beyond `start` in `direction`.\"\"\"\n",
|
||||
" (x, y), (dx, dy) = start, direction\n",
|
||||
" while True:\n",
|
||||
" (x, y) = (x + dx, y + dy)\n",
|
||||
" if (x, y) not in grid:\n",
|
||||
" start = add(start, direction)\n",
|
||||
" if start not in grid:\n",
|
||||
" return\n",
|
||||
" yield (x, y)\n",
|
||||
" yield start\n",
|
||||
"\n",
|
||||
"answer(8.1, 1829, lambda: visible_from_outside(in8))"
|
||||
]
|
||||
@@ -920,14 +921,14 @@
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"0.057 seconds for correct answer: 291,840\n"
|
||||
"0.055 seconds for correct answer: 291,840\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def scenic_score(loc, grid) -> int:\n",
|
||||
" \"\"\"The product of the number of trees you can see in each of the 4 directions.\"\"\"\n",
|
||||
" return prod(viewing_distance(loc, direction, grid) for direction in directions4)\n",
|
||||
" return prod(viewing_distance(loc, dir, grid) for dir in directions4)\n",
|
||||
"\n",
|
||||
"def viewing_distance(loc, direction, grid) -> int:\n",
|
||||
" \"\"\"The number of trees you can see from this location in this direction.\"\"\"\n",
|
||||
@@ -951,7 +952,9 @@
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"I can plot the forest. Darker green means taller trees, and the red dot is the most scenic spot. We see that the taller growth is towards the center of the forest:"
|
||||
"I can plot the forest. Darker green means taller trees, and the red dot is the most scenic spot. (I have a utility function, `naked_plot`, that plots points without the distracting axis lines and numbers. But it is not set up to do a plot that has different colors, so I do that in a separate call to `plt.scatter`.)\n",
|
||||
"\n",
|
||||
"We see that the taller growth is towards the center of the forest:"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1026,11 +1029,11 @@
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"These are motion commands for the head of a rope; the tail (one knot away) must follow, so that it is always on or adjacent to the head's location.\n",
|
||||
"These are motion commands for the head of a rope; the tail (one knot away) must follow, so that it is always on or adjacent (in one of 8 directions) to the head's location.\n",
|
||||
"\n",
|
||||
"#### Part 1: Simulate your complete hypothetical series of motions. How many positions does the tail of the rope visit at least once?\n",
|
||||
"\n",
|
||||
"The rules for how the tail moves are a bit tricky, but otherwise the control flow is easy. I'll return the set of visited squares (not just their count), in case I need it in part 2. I provide for an optional starting position; this is arbitrary, but it makes it easier to follow the example in the puzzle description if I start at the same place they start at."
|
||||
"The rules for how the tail moves are a bit tricky, but otherwise the control flow is easy. I'll return the set of visited squares (not just their count), in case I need it in Part 2. I provide for an optional starting position; this is arbitrary, but it makes it easier to follow the example in the puzzle description if I start at the same place they start at."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1042,7 +1045,7 @@
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"0.021 seconds for correct answer: 6,236\n"
|
||||
"0.020 seconds for correct answer: 6,236\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -1078,7 +1081,7 @@
|
||||
"source": [
|
||||
"#### Part 2: Simulate your complete series of motions on a larger rope with ten knots. How many positions does the tail of the rope visit at least once?\n",
|
||||
"\n",
|
||||
"I'll re-write `move_rope` to take an optional argument giving the number of knots in the rope. Then instead of just one `move_tail` per loop, I'll move all the non-head knots in the rope, each one to follow the one immediately in front of it. I'll show that the re-write is backwards compatible by repeating the two-knot solution from Part 1 and adding the ten-knot solution from Part 2:"
|
||||
"I'll re-write `move_rope` to take an optional argument giving the number of knots in the rope. Then instead of just one `move_tail` per loop, I'll move all the non-head knots in the rope, each one to follow the one immediately in front of it. I'll show that the re-write is backwards compatible by repeating the two-knot solution from Part 1 and adding the ten-knot solution for Part 2:"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1090,8 +1093,8 @@
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"0.024 seconds for correct answer: 6,236\n",
|
||||
"0.112 seconds for correct answer: 2,449\n"
|
||||
"0.025 seconds for correct answer: 6,236\n",
|
||||
"0.110 seconds for correct answer: 2,449\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -1321,7 +1324,7 @@
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"0.036 seconds for correct answer: PLPAFBCL\n"
|
||||
"0.035 seconds for correct answer: PLPAFBCL\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1488,7 +1491,7 @@
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"0.001 seconds for correct answer: 54,036\n",
|
||||
"0.278 seconds for correct answer: 13,237,873,355\n"
|
||||
"0.281 seconds for correct answer: 13,237,873,355\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -1590,7 +1593,7 @@
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"0.039 seconds for correct answer: 394\n"
|
||||
"0.035 seconds for correct answer: 394\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -1946,7 +1949,7 @@
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"0.136 seconds for correct answer: 728\n"
|
||||
"0.134 seconds for correct answer: 728\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -2005,8 +2008,8 @@
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"0.136 seconds for correct answer: 728\n",
|
||||
"6.396 seconds for correct answer: 27,623\n"
|
||||
"0.138 seconds for correct answer: 728\n",
|
||||
"6.550 seconds for correct answer: 27,623\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -2117,7 +2120,7 @@
|
||||
" 1.2: '0.000 seconds for correct answer: 206,582',\n",
|
||||
" 2.1: '0.001 seconds for correct answer: 13,268',\n",
|
||||
" 2.2: '0.001 seconds for correct answer: 15,508',\n",
|
||||
" 3.1: '0.000 seconds for correct answer: 8,401',\n",
|
||||
" 3.1: '0.001 seconds for correct answer: 8,401',\n",
|
||||
" 3.2: '0.000 seconds for correct answer: 2,641',\n",
|
||||
" 4.1: '0.000 seconds for correct answer: 477',\n",
|
||||
" 4.2: '0.000 seconds for correct answer: 830',\n",
|
||||
@@ -2127,20 +2130,20 @@
|
||||
" 6.2: '0.002 seconds for correct answer: 3,059',\n",
|
||||
" 7.1: '0.001 seconds for correct answer: 1,232,307',\n",
|
||||
" 7.2: '0.001 seconds for correct answer: 7,268,994',\n",
|
||||
" 8.1: '0.050 seconds for correct answer: 1,829',\n",
|
||||
" 8.2: '0.057 seconds for correct answer: 291,840',\n",
|
||||
" 9.1: '0.024 seconds for correct answer: 6,236',\n",
|
||||
" 9.2: '0.112 seconds for correct answer: 2,449',\n",
|
||||
" 8.1: '0.049 seconds for correct answer: 1,829',\n",
|
||||
" 8.2: '0.055 seconds for correct answer: 291,840',\n",
|
||||
" 9.1: '0.025 seconds for correct answer: 6,236',\n",
|
||||
" 9.2: '0.110 seconds for correct answer: 2,449',\n",
|
||||
" 10.1: '0.000 seconds for correct answer: 12,560',\n",
|
||||
" 10.2: '0.036 seconds for correct answer: PLPAFBCL',\n",
|
||||
" 10.2: '0.035 seconds for correct answer: PLPAFBCL',\n",
|
||||
" 11.1: '0.001 seconds for correct answer: 54,036',\n",
|
||||
" 11.2: '0.278 seconds for correct answer: 13,237,873,355',\n",
|
||||
" 12.1: '0.039 seconds for correct answer: 394',\n",
|
||||
" 11.2: '0.281 seconds for correct answer: 13,237,873,355',\n",
|
||||
" 12.1: '0.035 seconds for correct answer: 394',\n",
|
||||
" 12.2: '0.038 seconds for correct answer: 388',\n",
|
||||
" 13.1: '0.001 seconds for correct answer: 5,882',\n",
|
||||
" 13.2: '0.009 seconds for correct answer: 24,948',\n",
|
||||
" 14.1: '0.136 seconds for correct answer: 728',\n",
|
||||
" 14.2: '6.396 seconds for correct answer: 27,623'}"
|
||||
" 14.1: '0.138 seconds for correct answer: 728',\n",
|
||||
" 14.2: '6.550 seconds for correct answer: 27,623'}"
|
||||
]
|
||||
},
|
||||
"execution_count": 55,
|
||||
@@ -2151,6 +2154,33 @@
|
||||
"source": [
|
||||
"answers"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 56,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"0.05406618118286133"
|
||||
]
|
||||
},
|
||||
"execution_count": 56,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"TOTAL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
"def parse(day_or_text:Union[int, str], parser:Callable=str, sep:str=lines, show=6) -> tuple:\n",
|
||||
" \"\"\"Split the input text into items separated by `sep`, and apply `parser` to each.\n",
|
||||
" The first argument is either the text itself, or the day number of a text file.\"\"\"\n",
|
||||
" start = time.time()\n",
|
||||
" text = get_text(day_or_text)\n",
|
||||
" print_parse_items('Puzzle input', text.splitlines(), show, 'line')\n",
|
||||
" records = mapt(parser, text.rstrip().split(sep))\n",
|
||||
|
||||
Reference in New Issue
Block a user