From 2dc2e38a213f02037487cfbd5e3eaa91da230e20 Mon Sep 17 00:00:00 2001 From: Peter Norvig Date: Thu, 26 Dec 2024 14:11:49 -0800 Subject: [PATCH] Add files via upload --- ipynb/Advent-2024.ipynb | 992 +++++++++++++++++++++------------------- 1 file changed, 524 insertions(+), 468 deletions(-) diff --git a/ipynb/Advent-2024.ipynb b/ipynb/Advent-2024.ipynb index 49d4524..634e13b 100644 --- a/ipynb/Advent-2024.ipynb +++ b/ipynb/Advent-2024.ipynb @@ -9,16 +9,16 @@ "\n", "# Advent of Code 2024\n", "\n", - "I enjoy doing the [**Advent of Code**](https://adventofcode.com/) (AoC) programming puzzles, so here we go for 2024! Our old friend [@GaryJGrady](https://x.com/garyjgrady) is here to provide illustrations:\n", + "I enjoy doing the [**Advent of Code**](https://adventofcode.com/) (AoC) programming puzzles, so here we go for 2024! This is the 10th year, so congratulations to puzzle creator [**Eric Wastl**](https://adventofcode.com/2024/about). Our old friend [**Gary Grady**](https://find.sciences.social/search/accounts/@garygrady@mastodon.social) is here to provide illustrations:\n", "\n", "\"GaryJGrady\n", "\n", - "Even before December first I can start by loading up my [**AdventUtils.ipynb**](AdventUtils.ipynb) notebook (same as last time except for the `current_year`):" + "Even before December 1st I can start by loading up my [**AdventUtils.ipynb**](AdventUtils.ipynb) notebook (same as last time except for the `current_year`):" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1440, "id": "ed82ed5b-a42d-468b-8f6e-288d3c2de20b", "metadata": {}, "outputs": [ @@ -49,7 +49,7 @@ "\n", "The function `parse` assumes that the input is a sequence of sections (default one per line), each of which should be parsed in some way and then returned as a tuple. The parsing method `ints` says to treat each section as a tuple of integers. The function `answer` checks that the correct answer is computed (useful for regression testing), and records the run time (that's why a `lambda:` is used). You can read the [**AdventUtils.ipynb**](AdventUtils.ipynb) notebook for more on these functions (and the other utilities used throughout this notebook, such as the `Grid` class).\n", "\n", - "To fully understand each day's puzzle, and to follow along the drama involving Santa, the elves, the reindeer, some elephants, the Chief Historian, and all the rest, you need to read the descriptions on the [**AoC**](https://adventofcode.com/) site, as linked in the header for each of each day's solutions (e.g. [**Day 1**](https://adventofcode.com/2023/day/1) below). I can't copy the content of AoC here, nor show my input files; you need to go to the site for that." + "To fully understand each day's puzzle, and to follow along the drama involving Santa, the elves, the reindeer, some elephants, the Chief Historian, and all the rest, you need to read the puzzle descriptions on the [**AoC**](https://adventofcode.com/) site, as linked in the header for each day's solutions (e.g. [**Day 1**](https://adventofcode.com/2023/day/1) below). " ] }, { @@ -64,7 +64,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 907, "id": "22e5d621-a152-4712-866f-f8b962b5dd14", "metadata": {}, "outputs": [ @@ -117,7 +117,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 909, "id": "8d6bc9f5-5fa1-4dad-bd43-d957833d8ea9", "metadata": {}, "outputs": [], @@ -129,7 +129,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 910, "id": "6ada5e5b-2fb7-4198-a5bb-7b2af4b9270a", "metadata": {}, "outputs": [ @@ -139,7 +139,7 @@ "Puzzle 1.1: .000 seconds, answer 1830467 ok" ] }, - "execution_count": 8, + "execution_count": 910, "metadata": {}, "output_type": "execute_result" } @@ -161,7 +161,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 912, "id": "0131e096-38d1-4c13-9e9c-b0d09839a5cf", "metadata": {}, "outputs": [], @@ -174,7 +174,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 913, "id": "6f6c298a-53a1-4d80-8747-7dd713d4d4f0", "metadata": {}, "outputs": [ @@ -184,7 +184,7 @@ "Puzzle 1.2: .000 seconds, answer 26674158 ok" ] }, - "execution_count": 11, + "execution_count": 913, "metadata": {}, "output_type": "execute_result" } @@ -206,7 +206,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 915, "id": "10e1ab83-a6ec-4143-ad9a-eaae220adcde", "metadata": {}, "outputs": [ @@ -257,7 +257,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 1408, "id": "0f6b6744-e93d-47cf-accd-daab9f3650d0", "metadata": {}, "outputs": [], @@ -267,7 +267,7 @@ " deltas = diffs(report)\n", " return deltas.issubset({1, 2, 3}) or deltas.issubset({-1, -2, -3})\n", " \n", - "def diffs(report: Ints) -> set:\n", + "def diffs(report: Ints) -> Set[int]:\n", " \"\"\"The set of differences between adjacent numbers in the report.\"\"\"\n", " return {report[i] - report[i - 1] for i in range(1, len(report))}" ] @@ -282,7 +282,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 1411, "id": "c0cc052b-e9ef-4757-a860-4cd34dd00fb8", "metadata": {}, "outputs": [], @@ -291,9 +291,17 @@ "assert is_safe((7, 6, 4, 2, 1)) == True" ] }, + { + "cell_type": "markdown", + "id": "051c71b7-4375-4812-b7cc-0c50adf20a09", + "metadata": {}, + "source": [ + "And here is the answer to the puzzle:" + ] + }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 920, "id": "e662bf10-4d6a-40f1-95ce-dfc39f5b3fc2", "metadata": {}, "outputs": [ @@ -303,7 +311,7 @@ "Puzzle 2.1: .000 seconds, answer 257 ok" ] }, - "execution_count": 18, + "execution_count": 920, "metadata": {}, "output_type": "execute_result" } @@ -318,16 +326,16 @@ "id": "ee48bf63-8a67-407b-9a73-df097811eabc", "metadata": {}, "source": [ - "Note: I used my AdventUtil function `quantify`, where `quantify(reports, is_safe)` means the number of items in `reports` for which `is_safe` is true.\n", + "Note: I used my [AdventUtils](AdventUtils.ipynb) function `quantify`, where `quantify(reports, is_safe)` means the number of items in `reports` for which `is_safe` is true.\n", "\n", "### Part 2: How many reports are safe using the Problem Dampener?\n", "\n", - "The **problem dampener** says that a report is safe if you can drop one element and get a safe report." + "The **problem dampener** says that a report is safe if there is some way to drop one element and get a safe report." ] }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 1415, "id": "67ba1d53-95b7-4811-b225-2ff15d6bdc5c", "metadata": {}, "outputs": [], @@ -336,26 +344,26 @@ " \"\"\"Is there any way to drop one element of `report` to get a safe report?\"\"\"\n", " return any(map(is_safe, drop_one(report)))\n", "\n", - "def drop_one(report) -> Iterable:\n", - " \"\"\"All ways of dropping one element of the input report.\"\"\"\n", - " return (report[:i] + report[i + 1:] for i in range(len(report)))\n", + "def drop_one(seq: Sequence) -> Iterable:\n", + " \"\"\"All ways of dropping one element of the input sequence.\"\"\"\n", + " return (seq[:i] + seq[i + 1:] for i in range(len(seq)))\n", "\n", "assert set(drop_one('1234')) == {'234', '134', '124', '123'}" ] }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 1417, "id": "d1b9ffb5-af7a-465f-a063-c31df2d0605c", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 2.2: .002 seconds, answer 328 ok" + "Puzzle 2.2: .006 seconds, answer 328 ok" ] }, - "execution_count": 21, + "execution_count": 1417, "metadata": {}, "output_type": "execute_result" } @@ -372,12 +380,12 @@ "source": [ "# [Day 3](https://adventofcode.com/2024/day/3): Mull It Over\n", "\n", - "Today's input is a computer program with some corrupted characters. The program has multiple lines, but lines don't matter, so I will concatenate them into one big string:" + "Today's input is a computer program with some corrupted characters. The program has multiple lines, but newlines don't matter in this programming language, so I will concatenate them into one big string:" ] }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 1420, "id": "78080200-0f9f-4492-9bee-c936737ee96f", "metadata": {}, "outputs": [ @@ -416,7 +424,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 927, "id": "bf6366b1-6952-47d8-8b3c-09f8d05ec093", "metadata": {}, "outputs": [], @@ -430,7 +438,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 928, "id": "2032c903-5f23-4c16-ba68-410b6c1750e1", "metadata": {}, "outputs": [ @@ -440,7 +448,7 @@ "Puzzle 3.1: .001 seconds, answer 156388521 ok" ] }, - "execution_count": 26, + "execution_count": 928, "metadata": {}, "output_type": "execute_result" } @@ -450,25 +458,22 @@ " execute(program))" ] }, + { + "cell_type": "markdown", + "id": "d39477c7-5c81-41a9-83a3-5b1bfdef273a", + "metadata": {}, + "source": [ + "Here's an example of `findall_multiplications`:" + ] + }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 1424, "id": "85844f51-1396-4299-ba5b-c61064ee02b6", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['mul(1,2)', 'mul(34,5)']" - ] - }, - "execution_count": 27, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "findall_multiplications(\"mul(1,2) + mul(34,5) + mul(67,89]\")" + "assert findall_multiplications(\"mul(1,2) + mul(34,5) + mul(67,89] + mul(x,15)\") == ['mul(1,2)', 'mul(34,5)']" ] }, { @@ -478,12 +483,12 @@ "source": [ "### Part 2: What do you get if you add up all of the results of just the enabled multiplications?\n", "\n", - "For Part 2, the instruction \"don't()\" says to disable (ignore) following multiply instructions until a \"do()\" instruction enables them again. I will define the function `enabled`, which returns the part of the program that is enabled, by susbstituting a space for the \"don't()...do()\" sequence." + "For Part 2, the instruction \"`don't()`\" says to **disable** (ignore) following multiply instructions until a \"`do()`\" instruction **enables** them again. I will define the function `enabled`, which returns the part of the program that is enabled, by susbstituting a space for the \"`don't()...do()`\" sequence (or a \"`don't()...`\" sequence that goes to the end of the file)." ] }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 931, "id": "4525d01a-bac0-41c2-92b8-baf0fd395e88", "metadata": {}, "outputs": [], @@ -495,7 +500,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 932, "id": "ce40f258-ca76-48c3-9965-27a6979a4243", "metadata": {}, "outputs": [ @@ -505,7 +510,7 @@ "Puzzle 3.2: .000 seconds, answer 75920122 ok" ] }, - "execution_count": 30, + "execution_count": 932, "metadata": {}, "output_type": "execute_result" } @@ -527,7 +532,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 934, "id": "a0d903b9-018e-4861-9314-cafed59055fd", "metadata": {}, "outputs": [ @@ -561,12 +566,12 @@ "source": [ "### Part 1: How many times does XMAS appear?\n", "\n", - "We just have to find how many times the word \"XMAS\" appears in the grid, horizontally, vertically, or diagonally, forwards or backwards. The variable `directions8` contains those eight directions (as (delta-x, delta-y) pairs). So examine each square of the grid and if it contains \"X\", see in how many of the directions it spells \"XMAS\". (Note that locations in the grid are denoted by `(x, y)` coordinates, as are directions (e.g., `(1, 0)` is the `East` direction. The functions `add` and `mul` do addition and scalar multiplication on these vectors.)" + "We just have to find how many times the word \"XMAS\" appears in the grid, horizontally, vertically, or diagonally, forwards or backwards. The variable `directions8` contains those eight directions (as (delta-x, delta-y) pairs). So examine each square of the grid and if it contains \"X\", see in how many of the directions it spells \"XMAS\". (Note that locations in the grid are denoted by `(x, y)` coordinates, as are directions (e.g., `(1, 0)` is the `East` direction. The functions `add2` and `mul2` do addition and scalar multiplication on these 2D vectors.)" ] }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 1443, "id": "72d48abb-7a82-452f-b91d-838b3836a90f", "metadata": {}, "outputs": [], @@ -580,22 +585,23 @@ "\n", "def grid_can_spell(grid, start, dir, word):\n", " \"\"\"Does `word` appear in grid starting at `start` and going in direction `dir`?\"\"\"\n", - " return all(grid[add2(start, mul(dir, i))] == word[i] for i in range(len(word)))" + " return all(grid[add2(start, mul2(dir, i))] == word[i] \n", + " for i in range(len(word)))" ] }, { "cell_type": "code", - "execution_count": 35, + "execution_count": 1445, "id": "6175362b-d8b4-45d1-b70c-d8575a0fe188", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 4.1: .032 seconds, answer 2401 ok" + "Puzzle 4.1: .041 seconds, answer 2401 ok" ] }, - "execution_count": 35, + "execution_count": 1445, "metadata": {}, "output_type": "execute_result" } @@ -623,7 +629,7 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": 1451, "id": "3d8a051f-cf7b-4e8c-b0fb-78c3f089989d", "metadata": {}, "outputs": [], @@ -632,25 +638,26 @@ "\n", "def x_search(grid: Grid, word='MAS') -> int:\n", " \"\"\"How many times does an X-MAS appear in the grid?\"\"\"\n", - " return quantify((grid_can_spell(grid, sub(mid_pos, dir1), dir1, word) and\n", - " grid_can_spell(grid, sub(mid_pos, dir2), dir2, word))\n", - " for mid_pos in grid if grid[mid_pos] == word[1]\n", + " A = word[1] # The letter in the middle of the cross\n", + " return quantify((grid_can_spell(grid, sub2(mid_pos, dir1), dir1, word) and\n", + " grid_can_spell(grid, sub2(mid_pos, dir2), dir2, word))\n", + " for mid_pos in grid.findall(A) # All positions where A appears\n", " for dir1, dir2 in diagonal_pairs)" ] }, { "cell_type": "code", - "execution_count": 38, + "execution_count": 1453, "id": "64cde1d9-f58c-4633-b5da-87908a02f76d", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 4.2: .026 seconds, answer 1822 ok" + "Puzzle 4.2: .029 seconds, answer 1822 ok" ] }, - "execution_count": 38, + "execution_count": 1453, "metadata": {}, "output_type": "execute_result" } @@ -667,16 +674,16 @@ "source": [ "# [Day 5](https://adventofcode.com/2024/day/5): Print Queue\n", "\n", - "Today's puzzle involves a **sleigh launch safety manual** that needs to be updated. The day's input is in two sections: the first a set of **rules** such as \"47|53\", which means that page 47 must be printed before page 53; and the second a list of **updates** of the form \"75,47,61,53,29\", meaning that those pages are to be printed in that order.\n", + "Today's puzzle involves some **sleigh launch safety manuals** that need to be updated with new printings. The day's input is in two sections: the first a set of **rules** such as \"47|53\", which means that if an update prints both page 47 and page 53, then it must print 47 sometime before 53. The second section is a list of **updates** of the form \"75,47,61,53,29\", meaning that for one version of the safety manual, those are the pages that need to be printed, and that is the suggested order of printing.\n", "\n", "\n", "\n", - "I mostly like my `parse` function, but I admit it is not ideal when an input file has two sections like this. I'll parse the two sections as paragraphs, and then call `parse` again on each paragraph:" + "I mostly like my `parse` function: it is easy to tell it how to break the input into sections and how to parse every section. But I admit my `parse` is not ideal when an input file has sections with two different formats. I'll parse the two sections as paragraphs, and then call `parse` again on each paragraph:" ] }, { "cell_type": "code", - "execution_count": 40, + "execution_count": 942, "id": "b77a5a1f-a43b-4ce8-a60c-94d69a595505", "metadata": {}, "outputs": [ @@ -729,9 +736,17 @@ "updates = parse(manual[1], ints)" ] }, + { + "cell_type": "markdown", + "id": "c6e4d0b6-c69e-4284-9757-cf3ce51b196c", + "metadata": {}, + "source": [ + "Here I show what the rules and updates look like:" + ] + }, { "cell_type": "code", - "execution_count": 41, + "execution_count": 943, "id": "4c85a23e-686a-4129-a14c-ff6f6a88b9ac", "metadata": {}, "outputs": [], @@ -747,12 +762,12 @@ "source": [ "### Part 1: What do you get if you add up the middle page number from the correctly-ordered updates?\n", "\n", - "I'll define `is_correct` to determine if an update is in the correct order, and `sum_of_correct_middles` to add up the middle numbers of the correct updates:" + "An update is correct if no combination of two pages in the update violates any of the rules. I'll define `is_correct` to implement this check, and `sum_of_correct_middles` to add up the middle numbers of the correct updates:" ] }, { "cell_type": "code", - "execution_count": 43, + "execution_count": 1462, "id": "78898d37-46ff-4367-9d89-b2a107a90aa1", "metadata": {}, "outputs": [], @@ -765,12 +780,12 @@ " \"\"\"An update is correct if no pair of pages violates a rule in the rules set.\"\"\"\n", " return not any((second, first) in rules for (first, second) in combinations(update, 2))\n", "\n", - "def middle(sequence) -> object: return sequence[len(sequence) // 2]" + "def middle(seq: Sequence) -> object: return seq[len(seq) // 2]" ] }, { "cell_type": "code", - "execution_count": 44, + "execution_count": 1464, "id": "b1c87359-1d2d-4a90-8305-9d152ce5d547", "metadata": {}, "outputs": [ @@ -780,7 +795,7 @@ "Puzzle 5.1: .001 seconds, answer 5762 ok" ] }, - "execution_count": 44, + "execution_count": 1464, "metadata": {}, "output_type": "execute_result" } @@ -795,15 +810,15 @@ "id": "80da4fd9-b11e-4dbb-8d22-2071d1a89827", "metadata": {}, "source": [ - "### Part 2: What do you get if you add up the middle page numbers after correctly re-ordering the incorrect updates?\n", + "### Part 2: What do you get if you add up the middle page numbers of the correction of each incorrect update?\n", "\n", - "In Part 2 we have to find the incorrect updates, re-order them into a correct order, and again sum the middle page numbers.\n", - "Since I have already defined `is_correct`, i could just generate all permutations of each update and find one that `is_correct`. That would work great if the longest update consists of only 5 pages, as it does in the example input. But what is the longest update in the actual input?" + "In Part 2 we have to find the incorrect updates, re-order them into a correct order, and sum the middle page numbers of just these corrected updates.\n", + "Since I have already defined `is_correct`, I could just generate all permutations of each update and find one that `is_correct`. That would work great if the longest update consists of only 5 pages, as it does in the example input. But what is the longest update in *my* input?" ] }, { "cell_type": "code", - "execution_count": 46, + "execution_count": 948, "id": "d8718c3e-0b3b-49ce-8cca-abd82aa788d7", "metadata": {}, "outputs": [ @@ -813,7 +828,7 @@ "23" ] }, - "execution_count": 46, + "execution_count": 948, "metadata": {}, "output_type": "execute_result" } @@ -827,52 +842,49 @@ "id": "4449200f-dd19-48f1-94b2-7304daa9fa00", "metadata": {}, "source": [ - "That's not great. With 23 numbers there are 23! permutations, which is over 25 sextillion. So instead, here's my strategy:\n", + "That's not great. With 23 page numbers there are 23! permutations, which is over 25 sextillion. So instead, here's my strategy:\n", "\n", - "- `sum_of_corrected_middles` will find the incorrect rules, perform a correction on each, and sum the middle numbers.\n", - "- `correction` will sort an update, obeying the rules. It used to be that Python's `sort` method allowed a `cmp` keyword to compare two values; there is vestigial support for this with the `functools.cmp_to_key` function. I will **sort** each update so that page *m* comes before page *n* if (*m*, *n*) is in the rules.\n", - "- Sorting will be BOUT a sextillion times faster than enumerating permutations." + "- Instead of generating all permutations, `correction` will **sort** an update, obeying the rules. It used to be that Python's `sort` method allowed a `cmp` keyword to compare two values; there is vestigial support for this with the `functools.cmp_to_key` function. I will sort each update so that page *m* comes before page *n* if (*m*, *n*) is in the rules. Sorting will be about a sextillion times faster than enumerating permutations.\n", + "- `corrected` will find all the incorrect updates and correct them." ] }, { "cell_type": "code", - "execution_count": 48, + "execution_count": 1499, "id": "7222dc1c-067f-4bb5-84e1-3c2fc72fd53a", "metadata": {}, "outputs": [], "source": [ - "def sum_of_corrected_middles(rules, updates) -> int:\n", - " \"\"\"The sum of the middle elements of each update that is correct.\"\"\"\n", - " incorrect = [update for update in updates if not is_correct(update, rules)]\n", - " corrected = [correction(update, rules) for update in incorrect]\n", - " return sum(map(middle, corrected))\n", - " \n", "def correction(update: Ints, rules) -> Ints:\n", - " \"\"\"Reorder the update to make it correct.\"\"\"\n", + " \"\"\"Reorder the update to make it correctly obey all the rules.\"\"\"\n", " def rule_lookup(m, n): return +1 if (m, n) in rules else -1 \n", - " return sorted(update, key=functools.cmp_to_key(rule_lookup))" + " return sorted(update, key=functools.cmp_to_key(rule_lookup))\n", + "\n", + "def corrected(updates, rules) -> List[Ints]:\n", + " \"\"\"Returns a list of corrected versions of all the incorrect rules.\"\"\"\n", + " return [correction(update, rules) for update in updates if not is_correct(update, rules)]" ] }, { "cell_type": "code", - "execution_count": 49, - "id": "dc1fbda9-2cfd-442a-afef-12c9b0d2b17f", + "execution_count": 1501, + "id": "494cda6e-6b07-4054-9b03-45f61bd4f973", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 5.2: .001 seconds, answer 4130 ok" + "Puzzle 5.2: .002 seconds, answer 4130 ok" ] }, - "execution_count": 49, + "execution_count": 1501, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(5.2, 4130, lambda:\n", - " sum_of_corrected_middles(rules, updates))" + " sum_of_correct_middles([], corrected(updates, rules)))" ] }, { @@ -880,7 +892,7 @@ "id": "53b1ccbc-01ae-43d0-a75f-3f9389fdd3c9", "metadata": {}, "source": [ - "I have to say, I'm pleased that this day I got both parts right with no errors (and in fact, the same for the previous days). I was worried I might have my `+1` and `-1` backwards in `cmp_to_key`, but so far, everything has gone smoothly. (However, even if I started solving the second the puzzles are released (which I don't), I wouldn't show up on the leaderboard; I'm still *way* slower than the skilled contest programmers." + "I have to say, I'm pleased that this day I got both parts right with no errors (and in fact, the same for the previous days). I was worried I might have my `+1` and `-1` backwards in `cmp_to_key`, but so far, everything has gone smoothly. (However, even if I started solving the moment that the puzzles are released, I wouldn't show up on the leaderboard; I'm still *way* slower than the skilled contest programmers." ] }, { @@ -895,7 +907,7 @@ }, { "cell_type": "code", - "execution_count": 52, + "execution_count": 954, "id": "6ec71cf8-c43d-457e-8e14-0e9eb99b956a", "metadata": {}, "outputs": [ @@ -937,7 +949,7 @@ }, { "cell_type": "code", - "execution_count": 54, + "execution_count": 956, "id": "95f0b409-a6d6-47bc-8ce5-1c2df80f2b18", "metadata": {}, "outputs": [], @@ -955,17 +967,17 @@ }, { "cell_type": "code", - "execution_count": 55, + "execution_count": 957, "id": "f4be3d1f-7f24-4d55-8221-df0026178e1e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 6.1: .002 seconds, answer 5329 ok" + "Puzzle 6.1: .001 seconds, answer 5329 ok" ] }, - "execution_count": 55, + "execution_count": 957, "metadata": {}, "output_type": "execute_result" } @@ -980,7 +992,7 @@ "id": "eaf72ac3-ade0-4479-a090-1d0f292ecc27", "metadata": {}, "source": [ - "I initially had a **bug**; I asked for the length of the path, not the length of the **set** of positions in the path.\n", + "I initially had a **bug**; I asked for the length of the path, not the length of the **set** of positions in the path; since ther path crosses itself these two numbers are different.\n", " \n", "### Part 2: How many different positions could you choose for an obstruction to put the guard in a loop?\n", "\n", @@ -990,12 +1002,13 @@ "- A loop is when the guard's path returns to the same position with the same facing. This suggests that my Part 1 solution was not completely helpful: to find duplicate positions in the path I would need a set of position/facing pairs, not just positions.\n", "- I can make slightly less work by only storing the corners of the path: the places where the guard turns. \n", "- The simplest approach for finding obstacle positions is to temporarily place an obstacle on each point on the path, one at a time, and see if it leads to a loop.\n", + "- I can detect a loop by keeping a set of previously visited position/facing pairs.\n", "- There are 5,329 positions on the path, so the runtime should be about 5,000 times longer than Part 1; on the order of 10 seconds or so. I'll try it, and if it seems too slow, I'll try to think of something better." ] }, { "cell_type": "code", - "execution_count": 57, + "execution_count": 1509, "id": "1718fecb-aa3e-4162-9948-1c06d4ec5e8a", "metadata": {}, "outputs": [], @@ -1020,22 +1033,22 @@ " grid[pos] = '#' # Temporarily place an obstacle \n", " if is_loopy_path(grid, guard_pos):\n", " yield pos\n", - " grid[pos] = '.' # Remove the obstacle" + " grid[pos] = '.' # Remove the temporarily-placed obstacle" ] }, { "cell_type": "code", - "execution_count": 58, + "execution_count": 1511, "id": "36196264-eb33-4fc0-95d5-06c985105ebf", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 6.2: 1.942 seconds, answer 2162 ok" + "Puzzle 6.2: 1.962 seconds, answer 2162 ok" ] }, - "execution_count": 58, + "execution_count": 1511, "metadata": {}, "output_type": "execute_result" } @@ -1050,7 +1063,9 @@ "id": "9f3ee6f9-7ec7-4248-ae52-1804fdc81dbd", "metadata": {}, "source": [ - "That was a bit slow, but I'll take it. I had a **bug** when I was keeping a set of previously visited states to detect loops; the bug went away when I switched to the step-count limit." + "That was the first run time over a second, but faster than I thought it would be. \n", + "\n", + "I had a **bug** initially, and never figured out what it was; it went away when I refactored to make the program prettier." ] }, { @@ -1060,12 +1075,12 @@ "source": [ "# [Day 7](https://adventofcode.com/2024/day/7): Bridge Repair\n", "\n", - "The narrative for today involves fixing a bridge, and each line of our input represents a calibration equation for the bridge. Unfortunately, some nearby elephants stole all the operators from the equations, so all that is left are the integers:" + "The narrative for today involves fixing a bridge, and each line of our input represents a **calibration equation** for the bridge. Unfortunately, some nearby elephants stole all the operators from the equations, so all that is left are the integers:" ] }, { "cell_type": "code", - "execution_count": 61, + "execution_count": 963, "id": "c1c6cee8-122c-43c9-8c7d-ed8980ea2b76", "metadata": {}, "outputs": [ @@ -1126,7 +1141,7 @@ }, { "cell_type": "code", - "execution_count": 64, + "execution_count": 966, "id": "6fa3907c-0e1a-4d4a-9fc3-f809b9325674", "metadata": {}, "outputs": [ @@ -1136,7 +1151,7 @@ "13" ] }, - "execution_count": 64, + "execution_count": 966, "metadata": {}, "output_type": "execute_result" } @@ -1155,7 +1170,7 @@ }, { "cell_type": "code", - "execution_count": 66, + "execution_count": 968, "id": "5dfe0edf-cf29-4623-bb2c-6180f832f4d7", "metadata": {}, "outputs": [], @@ -1171,7 +1186,7 @@ }, { "cell_type": "code", - "execution_count": 67, + "execution_count": 969, "id": "3085596d-f5ec-4ba8-b05a-cf70cf276a0c", "metadata": {}, "outputs": [ @@ -1181,7 +1196,7 @@ "Puzzle 7.1: .014 seconds, answer 1985268524462 ok" ] }, - "execution_count": 67, + "execution_count": 969, "metadata": {}, "output_type": "execute_result" } @@ -1203,7 +1218,7 @@ }, { "cell_type": "code", - "execution_count": 69, + "execution_count": 971, "id": "393a50cf-f136-446a-a97e-c501669ce89f", "metadata": {}, "outputs": [], @@ -1213,17 +1228,17 @@ }, { "cell_type": "code", - "execution_count": 70, + "execution_count": 972, "id": "f8e75ea3-e8ba-4b33-8efe-8bf74357e35d", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 7.2: .788 seconds, answer 150077710195188 ok" + "Puzzle 7.2: .778 seconds, answer 150077710195188 ok" ] }, - "execution_count": 70, + "execution_count": 972, "metadata": {}, "output_type": "execute_result" } @@ -1243,7 +1258,7 @@ }, { "cell_type": "code", - "execution_count": 72, + "execution_count": 974, "id": "6fe6adad-a3a6-49b8-b49e-6098b27e3a44", "metadata": {}, "outputs": [], @@ -1261,17 +1276,17 @@ }, { "cell_type": "code", - "execution_count": 73, + "execution_count": 975, "id": "ffb673f1-af9d-4d15-8f8d-92e29489dd78", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 7.2: .646 seconds, answer 150077710195188 ok" + "Puzzle 7.2: .635 seconds, answer 150077710195188 ok" ] }, - "execution_count": 73, + "execution_count": 975, "metadata": {}, "output_type": "execute_result" } @@ -1293,7 +1308,7 @@ }, { "cell_type": "code", - "execution_count": 75, + "execution_count": 977, "id": "cf6361a7-e3bc-42ec-ae16-f9eec166055e", "metadata": {}, "outputs": [ @@ -1334,7 +1349,7 @@ }, { "cell_type": "code", - "execution_count": 77, + "execution_count": 979, "id": "22180ce8-5d03-4aee-8c73-62f2afbddf71", "metadata": {}, "outputs": [], @@ -1355,7 +1370,7 @@ }, { "cell_type": "code", - "execution_count": 78, + "execution_count": 980, "id": "dd173ce9-cbbb-4282-b43f-c7cff662bd90", "metadata": {}, "outputs": [ @@ -1365,7 +1380,7 @@ "Puzzle 8.1: .003 seconds, answer 220 ok" ] }, - "execution_count": 78, + "execution_count": 980, "metadata": {}, "output_type": "execute_result" } @@ -1389,7 +1404,7 @@ }, { "cell_type": "code", - "execution_count": 80, + "execution_count": 982, "id": "d30f8ce9-f186-46a0-a2e7-f74eceae6905", "metadata": {}, "outputs": [], @@ -1410,7 +1425,7 @@ }, { "cell_type": "code", - "execution_count": 81, + "execution_count": 983, "id": "6bf85b57-8b8f-4196-9903-6d5fe082f404", "metadata": {}, "outputs": [ @@ -1420,7 +1435,7 @@ "Puzzle 8.1: .003 seconds, answer 220 ok" ] }, - "execution_count": 81, + "execution_count": 983, "metadata": {}, "output_type": "execute_result" } @@ -1432,7 +1447,7 @@ }, { "cell_type": "code", - "execution_count": 82, + "execution_count": 984, "id": "f232952c-5fc6-4696-a8b1-d0b54137ac02", "metadata": {}, "outputs": [ @@ -1442,7 +1457,7 @@ "Puzzle 8.2: .003 seconds, answer 813 ok" ] }, - "execution_count": 82, + "execution_count": 984, "metadata": {}, "output_type": "execute_result" } @@ -1472,7 +1487,7 @@ }, { "cell_type": "code", - "execution_count": 85, + "execution_count": 987, "id": "0e944f9e-5c16-440c-b12e-178058a87048", "metadata": {}, "outputs": [ @@ -1513,7 +1528,7 @@ }, { "cell_type": "code", - "execution_count": 87, + "execution_count": 989, "id": "76e8454d-a2f3-4b6b-92df-182116cf46e0", "metadata": {}, "outputs": [], @@ -1545,7 +1560,7 @@ }, { "cell_type": "code", - "execution_count": 88, + "execution_count": 990, "id": "2aa7e2b9-844e-49ed-b41b-4a4cecff86b7", "metadata": {}, "outputs": [ @@ -1555,7 +1570,7 @@ "Puzzle 9.1: .020 seconds, answer 6332189866718 ok" ] }, - "execution_count": 88, + "execution_count": 990, "metadata": {}, "output_type": "execute_result" } @@ -1583,7 +1598,7 @@ }, { "cell_type": "code", - "execution_count": 90, + "execution_count": 992, "id": "fcf4d832-3d7d-4987-aa57-e6e0f1df16bf", "metadata": {}, "outputs": [], @@ -1625,17 +1640,17 @@ }, { "cell_type": "code", - "execution_count": 91, + "execution_count": 993, "id": "e3036875-88d0-496e-9d2f-facd0e80a5b2", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 9.2: 2.680 seconds, answer 6353648390778 ok" + "Puzzle 9.2: 2.722 seconds, answer 6353648390778 ok" ] }, - "execution_count": 91, + "execution_count": 993, "metadata": {}, "output_type": "execute_result" } @@ -1665,7 +1680,7 @@ }, { "cell_type": "code", - "execution_count": 94, + "execution_count": 996, "id": "5804fb03-05f3-402f-b6cc-6804c5d22512", "metadata": {}, "outputs": [ @@ -1718,7 +1733,7 @@ }, { "cell_type": "code", - "execution_count": 96, + "execution_count": 998, "id": "76b5379e-ee19-4607-91b8-88ec7b38023f", "metadata": {}, "outputs": [], @@ -1734,7 +1749,7 @@ }, { "cell_type": "code", - "execution_count": 97, + "execution_count": 999, "id": "97cf05f7-fa56-4a90-b2d8-2cd4d9b81f95", "metadata": {}, "outputs": [ @@ -1744,7 +1759,7 @@ "Puzzle 10.1: .005 seconds, answer 744 ok" ] }, - "execution_count": 97, + "execution_count": 999, "metadata": {}, "output_type": "execute_result" } @@ -1768,7 +1783,7 @@ }, { "cell_type": "code", - "execution_count": 99, + "execution_count": 1001, "id": "b763450f-a565-4936-bee4-e531c2eeebdb", "metadata": {}, "outputs": [], @@ -1785,7 +1800,7 @@ }, { "cell_type": "code", - "execution_count": 100, + "execution_count": 1002, "id": "f8a87032-6556-4fc9-9bb8-573611aee8dc", "metadata": {}, "outputs": [ @@ -1795,7 +1810,7 @@ "Puzzle 10.2: .006 seconds, answer 1651 ok" ] }, - "execution_count": 100, + "execution_count": 1002, "metadata": {}, "output_type": "execute_result" } @@ -1817,21 +1832,10 @@ }, { "cell_type": "code", - "execution_count": 102, + "execution_count": 1004, "id": "4b35defa-a19e-46c5-bd04-3af55bea14e4", "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "def plot_topo(topo: Grid):\n", " \"\"\"Show the map with a colormap from blue to red.\"\"\"\n", @@ -1857,7 +1861,7 @@ }, { "cell_type": "code", - "execution_count": 104, + "execution_count": 1006, "id": "76b68cef-d8de-4145-b65c-b254fedf1671", "metadata": {}, "outputs": [ @@ -1901,7 +1905,7 @@ }, { "cell_type": "code", - "execution_count": 106, + "execution_count": 1008, "id": "1513df56-3d6f-42cf-8aec-1bdbeb991d90", "metadata": {}, "outputs": [], @@ -1927,17 +1931,17 @@ }, { "cell_type": "code", - "execution_count": 107, + "execution_count": 1009, "id": "eff17cd0-a2c7-4d69-bc55-c0ef97917915", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 11.1: .067 seconds, answer 194482 ok" + "Puzzle 11.1: .063 seconds, answer 194482 ok" ] }, - "execution_count": 107, + "execution_count": 1009, "metadata": {}, "output_type": "execute_result" } @@ -1963,7 +1967,7 @@ }, { "cell_type": "code", - "execution_count": 109, + "execution_count": 1011, "id": "707b5a97-0296-48df-bdab-e34064cc67c2", "metadata": {}, "outputs": [], @@ -1988,7 +1992,7 @@ }, { "cell_type": "code", - "execution_count": 111, + "execution_count": 1013, "id": "efdcdbf8-e8ec-4a85-9d09-90a20e08c66a", "metadata": {}, "outputs": [ @@ -1998,7 +2002,7 @@ "Puzzle 11.1: .002 seconds, answer 194482 ok" ] }, - "execution_count": 111, + "execution_count": 1013, "metadata": {}, "output_type": "execute_result" } @@ -2010,17 +2014,17 @@ }, { "cell_type": "code", - "execution_count": 112, + "execution_count": 1014, "id": "657b1f13-ffcc-44c6-84f1-398fa2fcdac7", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 11.2: .060 seconds, answer 232454623677743 ok" + "Puzzle 11.2: .057 seconds, answer 232454623677743 ok" ] }, - "execution_count": 112, + "execution_count": 1014, "metadata": {}, "output_type": "execute_result" } @@ -2050,7 +2054,7 @@ }, { "cell_type": "code", - "execution_count": 115, + "execution_count": 1017, "id": "8161ee7e-76e3-499a-abf8-a607991c9602", "metadata": {}, "outputs": [ @@ -2089,7 +2093,7 @@ }, { "cell_type": "code", - "execution_count": 117, + "execution_count": 1019, "id": "79f91f38-e325-44f2-9e53-b64ce12d9d35", "metadata": {}, "outputs": [], @@ -2118,7 +2122,7 @@ }, { "cell_type": "code", - "execution_count": 119, + "execution_count": 1021, "id": "1fbabbfb-50c8-4197-8517-e7cee9582765", "metadata": {}, "outputs": [], @@ -2142,17 +2146,17 @@ }, { "cell_type": "code", - "execution_count": 120, + "execution_count": 1022, "id": "cdaf655b-d12c-4973-b19b-3132e5e691c6", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 12.1: .033 seconds, answer 1402544 ok" + "Puzzle 12.1: .031 seconds, answer 1402544 ok" ] }, - "execution_count": 120, + "execution_count": 1022, "metadata": {}, "output_type": "execute_result" } @@ -2192,7 +2196,7 @@ }, { "cell_type": "code", - "execution_count": 122, + "execution_count": 1024, "id": "38c30e15-3a33-40c2-b734-163a15af7a8a", "metadata": {}, "outputs": [], @@ -2215,17 +2219,17 @@ }, { "cell_type": "code", - "execution_count": 123, + "execution_count": 1025, "id": "72175812-dcd0-4f1b-9efa-0dceeeafa609", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 12.1: .051 seconds, answer 1402544 ok" + "Puzzle 12.1: .030 seconds, answer 1402544 ok" ] }, - "execution_count": 123, + "execution_count": 1025, "metadata": {}, "output_type": "execute_result" } @@ -2237,17 +2241,17 @@ }, { "cell_type": "code", - "execution_count": 124, + "execution_count": 1026, "id": "9defcd35-91bc-41d4-a16f-bb7a4ede75e7", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 12.2: .042 seconds, answer 862486 ok" + "Puzzle 12.2: .043 seconds, answer 862486 ok" ] }, - "execution_count": 124, + "execution_count": 1026, "metadata": {}, "output_type": "execute_result" } @@ -2271,7 +2275,7 @@ }, { "cell_type": "code", - "execution_count": 126, + "execution_count": 1028, "id": "e78f45c0-c420-4661-aad2-14e122b4473b", "metadata": {}, "outputs": [ @@ -2335,7 +2339,7 @@ }, { "cell_type": "code", - "execution_count": 128, + "execution_count": 1030, "id": "c2c4bbc9-42cd-483d-8da2-97cf051e93fe", "metadata": {}, "outputs": [], @@ -2359,17 +2363,17 @@ }, { "cell_type": "code", - "execution_count": 129, + "execution_count": 1031, "id": "f5638ed4-1e59-4b9f-b1fc-427d2eb0d036", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 13.1: .010 seconds, answer 29598 ok" + "Puzzle 13.1: .011 seconds, answer 29598 ok" ] }, - "execution_count": 129, + "execution_count": 1031, "metadata": {}, "output_type": "execute_result" } @@ -2406,7 +2410,7 @@ }, { "cell_type": "code", - "execution_count": 131, + "execution_count": 1033, "id": "df8da2ae-52f9-409b-a54f-ad7d21b32e45", "metadata": {}, "outputs": [ @@ -2416,7 +2420,7 @@ "Counter({0: 168, 1: 152})" ] }, - "execution_count": 131, + "execution_count": 1033, "metadata": {}, "output_type": "execute_result" } @@ -2445,7 +2449,7 @@ }, { "cell_type": "code", - "execution_count": 133, + "execution_count": 1035, "id": "6bbd0934-d962-4c93-940b-810651e9e568", "metadata": {}, "outputs": [], @@ -2469,7 +2473,7 @@ }, { "cell_type": "code", - "execution_count": 135, + "execution_count": 1037, "id": "dd38ba4c-44ba-426b-b1c8-0e10adbdd642", "metadata": {}, "outputs": [], @@ -2481,7 +2485,7 @@ }, { "cell_type": "code", - "execution_count": 136, + "execution_count": 1038, "id": "9f578b3e-6b6d-4eb0-9228-c98122a84747", "metadata": {}, "outputs": [ @@ -2491,7 +2495,7 @@ "Puzzle 13.2: .000 seconds, answer 93217456941970 ok" ] }, - "execution_count": 136, + "execution_count": 1038, "metadata": {}, "output_type": "execute_result" } @@ -2511,7 +2515,7 @@ }, { "cell_type": "code", - "execution_count": 138, + "execution_count": 1040, "id": "609ed4ce-548c-4af4-8e09-c621aca0124e", "metadata": {}, "outputs": [ @@ -2521,7 +2525,7 @@ "Puzzle 13.1: .000 seconds, answer 29598 ok" ] }, - "execution_count": 138, + "execution_count": 1040, "metadata": {}, "output_type": "execute_result" } @@ -2543,7 +2547,7 @@ }, { "cell_type": "code", - "execution_count": 140, + "execution_count": 1042, "id": "1a5f5875-426d-47ea-a35a-405c39ced5dd", "metadata": {}, "outputs": [ @@ -2594,7 +2598,7 @@ }, { "cell_type": "code", - "execution_count": 142, + "execution_count": 1044, "id": "be22ac94-7401-4cf6-ab83-e43775536af7", "metadata": {}, "outputs": [], @@ -2616,7 +2620,7 @@ }, { "cell_type": "code", - "execution_count": 143, + "execution_count": 1045, "id": "69093001-79aa-463a-b801-51cd5b4de4eb", "metadata": {}, "outputs": [ @@ -2626,7 +2630,7 @@ "Puzzle 14.1: .000 seconds, answer 216027840 ok" ] }, - "execution_count": 143, + "execution_count": 1045, "metadata": {}, "output_type": "execute_result" } @@ -2654,7 +2658,7 @@ }, { "cell_type": "code", - "execution_count": 145, + "execution_count": 1047, "id": "664c686e-0c3d-43b8-970f-88c0bf47dbf6", "metadata": {}, "outputs": [], @@ -2686,7 +2690,7 @@ }, { "cell_type": "code", - "execution_count": 147, + "execution_count": 1049, "id": "87843969-cb37-4fa5-9788-6a1b71c43521", "metadata": {}, "outputs": [ @@ -2878,42 +2882,42 @@ "\n", "\n", "
\n", - " \n", + " \n", "
\n", - " \n", + " oninput=\"anim75501bc2f88b4b64bc9a979c2943c746.set_frame(parseInt(this.value));\">\n", "
\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", "
\n", - "
\n", - " \n", - " \n", - " Once\n", + " \n", - " \n", - " Loop\n", + " \n", - " \n", + " \n", "
\n", "
\n", "
\n", @@ -2923,9 +2927,9 @@ " /* Instantiate the Animation class. */\n", " /* The IDs given should match those used in the template above. */\n", " (function() {\n", - " var img_id = \"_anim_imgf59c28f9f5894974b4791611a2c64487\";\n", - " var slider_id = \"_anim_sliderf59c28f9f5894974b4791611a2c64487\";\n", - " var loop_select_id = \"_anim_loop_selectf59c28f9f5894974b4791611a2c64487\";\n", + " var img_id = \"_anim_img75501bc2f88b4b64bc9a979c2943c746\";\n", + " var slider_id = \"_anim_slider75501bc2f88b4b64bc9a979c2943c746\";\n", + " var loop_select_id = \"_anim_loop_select75501bc2f88b4b64bc9a979c2943c746\";\n", " var frames = new Array(3);\n", " \n", " frames[0] = \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA8AAAALQCAYAAABfdxm0AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90\\\n", @@ -5697,17 +5701,17 @@ " /* set a timeout to make sure all the above elements are created before\n", " the object is initialized. */\n", " setTimeout(function() {\n", - " animf59c28f9f5894974b4791611a2c64487 = new Animation(frames, img_id, slider_id, 200.0,\n", + " anim75501bc2f88b4b64bc9a979c2943c746 = new Animation(frames, img_id, slider_id, 200.0,\n", " loop_select_id);\n", " }, 0);\n", " })()\n", "\n" ], "text/plain": [ - "" + "" ] }, - "execution_count": 147, + "execution_count": 1049, "metadata": {}, "output_type": "execute_result" } @@ -5728,7 +5732,7 @@ }, { "cell_type": "code", - "execution_count": 149, + "execution_count": 1051, "id": "9563d49c-54a3-439f-a833-f48c2a070609", "metadata": {}, "outputs": [], @@ -5745,7 +5749,7 @@ }, { "cell_type": "code", - "execution_count": 150, + "execution_count": 1052, "id": "ab8c7e3b-f400-4976-ad0d-5f92cbadec02", "metadata": {}, "outputs": [ @@ -5937,42 +5941,42 @@ "\n", "\n", "
\n", - " \n", + " \n", "
\n", - " \n", + " oninput=\"anima2955861de624838a41958e304b17493.set_frame(parseInt(this.value));\">\n", "
\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", "
\n", - "
\n", - " \n", - " \n", - " Once\n", + " \n", - " \n", - " Loop\n", + " \n", - " \n", + " \n", "
\n", "
\n", "
\n", @@ -5982,9 +5986,9 @@ " /* Instantiate the Animation class. */\n", " /* The IDs given should match those used in the template above. */\n", " (function() {\n", - " var img_id = \"_anim_img341b36c396fc4a0cb12fe324af161d71\";\n", - " var slider_id = \"_anim_slider341b36c396fc4a0cb12fe324af161d71\";\n", - " var loop_select_id = \"_anim_loop_select341b36c396fc4a0cb12fe324af161d71\";\n", + " var img_id = \"_anim_imga2955861de624838a41958e304b17493\";\n", + " var slider_id = \"_anim_slidera2955861de624838a41958e304b17493\";\n", + " var loop_select_id = \"_anim_loop_selecta2955861de624838a41958e304b17493\";\n", " var frames = new Array(1);\n", " \n", " frames[0] = \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA8AAAALQCAYAAABfdxm0AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90\\\n", @@ -6662,17 +6666,17 @@ " /* set a timeout to make sure all the above elements are created before\n", " the object is initialized. */\n", " setTimeout(function() {\n", - " anim341b36c396fc4a0cb12fe324af161d71 = new Animation(frames, img_id, slider_id, 200.0,\n", + " anima2955861de624838a41958e304b17493 = new Animation(frames, img_id, slider_id, 200.0,\n", " loop_select_id);\n", " }, 0);\n", " })()\n", "\n" ], "text/plain": [ - "" + "" ] }, - "execution_count": 150, + "execution_count": 1052, "metadata": {}, "output_type": "execute_result" } @@ -6694,17 +6698,17 @@ }, { "cell_type": "code", - "execution_count": 152, + "execution_count": 1054, "id": "75434bc8-35ae-4d8b-b747-01d773472541", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 14.2: 1.825 seconds, answer 6876 ok" + "Puzzle 14.2: 1.819 seconds, answer 6876 ok" ] }, - "execution_count": 152, + "execution_count": 1054, "metadata": {}, "output_type": "execute_result" } @@ -6726,7 +6730,7 @@ }, { "cell_type": "code", - "execution_count": 154, + "execution_count": 1056, "id": "20be45ec-f6fc-472c-9b49-872b7334528c", "metadata": {}, "outputs": [ @@ -6777,7 +6781,7 @@ }, { "cell_type": "code", - "execution_count": 156, + "execution_count": 1058, "id": "248d51c0-424e-4bbb-bbf4-37cdc18313e1", "metadata": {}, "outputs": [], @@ -6813,7 +6817,7 @@ }, { "cell_type": "code", - "execution_count": 157, + "execution_count": 1059, "id": "52e93218-6ac2-4cf7-aced-f4f3a3df77b5", "metadata": {}, "outputs": [ @@ -6823,7 +6827,7 @@ "Puzzle 15.1: .025 seconds, answer 1563092 ok" ] }, - "execution_count": 157, + "execution_count": 1059, "metadata": {}, "output_type": "execute_result" } @@ -6852,7 +6856,7 @@ }, { "cell_type": "code", - "execution_count": 159, + "execution_count": 1061, "id": "2d9afbc1-75b2-479d-81fc-fbab69d25753", "metadata": {}, "outputs": [], @@ -6890,17 +6894,17 @@ }, { "cell_type": "code", - "execution_count": 160, + "execution_count": 1062, "id": "7af49bbf-dd10-4221-9096-6f548dec44c0", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 15.1: .028 seconds, answer 1563092 ok" + "Puzzle 15.1: .029 seconds, answer 1563092 ok" ] }, - "execution_count": 160, + "execution_count": 1062, "metadata": {}, "output_type": "execute_result" } @@ -6912,17 +6916,17 @@ }, { "cell_type": "code", - "execution_count": 161, + "execution_count": 1063, "id": "99246602-a51e-41aa-a7e9-7cdbc8d449ca", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 15.2: .041 seconds, answer 1582688 ok" + "Puzzle 15.2: .042 seconds, answer 1582688 ok" ] }, - "execution_count": 161, + "execution_count": 1063, "metadata": {}, "output_type": "execute_result" } @@ -6942,7 +6946,7 @@ }, { "cell_type": "code", - "execution_count": 163, + "execution_count": 1065, "id": "47c99f0f-ab65-4ae1-a308-42668feacdd5", "metadata": {}, "outputs": [ @@ -6995,7 +6999,7 @@ }, { "cell_type": "code", - "execution_count": 166, + "execution_count": 1068, "id": "03255fd5-95d9-4a90-b1bb-abdf6bbf1d85", "metadata": {}, "outputs": [ @@ -7040,7 +7044,7 @@ }, { "cell_type": "code", - "execution_count": 168, + "execution_count": 1070, "id": "e6e4bfba-0170-436a-961b-d4749f2cd66e", "metadata": {}, "outputs": [], @@ -7073,17 +7077,17 @@ }, { "cell_type": "code", - "execution_count": 169, + "execution_count": 1071, "id": "4974c14c-86da-4b86-a55c-6ae8781df207", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 16.1: .144 seconds, answer 103512 ok" + "Puzzle 16.1: .139 seconds, answer 103512 ok" ] }, - "execution_count": 169, + "execution_count": 1071, "metadata": {}, "output_type": "execute_result" } @@ -7105,7 +7109,7 @@ }, { "cell_type": "code", - "execution_count": 171, + "execution_count": 1073, "id": "692abfea-f9c8-477c-8369-386cdd2a7606", "metadata": {}, "outputs": [], @@ -7137,17 +7141,17 @@ }, { "cell_type": "code", - "execution_count": 172, + "execution_count": 1074, "id": "ea9bf9f3-0e6b-4949-a641-6b3db2fd9d32", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 16.2: .846 seconds, answer 554 ok" + "Puzzle 16.2: .982 seconds, answer 554 ok" ] }, - "execution_count": 172, + "execution_count": 1074, "metadata": {}, "output_type": "execute_result" } @@ -7169,7 +7173,7 @@ }, { "cell_type": "code", - "execution_count": 174, + "execution_count": 1076, "id": "50fd3cb8-0a6f-4edd-b5cb-f7b1e6f9d987", "metadata": {}, "outputs": [ @@ -7213,7 +7217,7 @@ }, { "cell_type": "code", - "execution_count": 175, + "execution_count": 1077, "id": "c23b8a44-e352-4a30-abe5-3c939ffc743c", "metadata": {}, "outputs": [ @@ -7223,7 +7227,7 @@ "Computer(A=52042868, B=0, C=0, prog=[2, 4, 1, 7, 7, 5, 0, 3, 4, 4, 1, 7, 5, 5, 3, 0])" ] }, - "execution_count": 175, + "execution_count": 1077, "metadata": {}, "output_type": "execute_result" } @@ -7244,7 +7248,7 @@ }, { "cell_type": "code", - "execution_count": 177, + "execution_count": 1079, "id": "d98f88cc-c435-43fc-bcb5-52e6dd70fdb1", "metadata": {}, "outputs": [], @@ -7279,7 +7283,7 @@ }, { "cell_type": "code", - "execution_count": 179, + "execution_count": 1081, "id": "860f24e5-92ad-4361-8920-102ebc573598", "metadata": {}, "outputs": [ @@ -7289,7 +7293,7 @@ "Puzzle 17.1: .000 seconds, answer 2,1,0,1,7,2,5,0,3 ok" ] }, - "execution_count": 179, + "execution_count": 1081, "metadata": {}, "output_type": "execute_result" } @@ -7333,7 +7337,7 @@ }, { "cell_type": "code", - "execution_count": 181, + "execution_count": 1083, "id": "bb745303-dd20-486f-bbdd-7ae77f995c2c", "metadata": {}, "outputs": [], @@ -7345,7 +7349,7 @@ }, { "cell_type": "code", - "execution_count": 182, + "execution_count": 1084, "id": "54ac9b9c-70d9-4356-91c5-40fb285634b4", "metadata": {}, "outputs": [ @@ -7355,7 +7359,7 @@ "[2, 4, 1, 7, 7, 5, 0, 3, 4, 4, 1, 7, 5, 5, 3, 0]" ] }, - "execution_count": 182, + "execution_count": 1084, "metadata": {}, "output_type": "execute_result" } @@ -7366,7 +7370,7 @@ }, { "cell_type": "code", - "execution_count": 183, + "execution_count": 1085, "id": "36d89d9a-c8fc-41be-820b-cb13e40793c0", "metadata": {}, "outputs": [ @@ -7376,7 +7380,7 @@ "[0]" ] }, - "execution_count": 183, + "execution_count": 1085, "metadata": {}, "output_type": "execute_result" } @@ -7387,7 +7391,7 @@ }, { "cell_type": "code", - "execution_count": 184, + "execution_count": 1086, "id": "892fef38-5f9b-4370-a242-f7a10df5487b", "metadata": {}, "outputs": [ @@ -7397,7 +7401,7 @@ "[3, 0]" ] }, - "execution_count": 184, + "execution_count": 1086, "metadata": {}, "output_type": "execute_result" } @@ -7408,7 +7412,7 @@ }, { "cell_type": "code", - "execution_count": 185, + "execution_count": 1087, "id": "b3d11d5e-30c2-419f-bc11-3f26fbdddfbb", "metadata": {}, "outputs": [ @@ -7418,7 +7422,7 @@ "[5, 3, 0]" ] }, - "execution_count": 185, + "execution_count": 1087, "metadata": {}, "output_type": "execute_result" } @@ -7443,17 +7447,17 @@ }, { "cell_type": "code", - "execution_count": 187, + "execution_count": 1089, "id": "a49c6de9-4e6b-47e5-bcf0-2972a95c1af3", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 17.2: .024 seconds, answer 267265166222235 ok" + "Puzzle 17.2: .004 seconds, answer 267265166222235 ok" ] }, - "execution_count": 187, + "execution_count": 1089, "metadata": {}, "output_type": "execute_result" } @@ -7484,7 +7488,7 @@ }, { "cell_type": "code", - "execution_count": 189, + "execution_count": 1091, "id": "d14e1966-2feb-4553-9a0a-12595ef4f7d7", "metadata": {}, "outputs": [ @@ -7539,7 +7543,7 @@ }, { "cell_type": "code", - "execution_count": 191, + "execution_count": 1093, "id": "83af4751-38c9-4830-a2fa-78515b59bc97", "metadata": {}, "outputs": [], @@ -7554,7 +7558,7 @@ }, { "cell_type": "code", - "execution_count": 192, + "execution_count": 1094, "id": "29da25e2-f3c2-43e3-8769-1d4fcecb807b", "metadata": {}, "outputs": [ @@ -7564,7 +7568,7 @@ "Puzzle 18.1: .014 seconds, answer 344 ok" ] }, - "execution_count": 192, + "execution_count": 1094, "metadata": {}, "output_type": "execute_result" } @@ -7588,7 +7592,7 @@ }, { "cell_type": "code", - "execution_count": 194, + "execution_count": 1096, "id": "4c0a8dcb-c3af-45e7-9273-8776e8c3ea1d", "metadata": {}, "outputs": [], @@ -7607,17 +7611,17 @@ }, { "cell_type": "code", - "execution_count": 195, + "execution_count": 1097, "id": "22371144-5d51-440a-918f-a63de73b13ad", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 18.2: .032 seconds, answer 46,18 ok" + "Puzzle 18.2: .042 seconds, answer 46,18 ok" ] }, - "execution_count": 195, + "execution_count": 1097, "metadata": {}, "output_type": "execute_result" } @@ -7649,7 +7653,7 @@ }, { "cell_type": "code", - "execution_count": 198, + "execution_count": 1100, "id": "689df92b-92d7-44e6-8b4e-d67bf3f153df", "metadata": {}, "outputs": [ @@ -7693,7 +7697,7 @@ }, { "cell_type": "code", - "execution_count": 200, + "execution_count": 1102, "id": "e0b96545-5f60-4c8e-9a0f-c77608c19128", "metadata": {}, "outputs": [], @@ -7707,17 +7711,17 @@ }, { "cell_type": "code", - "execution_count": 201, + "execution_count": 1103, "id": "3c3fba1b-d3e5-494e-aad0-42ca0566ae1f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 19.1: .039 seconds, answer 242 ok" + "Puzzle 19.1: .046 seconds, answer 242 ok" ] }, - "execution_count": 201, + "execution_count": 1103, "metadata": {}, "output_type": "execute_result" } @@ -7739,7 +7743,7 @@ }, { "cell_type": "code", - "execution_count": 203, + "execution_count": 1105, "id": "77d4fae1-d506-4733-9bb2-467619012f97", "metadata": {}, "outputs": [], @@ -7754,17 +7758,17 @@ }, { "cell_type": "code", - "execution_count": 204, + "execution_count": 1106, "id": "14116eca-0b0f-484a-a169-9726e4ac7fbf", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 19.2: .184 seconds, answer 595975512785325 ok" + "Puzzle 19.2: .215 seconds, answer 595975512785325 ok" ] }, - "execution_count": 204, + "execution_count": 1106, "metadata": {}, "output_type": "execute_result" } @@ -7784,7 +7788,7 @@ }, { "cell_type": "code", - "execution_count": 206, + "execution_count": 1108, "id": "f992b197-be14-47dc-8678-10cc63a1afd7", "metadata": {}, "outputs": [], @@ -7803,17 +7807,17 @@ }, { "cell_type": "code", - "execution_count": 208, + "execution_count": 1110, "id": "57296f79-d0a0-4de3-bb1c-b3ed84ba1a59", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 19.1: .004 seconds, answer 242 ok" + "Puzzle 19.1: .003 seconds, answer 242 ok" ] }, - "execution_count": 208, + "execution_count": 1110, "metadata": {}, "output_type": "execute_result" } @@ -7840,7 +7844,7 @@ }, { "cell_type": "code", - "execution_count": 210, + "execution_count": 1112, "id": "156dcbf7-79ec-41a7-a9f2-397a827b9856", "metadata": {}, "outputs": [ @@ -7883,7 +7887,7 @@ }, { "cell_type": "code", - "execution_count": 212, + "execution_count": 1114, "id": "4c4ef05c-b548-49f9-b092-847e9752e745", "metadata": {}, "outputs": [], @@ -7913,17 +7917,17 @@ }, { "cell_type": "code", - "execution_count": 213, + "execution_count": 1115, "id": "1bbd8b72-c503-4384-aaea-a5bed45a4491", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 20.1: .028 seconds, answer 1343 ok" + "Puzzle 20.1: .037 seconds, answer 1343 ok" ] }, - "execution_count": 213, + "execution_count": 1115, "metadata": {}, "output_type": "execute_result" } @@ -7950,17 +7954,17 @@ }, { "cell_type": "code", - "execution_count": 215, + "execution_count": 1117, "id": "d370e24c-9b82-4415-82a5-7afe2be17654", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 20.2: .756 seconds, answer 982891 ok" + "Puzzle 20.2: .822 seconds, answer 982891 ok" ] }, - "execution_count": 215, + "execution_count": 1117, "metadata": {}, "output_type": "execute_result" } @@ -7995,7 +7999,7 @@ }, { "cell_type": "code", - "execution_count": 217, + "execution_count": 1119, "id": "332e9c72-db9a-4b90-a649-45f7bf955e84", "metadata": {}, "outputs": [ @@ -8005,7 +8009,7 @@ "Puzzle 20.1: .022 seconds, answer 1343 ok" ] }, - "execution_count": 217, + "execution_count": 1119, "metadata": {}, "output_type": "execute_result" } @@ -8027,7 +8031,7 @@ }, { "cell_type": "code", - "execution_count": 219, + "execution_count": 1121, "id": "9d0eea9f-9d8f-4410-97ec-13d8b136925b", "metadata": {}, "outputs": [ @@ -8069,7 +8073,7 @@ " | 0 | A |\n", " +---+---+\n", " \n", - "Long story short: it turns out the robot's remote keypad is *also* inaccessible, and we end up needing **three robots**, each pressing buttons on the next keypad, so there are four levels of button pressing all together:\n", + "Long story short: it turns out the robot's remote keypad is *also* inaccessible, and we end up needing **three robots**, each pressing buttons on the next keypad, so there are **four levels** of button pressing all together:\n", "\n", "- You press some buttons on Robot 3's remote keypad (e.g. \">\"...)\n", @@ -8095,7 +8099,7 @@ }, { "cell_type": "code", - "execution_count": 221, + "execution_count": 1123, "id": "779c6b4c-ceb0-49ac-96f2-4700835c70ea", "metadata": {}, "outputs": [], @@ -8121,7 +8125,7 @@ }, { "cell_type": "code", - "execution_count": 222, + "execution_count": 1125, "id": "c915ada2-9dfe-42fe-bd08-855ff5d0e837", "metadata": {}, "outputs": [], @@ -8140,7 +8144,7 @@ }, { "cell_type": "code", - "execution_count": 446, + "execution_count": 1126, "id": "391f6120-6373-43f2-b697-585c90e45e54", "metadata": {}, "outputs": [], @@ -8160,7 +8164,7 @@ }, { "cell_type": "code", - "execution_count": 449, + "execution_count": 1128, "id": "1e2e8c59-744f-4f36-9251-c8ea5fd60aed", "metadata": {}, "outputs": [], @@ -8175,12 +8179,12 @@ "id": "975b5719-9afc-4b0a-9e07-c1c2b38059f7", "metadata": {}, "source": [ - "And here's how we compute the minimum number of keypresses. Normally I would do this with a `@cache` decorator, but I was encountering **bugs** doing that and got confused, so I refactored to explicitly create a cache of path lengths saying how many presses it takes at each level to command a single button press, getting you from the start button to the destination button. This made debugging slightly easier for me, or maybe it was just starting over that made it easier." + "And here's how we compute the minimum number of keypresses. Normally I would do this with a `@cache` decorator, but I was encountering **bugs** doing that and got confused (off-by-one errors, maybe?), so I refactored to explicitly create a cache of path lengths saying how many presses it takes at each level to command a single button press, getting you from the start button to the destination button. This made debugging slightly easier for me, or maybe it was just starting over that made it easier." ] }, { "cell_type": "code", - "execution_count": 489, + "execution_count": 1130, "id": "704ade67-31e6-4f39-b48c-0a7185c42c48", "metadata": {}, "outputs": [], @@ -8205,7 +8209,7 @@ }, { "cell_type": "code", - "execution_count": 491, + "execution_count": 1131, "id": "4d8c8659-52d3-4349-8465-7003e880502f", "metadata": {}, "outputs": [], @@ -8223,17 +8227,17 @@ }, { "cell_type": "code", - "execution_count": 493, + "execution_count": 1133, "id": "393a8c6b-6a1c-4495-aad5-92f48711fbf1", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 21.1: .004 seconds, answer 205160 ok" + "Puzzle 21.1: .002 seconds, answer 205160 ok" ] }, - "execution_count": 493, + "execution_count": 1133, "metadata": {}, "output_type": "execute_result" } @@ -8255,17 +8259,17 @@ }, { "cell_type": "code", - "execution_count": 495, + "execution_count": 1135, "id": "563c5959-692d-4368-8c0b-469fa0142678", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 21.2: .016 seconds, answer 252473394928452 ok" + "Puzzle 21.2: .008 seconds, answer 252473394928452 ok" ] }, - "execution_count": 495, + "execution_count": 1135, "metadata": {}, "output_type": "execute_result" } @@ -8295,7 +8299,7 @@ }, { "cell_type": "code", - "execution_count": 230, + "execution_count": 1138, "id": "2c1e7612-4ec5-4ce1-b591-5c3a14f8ea61", "metadata": {}, "outputs": [ @@ -8346,7 +8350,7 @@ }, { "cell_type": "code", - "execution_count": 232, + "execution_count": 1140, "id": "3807adbc-261a-4108-88ba-6e2b061526b5", "metadata": {}, "outputs": [], @@ -8362,17 +8366,17 @@ }, { "cell_type": "code", - "execution_count": 233, + "execution_count": 1141, "id": "fce754cd-f6da-4e7d-b406-3314c9c28ca8", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 22.1: .314 seconds, answer 14273043166 ok" + "Puzzle 22.1: .319 seconds, answer 14273043166 ok" ] }, - "execution_count": 233, + "execution_count": 1141, "metadata": {}, "output_type": "execute_result" } @@ -8416,7 +8420,7 @@ }, { "cell_type": "code", - "execution_count": 235, + "execution_count": 1369, "id": "cbbb4793-b13d-4a95-ba03-673b3ebaa229", "metadata": {}, "outputs": [], @@ -8449,17 +8453,17 @@ }, { "cell_type": "code", - "execution_count": 236, + "execution_count": 1371, "id": "34eaf7fe-fe9b-4858-b1e8-e4c3713ea093", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 22.2: 1.259 seconds, answer 1667 ok" + "Puzzle 22.2: 1.294 seconds, answer 1667 ok" ] }, - "execution_count": 236, + "execution_count": 1371, "metadata": {}, "output_type": "execute_result" } @@ -8479,7 +8483,7 @@ }, { "cell_type": "code", - "execution_count": 238, + "execution_count": 1146, "id": "a2da8c78-d240-4c52-a83a-f3599f4f69a4", "metadata": {}, "outputs": [ @@ -8489,7 +8493,7 @@ "(-3, 2, -1, 2)" ] }, - "execution_count": 238, + "execution_count": 1146, "metadata": {}, "output_type": "execute_result" } @@ -8510,7 +8514,7 @@ }, { "cell_type": "code", - "execution_count": 240, + "execution_count": 1383, "id": "9de3f365-c546-494a-a18c-2ae58d88792b", "metadata": {}, "outputs": [ @@ -8518,14 +8522,22 @@ "name": "stdout", "output_type": "stream", "text": [ - "271 monkeys paid 1667 total at prices: {0: 0, 1: 0, 2: 0, 3: 43, 4: 34, 5: 33, 6: 32, 7: 37, 8: 42, 9: 50}, mean: 6.2\n" + "271 monkeys (16%), price 6.2 mean: {1: 0, 2: 0, 3: 43, 4: 34, 5: 33, 6: 32, 7: 37, 8: 42, 9: 50}\n" ] } ], "source": [ "prices = [p for secret in secrets for d, p in price_timeline(secret).items() if d == best]\n", - "histo = {p: prices.count(p) for p in range(10)}\n", - "print(f'{len(prices)} monkeys paid {sum(prices)} total at prices: {histo}, mean: {mean(prices):3.1f}')" + "histo = {p: prices.count(p) for p in range(1, 10)}\n", + "print(f'{len(prices)} monkeys ({len(prices)/len(secrets):.0%}), price {mean(prices):3.1f} mean: {histo}')" + ] + }, + { + "cell_type": "markdown", + "id": "1fa741c6-ecf7-4459-a017-ffa574352d7e", + "metadata": {}, + "source": [ + "We do pretty well on prices, getting a lot of 8 and 9 prices, but only 16% of monkeys every get this sequence of price deltas." ] }, { @@ -8535,12 +8547,12 @@ "source": [ "# [Day 23](https://adventofcode.com/2024/day/23): LAN Party\n", "\n", - "We see that there is a LAN party scheduled for today. Our input is a map of bidirectional connections between computers:" + "We see that there is a LAN party scheduled for today. Our input is a network map of bidirectional connections between computers:" ] }, { "cell_type": "code", - "execution_count": 242, + "execution_count": 1393, "id": "85f5b145-8c5e-448c-8b45-ad5750252ff2", "metadata": {}, "outputs": [ @@ -8576,7 +8588,7 @@ } ], "source": [ - "connections = parse(23, atoms)" + "network = parse(23, atoms)" ] }, { @@ -8591,7 +8603,7 @@ }, { "cell_type": "code", - "execution_count": 244, + "execution_count": 1152, "id": "289d2325-1e58-41f5-b4b2-b90ae26e7887", "metadata": {}, "outputs": [], @@ -8616,24 +8628,24 @@ }, { "cell_type": "code", - "execution_count": 245, + "execution_count": 1395, "id": "6425577d-4ca9-45de-9698-cd9b026f7ce6", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 23.1: .001 seconds, answer 1170 ok" + "Puzzle 23.1: .003 seconds, answer 1170 ok" ] }, - "execution_count": 245, + "execution_count": 1395, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(23.1, 1170, lambda:\n", - " len(triples_starting_with(bidirected_graph(connections), 't')))" + " len(triples_starting_with(bidirected_graph(network), 't')))" ] }, { @@ -8648,20 +8660,19 @@ }, { "cell_type": "code", - "execution_count": 247, + "execution_count": 1386, "id": "88811073-22b2-4378-afa5-9d38462c63b5", "metadata": {}, "outputs": [], "source": [ "def maximum_clique(graph) -> Clique: \n", " \"\"\"The clique in `graph` with the most members.\"\"\"\n", - " return max((expand_clique(A, graph) for A in graph), key=len)\n", + " return max((expand_clique(A, graph, clique=set()) for A in graph), key=len)\n", "\n", "def password(names) -> str: return ','.join(sorted(names))\n", " \n", - "def expand_clique(A, graph, clique=None) -> Clique:\n", - " \"\"\"The largest clique in the graph that has A as a member.\"\"\"\n", - " if clique is None: clique = set() # If clique wasn't started yet, start it here\n", + "def expand_clique(A, graph, clique) -> Clique:\n", + " \"\"\"Expand out from A, adding nodes to `clique` as long as they form a clique.\"\"\"\n", " clique.add(A)\n", " for B in graph[A]:\n", " if B not in clique and clique.issubset(graph[B]):\n", @@ -8671,24 +8682,36 @@ }, { "cell_type": "code", - "execution_count": 248, + "execution_count": 1397, "id": "0b5f08ac-18e2-4933-9737-cdbc842c5809", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 23.2: .003 seconds, answer bo,dd,eq,ik,lo,lu,ph,ro,rr,rw,uo,wx,yg ok" + "Puzzle 23.2: .008 seconds, answer bo,dd,eq,ik,lo,lu,ph,ro,rr,rw,uo,wx,yg ok" ] }, - "execution_count": 248, + "execution_count": 1397, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(23.2, 'bo,dd,eq,ik,lo,lu,ph,ro,rr,rw,uo,wx,yg', lambda:\n", - " password(maximum_clique(bidirected_graph(connections))))" + " password(maximum_clique(bidirected_graph(network))))" + ] + }, + { + "cell_type": "markdown", + "id": "afa122bf-4459-49c8-98bf-ddc3667fa50c", + "metadata": {}, + "source": [ + "I got the right answer, and it was very quick (for me), but now I'm not sure it handles all possible inputs. Consider the following network, where `{BCD}` means the three nodes form a (non-maximal) clique, and a dashed line means all nodes on each side are connected.\n", + "\n", + " {BCD}--{A}--{EF}\n", + "\n", + "The call to `expand_cliqe(A, ...)` might return either `{ABCD}` or `{AEF}`, so it might miss the maximum clique. For this case, `expand_cliqe(B, ...)` will indeed always `{ABCD}`. But I'm not quite sure there can't be some more complex configuration where my algorithm fails." ] }, { @@ -8698,14 +8721,16 @@ "source": [ "# [Day 24](https://adventofcode.com/2024/day/24): Crossed Wire\n", "\n", - "Today we are trying to help the historian to debug a malfunctioning monitoring device, which consistes of some wires and logic gates. The day's input described the signals (0 or 1) on some input wires, and the gates, which each have two input wires and one output wire, and a Boolean operator. There are two types of inputs: an input wire is described with itrs name and its bit value: `x00: 1`, and a logic gate is described with the two input wire names, the operation, and the output wire name: `x00 AND y00 -> z00`.\n", + "Today we are trying to help the historian to debug a malfunctioning monitoring device, which consistes of some wires and logic gates. Some of the wires have been misrouted. The day's input described the connections in the device. There are two types of inputs: an input wire is described with its name and its bit value: `x00: 1`, and a logic gate is described with the two input wire names, the operation, and the output wire name: `x00 AND y00 -> z00`.\n", "\n", - "I'll parse each line as a sequence of atoms, and assemble them into a `Device`, a subclass of `dict` where the keys are wire names and the values are either bits or gates." + "\n", + "\n", + "For now I'll just parse each line as a sequence of atoms: " ] }, { "cell_type": "code", - "execution_count": 250, + "execution_count": 1158, "id": "47421581-71df-4c72-a62e-c40d0596fdbb", "metadata": {}, "outputs": [ @@ -8740,6 +8765,26 @@ ] } ], + "source": [ + "connections = parse(24, atoms)" + ] + }, + { + "cell_type": "markdown", + "id": "354dd8da-2737-45c2-af8c-b4b30584ae9a", + "metadata": {}, + "source": [ + "### Part 1: Simulate the system of gates and wires. What decimal number does it output on the wires starting with z?\n", + "\n", + "We can't just treat the device as a program where we execute statements in order, because in a line like `z01 = bfn XOR y33`, the values of `bfn` and `y33` may not yet be determined. But we can execute *backwards*, as a [dataflow architecture](https://en.wikipedia.org/wiki/Dataflow_architecture). To go backwards we'll need a mapping from each output wire to where it comes from: either a bit value or a gate. I'll define `Device` as a subclass of `dict` where the keys are wire names and the values are either bits or gates." + ] + }, + { + "cell_type": "code", + "execution_count": 1160, + "id": "43b29260-d912-4cfc-91ce-d303ec1c86df", + "metadata": {}, + "outputs": [], "source": [ "class Device(dict):\n", " \"\"\"A mapping of {wire_name: bit_value_or_gate}, assembled from a device specification.\"\"\"\n", @@ -8749,26 +8794,20 @@ " case (wire, bit): # e.g., ('x00', 1)\n", " self[wire] = bit\n", " case (x, op, y, out): # e.g., ('y33', 'AND', 'x33', 'bfn')\n", - " self[out] = (x, op, y)\n", - " \n", - "device = Device(parse(24, atoms))" + " self[out] = (x, op, y)" ] }, { "cell_type": "markdown", - "id": "25787cce-ef81-4390-9656-5085262f2bfb", + "id": "ff09bc35-43a4-45c1-bc00-c9cd6a1d7f69", "metadata": {}, "source": [ - "### Part 1: Simulate the system of gates and wires. What decimal number does it output on the wires starting with z?\n", - "\n", - "We can't just treat the device as a program where we execute statements in order, because in a line like `z01 = bfn XOR y33`, the values of `bfn` and `y33` may not yet be determined. But we can execute *backwards*, as a [dataflow architecture](https://en.wikipedia.org/wiki/Dataflow_architecture). \n", - "\n", - "The function `simulate` does that. We start from the outputs (the wires whose first letter is `'z'`) and try to **get** their values. If the value is a bit, great, we got it. If the value is a gate, then we recursively **get** the values of both input wires to the gate, and perform the gate's boolean operation on them. When we're done calculating all the output variables, the function `simulate` returns their values as a string of `'0'` or `'1'` characters." + "Next, the function `simulate` does the dataflow computation. We start from the outputs (the wires whose first letter is `'z'`) and try to **get** their values. If the value is a bit, great, we got it. If the value is a gate, then we recursively **get** the values of both input wires to the gate, and perform the gate's boolean operation on them. When we're done calculating all the output variables, the function `simulate` returns their values as a string of `'0'` or `'1'` characters." ] }, { "cell_type": "code", - "execution_count": 252, + "execution_count": 1162, "id": "a9a4780f-6033-452f-b49c-74b97c9e2440", "metadata": {}, "outputs": [], @@ -8783,14 +8822,14 @@ "\n", "operators = dict(XOR=operator.xor, AND=min, OR=max)\n", "\n", - "def wires(device, letter) -> List[str]: \n", + "def wires(device: Device, letter: str) -> List[str]: \n", " \"\"\"The names of all the wires that start with the given letter, in sorted order.\"\"\"\n", " return sorted([w for w in device if w.startswith(letter)], reverse=True)" ] }, { "cell_type": "code", - "execution_count": 253, + "execution_count": 1163, "id": "72437439-dddf-4202-9944-36e796800304", "metadata": {}, "outputs": [ @@ -8800,14 +8839,14 @@ "Puzzle 24.1: .001 seconds, answer 36035961805936 ok" ] }, - "execution_count": 253, + "execution_count": 1163, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(24.1, 36035961805936, lambda:\n", - " int(simulate(device), base=2))" + " int(simulate(Device(connections)), base=2))" ] }, { @@ -8815,7 +8854,7 @@ "id": "7ddc7897-5ff2-46bc-999d-302c92c137da", "metadata": {}, "source": [ - "At first I had a **bug**. I fell victim to one of the [**classic blunders**](https://youtu.be/RWW6aDpUvbQ?si=0uvZFEYgY9i_441N): using the wrong [**endianness**](https://en.wikipedia.org/wiki/Endianness) of my bits. After re-reading the puzzle description, I added the `reverse=True` to `wires`." + "At first I fell victim to one of the [**classic blunders**](https://youtu.be/RWW6aDpUvbQ?si=0uvZFEYgY9i_441N): using the wrong [**endianness**](https://en.wikipedia.org/wiki/Endianness) of my bits. After re-reading the puzzle description, I fixed the **bug** by adding `reverse=True` to `wires`." ] }, { @@ -8837,17 +8876,20 @@ " - If I chose random numbers it might take a long time to isolate the faults.\n", " - It is easy to identify faulty output (`z`) values; trickier to identify faults in internal gates.\n", " - I could test the one-bit adders one at a time (with and without carry). But I don;t know if that would always work.\n", - "4) I know a bit about how an adder circuit is normally built; I can walk the graph of gates and see if it conforms to what I think it should be.\n", - " - When it isn't, I can swap wires into place and keep looking.\n", + "4) I know a bit about how an adder circuit is normally built; if our device is like that, we should be able to see if each bit conforms to the pattern.\n", + " - When it doesn't, I can swap wires to make it conform.\n", " - I don't know if this approach will find all faults.\n", + " - It could be that the device is a correct adder, but is built in a non-conventional way.\n", " \n", - "Here's a picture of a full adder; we'd have one of these for each output wire (except for `z00`, which doesn't have to deal with a carry bit). \n", - "![Adder from Wikipedia](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCXZpXA19TudYZz-S51V6WZ_b1HPAbA-uozACxQdnavllWn9oUrVwID5eOmtOhUhFHZZKadar5TY3os2H-Vs4uiCK92wEERCFSOAamOTwOZTQ_q034zdMUhSmxYNihUHWRIRVwLJVoR7Zo1u7-dPL9gysEifyvQqO8AnTvGv9oEAgkxTZMuVyNVN-D/w400-h245/nbit_1.png) Let's see if this matches the number of gates in our device:" + "Here's a picture of a (one-bit) full adder; we have two XOR gates, two AND gates, and one OR gate for every output wire (except for `z00`, which doesn't have a carry bit). \n", + "![Adder from Wikipedia](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCXZpXA19TudYZz-S51V6WZ_b1HPAbA-uozACxQdnavllWn9oUrVwID5eOmtOhUhFHZZKadar5TY3os2H-Vs4uiCK92wEERCFSOAamOTwOZTQ_q034zdMUhSmxYNihUHWRIRVwLJVoR7Zo1u7-dPL9gysEifyvQqO8AnTvGv9oEAgkxTZMuVyNVN-D/w400-h245/nbit_1.png) \n", + "\n", + "Let's see if this matches the number of gates in our device:" ] }, { "cell_type": "code", - "execution_count": 256, + "execution_count": 1166, "id": "3b41a166-d33b-402b-971b-1dc1d33135ec", "metadata": {}, "outputs": [ @@ -8857,13 +8899,13 @@ "Counter({'AND': 89, 'XOR': 89, 'OR': 44})" ] }, - "execution_count": 256, + "execution_count": 1166, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "Counter(val[1] for val in device.values() if val not in (0, 1))" + "Counter(val[1] for val in Device(connections).values() if val not in (0, 1))" ] }, { @@ -8871,20 +8913,21 @@ "id": "c1f072b2-8c7f-40b2-9712-d0fc0dee62e7", "metadata": {}, "source": [ - "It does match, so I guess our device is implementing this circuit layout, so I'll try approach (4). I basically trace through, checking if the right gates are connected to the right wires. Since we are told that the swaps are one-for-one, and that fixing them gives a valid adder circuit, I take that to mean that the gates all have the right operator; we only have to switch some wires.\n", + "It does match, so I guess our device is probably implementing the conventional circuit layout. Therefore I'll try approach (4). \n", " \n", - "The first trouble I ran into was that the two inputs to a gate can be in either order. It will save trouble to canonicalize this, so that the first input wire is always alphabetically before the second one. The function `canon` enforces this, and I had to redefine `Device` to canonicalize it." + "The first trouble I ran into was that the two inputs to a gate could be in either order. I will canonicalize this, so that the first input wire is always alphabetically before the second one. The function `canon` enforces canonicalization. I'll redefine `Device` to canonicalize gate order, and also to cache the **inverse** mapping: from gates to output wires rather than from output wires to gates/bits." ] }, { "cell_type": "code", - "execution_count": 258, + "execution_count": 1168, "id": "ec8d86d4-8caf-40f2-b516-c7da4acbda19", "metadata": {}, "outputs": [], "source": [ "class Device(dict):\n", - " \"\"\"A mapping of {wire_name: bit_value_or_gate}, assembled from a device specification.\"\"\"\n", + " \"\"\"A mapping of {wire_name: bit_value_or_gate}, assembled from a device specification.\n", + " Also caches the inverse as a dict under self.inverse.\"\"\"\n", " def __init__(self, lines: Tuple[Tuple]):\n", " for line in lines:\n", " match line: \n", @@ -8892,12 +8935,11 @@ " self[wire] = bit\n", " case (x, op, y, out): # e.g., ('y33', 'AND', 'x33', 'bfn')\n", " self[out] = canon(x, op, y) # canonicalize order \n", + " self.inverse = {self[w]: w for w in self if self[w] not in (0, 1)} # Inverse mapping\n", " \n", "def canon(x, op, y) -> Tuple: \n", " \"\"\"The canonical ordering of the two input wires (and the operator).\"\"\"\n", - " return (min(x, y), op, max(x, y))\n", - "\n", - "device = Device(parse(24, atoms, show=0)) # I put 'show=0' so I don't print the inoput file again." + " return (min(x, y), op, max(x, y))" ] }, { @@ -8910,40 +8952,40 @@ }, { "cell_type": "code", - "execution_count": 260, - "id": "2a06af7f-2b9a-4b1f-b9dd-9ec6fb94a1e6", + "execution_count": 1170, + "id": "7ed8f8e6-c3e1-4c22-b812-e1a201afec3d", "metadata": {}, "outputs": [], "source": [ "def find_swaps(device):\n", - " \"\"\"Find all wires that need to be swapped to have the right architecture for an adder.\n", - " This uses a few heuristics to look for how the carry bits are XOR-ed and AND-ed in.\n", - " This may not work on all faulty devices, but it worked on the one we were given.\"\"\"\n", - " device = device.copy()\n", - " inv = {device[w]: w for w in device} # Inverse mapping\n", - " def lookup(x, op, y): return inv.get(canon(x, op, y), None)\n", + " \"\"\"For each bit position in the inputs, x and y, look forward for the\n", + " XOR and AND gates they participate in, then look backwards from the \n", + " corresponding z output, and see where they fail to match up,\n", + " and swap wires accordingly, yielding each swapped wire.\"\"\"\n", + " \n", + " def wire(x, op, y): return device.inverse.get(canon(x, op, y), None)\n", " \n", " for i in range(len(wires(device, 'x'))):\n", " x, y, z = [f'{v}{i:02d}' for v in 'xyz']\n", - " XOR_gate = lookup(x, 'XOR', y)\n", - " AND_gate = lookup(x, 'AND', y)\n", + " XOR_wire = wire(x, 'XOR', y)\n", + " AND_wire = wire(x, 'AND', y)\n", " if x == 'x00':\n", - " carry = AND_gate\n", + " carry = AND_wire\n", " else:\n", - " a, b = carry, XOR_gate\n", - " if not lookup(a, 'XOR', b):\n", - " e, op, f, = device[z]\n", - " a, b = {e, f} ^ {a, b}\n", - " yield from swap(a, b, device, inv)\n", - " elif lookup(a, 'XOR', b) != z:\n", - " yield from swap(z, lookup(a, 'XOR', b), device, inv)\n", - " XOR_gate = lookup(x, 'XOR', y) # After the swap, need to get the right gates\n", - " AND_gate = lookup(x, 'AND', y)\n", - " carry = lookup(carry, 'AND', XOR_gate) # The carry gets propagated through two gates\n", - " carry = lookup(carry, 'OR', AND_gate)\n", + " a, b = carry, XOR_wire\n", + " if not wire(a, 'XOR', b):\n", + " a2, op, b2, = device[z] # Look backwards from z to see if they hook up\n", + " once = [w for w in (a, b, a2, b2) if [a, b, a2, b2].count(w) == 1]\n", + " if len(once) == 2: # Wires that appear once in the two gates; they don't connect properly\n", + " yield from swap(*once, device)\n", + " elif wire(a, 'XOR', b) != z:\n", + " yield from swap(z, wire(a, 'XOR', b), device)\n", + " carry = wire(carry, 'AND', wire(x, 'XOR', y)) # The carry gets propagated through two gates\n", + " carry = wire(carry, 'OR', wire(x, 'AND', y))\n", "\n", - "def swap(a: str, b: str, device: dict, inv: dict) -> Set[str]:\n", + "def swap(a: str, b: str, device: dict) -> Set[str]:\n", " \"\"\"Swap wires `a` and `b` in device (and also update the inverse mapping).\"\"\"\n", + " inv = device.inverse\n", " device[a], device[b] = device[b], device[a]\n", " inv[device[a]], inv[device[b]] = inv[device[b]], inv[device[a]]\n", " return a, b" @@ -8951,7 +8993,7 @@ }, { "cell_type": "code", - "execution_count": 261, + "execution_count": 1171, "id": "e9b87c38-f67c-4948-9af6-251021747e9d", "metadata": {}, "outputs": [ @@ -8961,14 +9003,14 @@ "Puzzle 24.2: .000 seconds, answer jqf,mdd,skh,wpd,wts,z11,z19,z37 ok" ] }, - "execution_count": 261, + "execution_count": 1171, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(24.2, 'jqf,mdd,skh,wpd,wts,z11,z19,z37', lambda:\n", - " ','.join(sorted(find_swaps(device))))" + " ','.join(sorted(find_swaps(Device(connections)))))" ] }, { @@ -8985,7 +9027,7 @@ }, { "cell_type": "code", - "execution_count": 263, + "execution_count": 1173, "id": "f5971853-7139-4f17-bdc5-6c51e12a928d", "metadata": {}, "outputs": [ @@ -9044,29 +9086,29 @@ }, { "cell_type": "code", - "execution_count": 265, + "execution_count": 1175, "id": "5302ac58-91fc-475a-83d9-cea91457df3b", "metadata": {}, "outputs": [], "source": [ "def count_fits(schematics) -> List:\n", - " \"\"\"How many key/lock combinations fit each other.\"\"\"\n", + " \"\"\"Try all key/lock combinations and count how many fit each other.\"\"\"\n", " locks = [heights(s) for s in schematics if s[0] == '#####']\n", " keys = [heights(s) for s in schematics if s[0] != '#####']\n", - " return quantify(can_fit(lock, key) for lock in locks for key in keys)\n", + " return quantify(can_fit(key, lock) for lock in locks for key in keys)\n", " \n", - "def can_fit(lock, key): \n", + "def can_fit(key: Ints, lock: Ints): \n", " \"\"\"The key can fit the lock if the sum of the '#' count in each column is <= 7.\"\"\"\n", " return all(lock[c] + key[c] <= 7 for c in range(5))\n", "\n", "def heights(schematic) -> List[int]:\n", " \"\"\"A counter of {column_number: (number of '#' in that column)}.\"\"\"\n", - " return [column.count('#') for column in T(schematic)]" + " return [column.count('#') for column in T(schematic)] # Remember, `T` is transpose" ] }, { "cell_type": "code", - "execution_count": 266, + "execution_count": 1176, "id": "c415f5c1-76c3-486c-9075-c46a5a8c5bcb", "metadata": {}, "outputs": [], @@ -9076,17 +9118,17 @@ }, { "cell_type": "code", - "execution_count": 267, + "execution_count": 1177, "id": "89c28b74-ed31-4bb5-b463-7177952a95ae", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 25.1: .021 seconds, answer 3196 ok" + "Puzzle 25.1: .022 seconds, answer 3196 ok" ] }, - "execution_count": 267, + "execution_count": 1177, "metadata": {}, "output_type": "execute_result" } @@ -9096,6 +9138,18 @@ " count_fits(schematics))" ] }, + { + "cell_type": "markdown", + "id": "ce1c8e04-5297-4798-969d-3cc9210bfd9a", + "metadata": {}, + "source": [ + "And with that, we're done! \n", + "\n", + "Thanks, [Eric Wastl](https://adventofcode.com/2024/about)!\n", + "\n", + "" + ] + }, { "cell_type": "markdown", "id": "3e78ac0f-5866-4620-8114-1b05b5c44de1", @@ -9103,12 +9157,14 @@ "source": [ "# Summary\n", "\n", - "Here are all the puzzle answers and timings. The median run time is under 10 milliseconds, but 4 puzzles take over a second." + "Here are all the puzzle answers and timings. I got all the puzzles right! And I did it before midnight on December 25th, a rarity for me. \n", + "\n", + "The median run time is under 10 milliseconds, with 4 puzzles taking over a second. I didn't count the time that `parse` takes, but that is less than a millisecond per day." ] }, { "cell_type": "code", - "execution_count": 269, + "execution_count": 1180, "id": "34813fc9-a000-4cd8-88ae-692851b3242c", "metadata": {}, "outputs": [ @@ -9122,53 +9178,53 @@ "Puzzle 2.2: .002 seconds, answer 328 ok\n", "Puzzle 3.1: .001 seconds, answer 156388521 ok\n", "Puzzle 3.2: .000 seconds, answer 75920122 ok\n", - "Puzzle 4.1: .032 seconds, answer 2401 ok\n", - "Puzzle 4.2: .026 seconds, answer 1822 ok\n", + "Puzzle 4.1: .035 seconds, answer 2401 ok\n", + "Puzzle 4.2: .028 seconds, answer 1822 ok\n", "Puzzle 5.1: .001 seconds, answer 5762 ok\n", "Puzzle 5.2: .001 seconds, answer 4130 ok\n", - "Puzzle 6.1: .002 seconds, answer 5329 ok\n", - "Puzzle 6.2: 1.942 seconds, answer 2162 ok\n", + "Puzzle 6.1: .001 seconds, answer 5329 ok\n", + "Puzzle 6.2: 1.936 seconds, answer 2162 ok\n", "Puzzle 7.1: .014 seconds, answer 1985268524462 ok\n", - "Puzzle 7.2: .646 seconds, answer 150077710195188 ok\n", + "Puzzle 7.2: .635 seconds, answer 150077710195188 ok\n", "Puzzle 8.1: .003 seconds, answer 220 ok\n", "Puzzle 8.2: .003 seconds, answer 813 ok\n", "Puzzle 9.1: .020 seconds, answer 6332189866718 ok\n", - "Puzzle 9.2: 2.680 seconds, answer 6353648390778 ok\n", + "Puzzle 9.2: 2.722 seconds, answer 6353648390778 ok\n", "Puzzle 10.1: .005 seconds, answer 744 ok\n", "Puzzle 10.2: .006 seconds, answer 1651 ok\n", "Puzzle 11.1: .002 seconds, answer 194482 ok\n", - "Puzzle 11.2: .060 seconds, answer 232454623677743 ok\n", - "Puzzle 12.1: .051 seconds, answer 1402544 ok\n", - "Puzzle 12.2: .042 seconds, answer 862486 ok\n", + "Puzzle 11.2: .057 seconds, answer 232454623677743 ok\n", + "Puzzle 12.1: .030 seconds, answer 1402544 ok\n", + "Puzzle 12.2: .043 seconds, answer 862486 ok\n", "Puzzle 13.1: .000 seconds, answer 29598 ok\n", "Puzzle 13.2: .000 seconds, answer 93217456941970 ok\n", "Puzzle 14.1: .000 seconds, answer 216027840 ok\n", - "Puzzle 14.2: 1.825 seconds, answer 6876 ok\n", - "Puzzle 15.1: .028 seconds, answer 1563092 ok\n", - "Puzzle 15.2: .041 seconds, answer 1582688 ok\n", - "Puzzle 16.1: .144 seconds, answer 103512 ok\n", - "Puzzle 16.2: .846 seconds, answer 554 ok\n", + "Puzzle 14.2: 1.819 seconds, answer 6876 ok\n", + "Puzzle 15.1: .029 seconds, answer 1563092 ok\n", + "Puzzle 15.2: .042 seconds, answer 1582688 ok\n", + "Puzzle 16.1: .139 seconds, answer 103512 ok\n", + "Puzzle 16.2: .982 seconds, answer 554 ok\n", "Puzzle 17.1: .000 seconds, answer 2,1,0,1,7,2,5,0,3 ok\n", - "Puzzle 17.2: .024 seconds, answer 267265166222235 ok\n", + "Puzzle 17.2: .004 seconds, answer 267265166222235 ok\n", "Puzzle 18.1: .014 seconds, answer 344 ok\n", - "Puzzle 18.2: .032 seconds, answer 46,18 ok\n", - "Puzzle 19.1: .004 seconds, answer 242 ok\n", - "Puzzle 19.2: .184 seconds, answer 595975512785325 ok\n", + "Puzzle 18.2: .042 seconds, answer 46,18 ok\n", + "Puzzle 19.1: .003 seconds, answer 242 ok\n", + "Puzzle 19.2: .215 seconds, answer 595975512785325 ok\n", "Puzzle 20.1: .022 seconds, answer 1343 ok\n", - "Puzzle 20.2: .756 seconds, answer 982891 ok\n", + "Puzzle 20.2: .822 seconds, answer 982891 ok\n", "Puzzle 21.1: .002 seconds, answer 205160 ok\n", "Puzzle 21.2: .008 seconds, answer 252473394928452 ok\n", - "Puzzle 22.1: .314 seconds, answer 14273043166 ok\n", - "Puzzle 22.2: 1.259 seconds, answer 1667 ok\n", + "Puzzle 22.1: .319 seconds, answer 14273043166 ok\n", + "Puzzle 22.2: 1.280 seconds, answer 1667 ok\n", "Puzzle 23.1: .001 seconds, answer 1170 ok\n", "Puzzle 23.2: .003 seconds, answer bo,dd,eq,ik,lo,lu,ph,ro,rr,rw,uo,wx,yg ok\n", "Puzzle 24.1: .001 seconds, answer 36035961805936 ok\n", "Puzzle 24.2: .000 seconds, answer jqf,mdd,skh,wpd,wts,z11,z19,z37 ok\n", - "Puzzle 25.1: .021 seconds, answer 3196 ok\n", + "Puzzle 25.1: .022 seconds, answer 3196 ok\n", "\n", "Correct: 49/49\n", "\n", - "Time in seconds: 0.008 median, 0.226 mean, 11.069 total.\n" + "Time in seconds: 0.006 median, 0.231 mean, 11.318 total.\n" ] } ],