{ "cells": [ { "cell_type": "markdown", "id": "4769054f-d675-4678-852f-945df5f1fc7d", "metadata": {}, "source": [ "
Peter Norvig, December 2025
\n", "\n", "# Advent of Code 2025\n", "\n", "I enjoy doing the [**Advent of Code**](https://adventofcode.com/) (AoC) programming puzzles, so here we go for 2025! \n", "\n", "This year I will be doing something different: I will solve each problem myself here in this notebook, and then [**as you can see in another notebook**](Advent-2025-AI.ipynb) I will ask an AI Large Language Model to solve the same problem. \n", "\n", "# Day 0: Utilities\n", "\n", "I start by loading up my [**AdventUtils.ipynb**](AdventUtils.ipynb) notebook (same as last time except for the `current_year`). On each day I will do three things:\n", "- Parse the input file (with the help of my `parse` utility function).\n", "- Solve Part 1 (recording the correct answer with my `answer` function).\n", "- Solve Part 2 (recording the correct answer with my `answer` function)." ] }, { "cell_type": "code", "execution_count": 1, "id": "a6fc45f3-ccc3-4905-881c-3cf7f6e897d7", "metadata": {}, "outputs": [], "source": [ "%run AdventUtils.ipynb\n", "current_year = 2025" ] }, { "cell_type": "markdown", "id": "d0d7cba9-e8be-4eeb-9918-2a2aecb21738", "metadata": {}, "source": [ "I'm thankful that [**@GaryGrady**](https://mastodon.social/@garygrady) is providing cartoons:\n", "\n", "\"Gary" ] }, { "cell_type": "markdown", "id": "37bc12b8-d0dc-4873-984c-6f09ae647229", "metadata": {}, "source": [ "# Day 1: Secret Entrance (Summing numbers mod 100)\n", "\n", "On [**Day 1**](https://adventofcode.com/2025/day/1) we meet an elf and learn that our task is to finish decorating the North Pole by December 12th. There will be 23 challenges along the way; the first one involves unlocking a safe. The safe has a dial with 100 numbers, and an arrow that currently points at 50. Our input for today is a sequence of left and right rotations; for example \"R20\" means move the dial right by 20 numbers and \"L13\" means move it left by 13 numbers. \n", "\n", "I'll use my `parse` utility function to parse each line of the input as an integer. My `parse` takes the day number as the first argument, and then the `parser` argument is a function that parses each line of the file; here it replaces each 'L' with a minus sign and each 'R' with a plus sign (using my `translate` [utility](AdventUtils.ipynb)) and then converts to an `int`." ] }, { "cell_type": "code", "execution_count": 2, "id": "ed911a15-addc-4c04-8546-2c9f37aee341", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "Puzzle input ➜ 4780 strs of size 2 to 4:\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "L20\n", "L13\n", "L16\n", "L16\n", "L29\n", "L7\n", "L48\n", "L48\n", "...\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "Parsed representation ➜ 4780 ints in range -999 to 997:\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "-20\n", "-13\n", "-16\n", "-16\n", "-29\n", "-7\n", "-48\n", "-48\n", "...\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n" ] } ], "source": [ "rotations = parse(day=1, parser=lambda line: int(translate(line, 'LR', '-+')))" ] }, { "cell_type": "markdown", "id": "7c98c883-d1dc-4d4e-9590-d47b1de000a0", "metadata": {}, "source": [ "Note that my `parse` function prints the first few input lines, then prints the parsed representation of these lines. That helps **me** debug and helps **you** the reader understand what is going on.\n", "\n", "\"Gary\n", "\n", "### Part 1.1: How many times is the dial left pointing at 0 after any rotation in the sequence?\n", "\n", "When applying the rotations in order, we are asked how many of the rotations leave the dial pointing at 0. The `itertools.accumulate` function yields running totals of its input sequence, so we just have to count (quantify) how many times the running total of the rotations is 0 mod 100. I'll write a function to do that and run it on the input:" ] }, { "cell_type": "code", "execution_count": 3, "id": "86079e27-2912-4431-8608-7a110a115789", "metadata": {}, "outputs": [], "source": [ "def count_zeros(numbers, dial=100) -> int:\n", " \"\"\"How many zeros (modulo `dial`) in the running partial sums of the numbers?\"\"\"\n", " return quantify(total % dial == 0 for total in accumulate(numbers, initial=50))" ] }, { "cell_type": "code", "execution_count": 4, "id": "eb90f15c-8f87-4d94-b49c-fcaa53aab8ae", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1182" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "count_zeros(rotations)" ] }, { "cell_type": "markdown", "id": "b5f68a70-8465-4249-954c-cba2b78751d8", "metadata": {}, "source": [ "I submitted \"1182\" to AoC and got back ***That's the right answer!***, so I record the answer (and its run time) like this:" ] }, { "cell_type": "code", "execution_count": 5, "id": "8387c4bd-a0b7-46d7-b726-d2d4b383b3cf", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 1.1: 0.2 msec, correct answer: 1182 " ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(puzzle=1.1, solution=1182, code=lambda: \n", " count_zeros(rotations))" ] }, { "cell_type": "markdown", "id": "12d5d111-8f69-4944-855b-54cca8215d7b", "metadata": {}, "source": [ "### Part 1.2: How many times does the dial point to 0 at any time?\n", "\n", "For Part 2 we are asked to count both when a rotation ends up at 0 and when the arrow passes 0 at any time during a rotation. For example, if the arrow points to 95, then only a \"R5\" or a \"L95\" would register a 0 in Part 1, but now for Part 2 a rotation of \"R10\" would also count because it passes 0 (as would any rotation of \"R5\" or larger, or \"L95\" or larger). \n", "\n", "I'll start with a brute force approach: treat a rotation of, say, -20 as 20 rotations of -1, and then use the same `count_zeros` function from Part 1. (Note that `sign(r)` returns +1 for any positive input, and -1 for any negative input.)" ] }, { "cell_type": "code", "execution_count": 6, "id": "053717d0-fe49-4b95-95a4-06202357883d", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 1.2: 27.0 msec, correct answer: 6907 " ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(1.2, 6907, lambda:\n", " count_zeros(flatten(abs(r) * [sign(r)] for r in rotations)))" ] }, { "cell_type": "markdown", "id": "bb0f6906-369e-4b3c-8840-d5648d713942", "metadata": {}, "source": [ "That's a long run time for a Day 1 problem, so here's a faster method: break each rotation down into a number of full circles and some remainder, then add the full circles to the count of zeros, and add one more if the remainder is at least as much as the distance to zero (in the appropriate direction): " ] }, { "cell_type": "code", "execution_count": 7, "id": "e0b676d8-3d4f-4b36-835d-b045ece53bd6", "metadata": {}, "outputs": [], "source": [ "def count_all_zeros(rotations, position=50, dial=100) -> int:\n", " \"\"\"How many times does any click cause the dial to point at 0?\n", " Count 1 if the rotation crosses the distance to 0,\n", " and for large rotations, count abs(r) // 100 more.\"\"\"\n", " zeros = 0\n", " for r in rotations:\n", " full_circles, remainder = divmod(abs(r), dial)\n", " distance_to_0 = (dial - position if (r > 0 or position == 0) else position)\n", " zeros += full_circles + (remainder >= distance_to_0)\n", " position = (position + r) % dial\n", " return zeros" ] }, { "cell_type": "code", "execution_count": 8, "id": "8969191e-bd50-4187-8e4b-64524bc8427a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 1.2: 0.4 msec, correct answer: 6907 " ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(1.2, 6907, lambda:\n", " count_all_zeros(rotations))" ] }, { "cell_type": "markdown", "id": "f47b1f7a-c9d9-4b21-a28a-f1e4e73d4c0d", "metadata": {}, "source": [ "That's much faster, but the code is trickier, and indeed I initially had a **bug** in the `distance_to_0` computation: when the current position is 0 the distance should be 100: it takes a full rotation to get back to 0. I fixed the bug by adding `or position == 0`." ] }, { "cell_type": "markdown", "id": "dd6908ae-1906-4687-a50d-a50293a1dad5", "metadata": {}, "source": [ "# Day 2: Gift Shop (Repeated digits as invalid IDs)\n", "\n", "On [**Day 2**](https://adventofcode.com/2025/day/2) we're in the North Pole gift shop, where the elves are doing inventory control. Today's input is a list of ranges of product IDs of items in stock. Each range is a pair of integers separated by a dash, and the ranges are separated by commas:" ] }, { "cell_type": "code", "execution_count": 9, "id": "63bb5099-68ab-41b3-8d0c-2f409433b3f2", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "Puzzle input ➜ 1 str of size 511:\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "990244-1009337,5518069-5608946,34273134-34397466,3636295061-3636388848,8613701-8663602,573252-68 ...\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "Parsed representation ➜ 35 tuples of size 2:\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "(990244, 1009337)\n", "(5518069, 5608946)\n", "(34273134, 34397466)\n", "(3636295061, 3636388848)\n", "(8613701, 8663602)\n", "(573252, 688417)\n", "(472288, 533253)\n", "(960590, 988421)\n", "...\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n" ] } ], "source": [ "id_ranges = parse(day=2, parser=positive_ints, sections=lambda text: text.split(','))" ] }, { "cell_type": "markdown", "id": "a5463e74-a3a1-4c79-9497-a1e307ef81e2", "metadata": {}, "source": [ "\"GaryJGrady\n", "\n", "### Part 2.1: What is the sum of the invalid IDs?\n", "\n", "An invalid ID is defined as one that consists of a digit sequence repeated twice. So 55, 6464 and 123123 are invalid. We're asked for the sum of the invalid IDs across all the ID ranges.\n", "\n", "We could look at every number in every range and check if the first half of the number (as a string) is the same as the second half. How many checks would that be?" ] }, { "cell_type": "code", "execution_count": 10, "id": "d682f3f2-415e-4556-b6c8-43e331a38703", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1990936" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sum((hi - lo + 1) for lo, hi in id_ranges)" ] }, { "cell_type": "markdown", "id": "a9bf1aab-bd09-49a9-ab57-8b26b1f4a98d", "metadata": {}, "source": [ "Only 2 million! So it would indeed be feasible to check every one. But I have a suspicion that Part 2 would make it infeasible, so I'll invest in a more efficient approach. For each ID range, instead of enumerating every number in the range and checking each one for validity, I will instead enumerate over the **first half** of the possible digit strings in the range, and automatically generate invalid IDs by appending a copy of the first half to itself. By **first half** I don't mean divide by 2; I mean the first half of the digit string: The first half of \"1234\" is \"12\". What's the first half of \"12345\"? It can't have 2.5 digits. I'm going to call it \"100\", because what we're looking for is the lowest number that, when appended to a copy of itself, could possibly be in range. The result can't be a 5-digit number, and 100 is the smallest first half that gives us a 6-digit number.\n", "\n", "We can see the first-half strategy has to consider far fewer numbers than the full range strategy:\n", "\n", "|strategy|example range|start|end|numbers in range|\n", "|---|---|---|---|---|\n", "|full range|123456-223456|123456|223000|100,001|\n", "|first half|123456-223456|123|223|101|" ] }, { "cell_type": "code", "execution_count": 11, "id": "c65d1ca2-571a-497a-afe7-6f3ab01c23ab", "metadata": {}, "outputs": [], "source": [ "def invalids_in_range(lo: int, hi: int) -> list[int]:\n", " \"\"\"All the invalid IDs between lo and hi inclusive.\n", " An ID is invalid if it consists of a digit sequence repeated twice.\"\"\"\n", " halves = range(first_half(lo), first_half(hi) + 1)\n", " return [id for half in halves\n", " if lo <= (id := int(str(half) * 2)) <= hi]\n", "\n", "def first_half(lo: int) -> int:\n", " \"\"\"The first half of a digit string, or the next power of 10.\"\"\"\n", " digit_string = str(lo)\n", " N = len(digit_string)\n", " return int(digit_string[:N//2]) if (N % 2 == 0) else 10 ** (N // 2)\n", "\n", "def invalids(id_ranges) -> set[int]:\n", " \"\"\"Invalid IDs, according to any one of the list of invalid ID ranges.\"\"\"\n", " return union(invalids_in_range(lo, hi)\n", " for (lo, hi) in id_ranges)" ] }, { "cell_type": "code", "execution_count": 12, "id": "607a72ac-2630-49b0-9060-103b34d3746b", "metadata": {}, "outputs": [], "source": [ "assert invalids([(11, 22)]) == {11, 22}\n", "assert first_half(1234) == 12\n", "assert first_half(12345) == 100\n", "assert first_half(1) == 1" ] }, { "cell_type": "code", "execution_count": 13, "id": "504d1291-98d6-4837-8aff-eb8179aa32fe", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 2.1: 0.1 msec, correct answer: 23560874270 " ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(2.1, 23560874270, lambda:\n", " sum(invalids(id_ranges)))" ] }, { "cell_type": "markdown", "id": "188dd774-0c2d-4304-8351-dfe208913a99", "metadata": {}, "source": [ "### Part 2.2: What is the sum of the invalid IDs, under the new rules?\n", "\n", "In Part 2 we discover that an ID should be considered invalid if it consists of two ***or more*** repeats of a sequence of digits. So 100100 is still invalid, but so are 100100100 and 100100100100 I'll rewrite `invalids_in_range` to take an optional argument saying how many repeats we're looking for, change `first_half` to accept the repeat count, and introduce `all_invalids` to try all possible repeat lengths across all ID ranges:" ] }, { "cell_type": "code", "execution_count": 14, "id": "4fbf52e7-a06a-4000-8627-80d159788da1", "metadata": {}, "outputs": [], "source": [ "def invalids_in_range(lo: int, hi: int, repeat=2) -> list[int]:\n", " \"\"\"The invalid IDs between lo and hi inclusive, which consist\n", " of a digit sequence repeated exactly `repeat` times.\"\"\"\n", " halves = range(first_half(lo, repeat), first_half(hi, repeat) + 1)\n", " return [id for half in halves\n", " if lo <= (id := int(str(half) * repeat)) <= hi]\n", "\n", "def first_half(lo: int, repeat=2) -> int:\n", " \"\"\"The first half of a digit string, or the next power of 10.\"\"\"\n", " digit_string = str(lo)\n", " N = len(digit_string)\n", " return int(digit_string[:N//repeat]) if (N % repeat == 0) else 10 ** (N // repeat)\n", "\n", "def all_invalids(id_ranges) -> set[int]:\n", " \"\"\"All Invalid IDs, for all ID ranges, with any number of repeats.\"\"\"\n", " return union(invalids_in_range(lo, hi, repeat)\n", " for (lo, hi) in id_ranges\n", " for repeat in range(2, len(str(hi)) + 1))" ] }, { "cell_type": "markdown", "id": "79a3a37d-14a5-493d-8c01-c3550479afe9", "metadata": {}, "source": [ "Some assertions because this is a bit tricky." ] }, { "cell_type": "code", "execution_count": 15, "id": "5a29e5bc-3b07-4800-9a0f-4bd433e01c55", "metadata": {}, "outputs": [], "source": [ "assert invalids_in_range(2121212118, 2121212124, 5) == [2121212121]\n", "assert all_invalids([(11, 22), (95, 115)]) == {11, 22, 99, 111}\n", "assert first_half(123456, 3) == 12\n", "assert first_half(1234567, 3) == 100" ] }, { "cell_type": "markdown", "id": "cb254f91-8c6d-445d-86be-97df9a93018c", "metadata": {}, "source": [ "Now I'll verify that the answer for Part 1 still works, and go ahead and compute the answer for Part 2:" ] }, { "cell_type": "code", "execution_count": 16, "id": "8a7c6c25-4b5f-4178-8559-166ba1a9f924", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 2.1: 0.1 msec, correct answer: 23560874270 " ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(2.1, 23560874270, lambda:\n", " sum(invalids(id_ranges)))" ] }, { "cell_type": "code", "execution_count": 17, "id": "32fefd65-df2a-4ea3-9acd-7525ebd32380", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 2.2: 0.2 msec, correct answer: 44143124633 " ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(2.2, 44143124633, lambda:\n", " sum(all_invalids(id_ranges)))" ] }, { "cell_type": "markdown", "id": "872cf212-bfbf-4edd-b898-5f76ad122a85", "metadata": {}, "source": [ "I initially had another **bug** here: I initially counted \"222222\" three times: as 2 repeats of \"222\", or 3 repeats of \"22\", or 6 repeats of \"2\". I changed the output of `all_invalids` to be a `set` rather than a `list` to fix that.\n", "\n", "I can certainly make this faster by eliminating the conversion back and forth to string. Instead of doing `(id := int(str(123) * 4))` to get 123123123123, I could do `123 * 1001001001`. This would be faster, but would require more code to figure out the multiplicand, so I'll say it is already fast enough." ] }, { "cell_type": "markdown", "id": "16e222aa-d424-44d8-bcb3-7aa11c31b540", "metadata": {}, "source": [ "# Day 3: Lobby (Maximum number from digit string)\n", "\n", "Entering the lobby on [**Day 3**](https://adventofcode.com/2025/day/3), we find that the elevators are offline. We might be able to fix the problem by turning on some batteries. There are multiple battery banks, each bank consisting of a sequence of digits representing the *joltage* level of a battery. " ] }, { "cell_type": "code", "execution_count": 18, "id": "04ef4f2f-2b07-43cd-87d4-a8f63f7fe840", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "Puzzle input ➜ 200 strs of size 100:\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "5353323523322232362334333433323333353233331313222372133133353643423323233323333534414523333432223242\n", "6344544745655555456556556566665564538465555575558846455665837545764555554465564547547565544657585435\n", "2246273372253242254243532252231242225522622633532222322234255122531222423531343223123232234213323424\n", "6545643634344444495734739454433454439454355654483544243344534445434437426443854344454534654439534424\n", "2356636643143433535443636338231745346538433576334436353176353333433532345344334224435234343644332536\n", "3221311221443323323322222214632342232233222322333436263122265162212321261323142262212332322125216222\n", "3336332333336335335324359336493238433441666379243536334165623214253384333323893933867663434332383763\n", "3235321252332431332223232436222532432226223222213233432853535322314122221322352235213323124321222233\n", "...\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n" ] } ], "source": [ "banks = parse(day=3)" ] }, { "cell_type": "markdown", "id": "529e9177-7e47-46fa-bdc0-b979205d2e72", "metadata": {}, "source": [ "### Part 3.1: What is the maximum possible total output joltage?\n", "\n", "We are allowed to turn on exactly two batteries in each bank, resulting in a two digit number which is the *joltage* of the bank. For example, given the bank \"8647\" we could choose to turn on the \"8\" and \"7\" to produce a joltage of 87; that's the maximum. We are asked what is the sum of the maximal possible joltage from each bank. The function `total_joltage` computes that; it calls `joltage` on each bank, and `joltage` chooses the biggest first digit, and then the biggest second digit that follows the first digit. Note that the possible choices for the first digit exclude the last digit, because if we chose that, then there would be no choices left for the second digit. (I chose to do the string-to-int conversion in `total_joltage`; it would also be okay to have `joltage` return an int.)" ] }, { "cell_type": "code", "execution_count": 19, "id": "0168ada2-b53e-4215-9e6a-2468759f095c", "metadata": {}, "outputs": [], "source": [ "def max_joltage(bank: str) -> str:\n", " \"\"\"The maximum possible joltage by turning on 2 batteries in the bank.\n", " Pick the biggest first digit, then the biggest digit that follows.\"\"\"\n", " first = max(bank[:-1]) # The first digit can't be the last character\n", " second = max(bank[bank.index(first) + 1:]) # The second digit must come after the first\n", " return first + second\n", "\n", "def total_joltage(banks: list[str]) -> int:\n", " \"\"\"The maximum possible total joltage from all the banks.\"\"\"\n", " return sum(int(max_joltage(bank)) for bank in banks)" ] }, { "cell_type": "code", "execution_count": 20, "id": "3f6390f5-78b7-4472-acf9-8855d2c2453e", "metadata": {}, "outputs": [], "source": [ "assert max_joltage(\"8647\") == \"87\"\n", "assert max_joltage(\"1239\") == \"39\"" ] }, { "cell_type": "code", "execution_count": 21, "id": "9cc62ae9-b313-4b82-b8fb-bab9c0ef5cb6", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 3.1: 0.3 msec, correct answer: 17085 " ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(3.1, 17085, lambda:\n", " total_joltage(banks))" ] }, { "cell_type": "markdown", "id": "3f8a4645-5e36-4b3d-8ace-125024403b3b", "metadata": {}, "source": [ "### Part 3.2: What is the new maximum possible total output joltage?\n", "\n", "The elf hits the ***safety override*** button, and we can now turn on **12** batteries per bank, resulting in a 12-digit joltage. What is the new maximum possible total joltage?\n", "\n", "I will make a change to the two functions, passing in the number of digits to be chosen, *n* (with default 2 for backwards compatibility). The function `max_joltage` recurses when there is more than one digit remaining, choosing the first digit from the bank up to the last *n* - 1 characters, then recursively finding the biggest joltage from the rest. " ] }, { "cell_type": "code", "execution_count": 22, "id": "b9507c12-421b-41af-b926-a4d3d83f622d", "metadata": {}, "outputs": [], "source": [ "def max_joltage(bank: str, n=2) -> str:\n", " \"\"\"The maximum possible joltage by turning on `n` batteries in the bank.\n", " Pick the first digit, then the maximum joltage from the rest of the bank.\"\"\"\n", " if n == 1:\n", " return max(bank)\n", " else:\n", " first = max(bank[:-(n - 1)]) # The first digit can't be the last n-1 characters\n", " rest = bank[bank.index(first) + 1:]\n", " return first + max_joltage(rest, n - 1)\n", "\n", "def total_joltage(banks: list[str], n=2) -> int:\n", " \"\"\"The maximum possible joltage from all the banks,\n", " when `n` batteries are turned on per bank.\"\"\"\n", " return sum(int(max_joltage(bank, n)) for bank in banks)" ] }, { "cell_type": "code", "execution_count": 23, "id": "4a58a657-8f32-4001-a4ff-f30dfbe7e5e7", "metadata": {}, "outputs": [], "source": [ "assert max_joltage(\"811111111111119\", 2) == '89'\n", "assert max_joltage(\"818181911112111\", 5) == '92111'\n", "assert max_joltage(\"818181911112111\", 12) == '888911112111'" ] }, { "cell_type": "markdown", "id": "28d2e2ce-98b5-4b3b-9f4d-26efcb7e1258", "metadata": {}, "source": [ "I'll make sure Part 1 still works, and then solve Part 2:" ] }, { "cell_type": "code", "execution_count": 24, "id": "fe3cff78-81c0-4d4a-bb4d-f0f841067e0d", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 3.1: 0.3 msec, correct answer: 17085 " ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(3.1, 17085, lambda:\n", " total_joltage(banks))" ] }, { "cell_type": "code", "execution_count": 25, "id": "f971839e-81ea-49b4-a92f-a44884be645d", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 3.2: 0.8 msec, correct answer: 169408143086082" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(3.2, 169408143086082, lambda:\n", " total_joltage(banks, 12))" ] }, { "cell_type": "markdown", "id": "db13a440-9ad0-4344-b555-aec969869688", "metadata": {}, "source": [ "# Day 4: Printing Department (Accessible squares in a grid)\n", "\n", "On [**Day 4**](https://adventofcode.com/2025/day/4) the floor of the printing department is divided into squares, some of which contain a roll of paper. The day's input is a map of the floor, with `@` representing a roll of paper. I can handle that with the `Grid` class from my [AdventUtils](AdventUtils.ipynb):" ] }, { "cell_type": "code", "execution_count": 26, "id": "c9f227d5-2748-48e1-80c1-7385dad46323", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "Puzzle input ➜ 140 strs of size 140:\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", ".@@@@@...@.@@@@@@@@@@.@@@@@@@.@.@.@@@@@@@@@@@@@..@.@@@.@@@@@@..@.@..@.@@...@.@@@@..@@@@....@@@.@ ...\n", ".@@@@@.@....@.....@@@.@@.@@.@@@.@@@.@.@.@.@@@@@.@@.@@@@@.@@@@@@@@@@@..@@.@.@@.@@@.@@@@@@@@@@@..@ ...\n", "@.@@@@.@@@@.@@@@..@@.@@@@@@@@.@@@@.@@@@.@@..@.@...@.@.@.@.@@..@@@@@.@.@.@@@@.@@@@@@@@@.@@@@..@@. ...\n", ".@.....@.@@@..@.@@@.@..@@@@@..@@@.@@..@...@.@@@@.@@@.@.@@@@@@.@.@@@@@@@.@.@@@.@@@@@@...@@.@@..@. ...\n", "@@@@@.@@@.@@@@@@@..@@.@.@@@..@@..@@@.@@....@.@..@@@@@@@@.@.@@..@@...@@.@@@...@.@.@@@..@.@.@@@@@@ ...\n", "@.@@@@@@..@@@@...@..@@@@@@.@@@..@.....@@.@.@@...@@@.@@.@.@@@....@@.@.@.@@@@.@@@@@.@@@.@@...@@.@@ ...\n", ".@@@.@.@@@..@@.@.@@@@@.@.@..@@....@..@.@.@@@@.@..@@.@..@@@@@.@@@@@@@.@.@@@.@.@@@.@@@@.@@@@@@@@.@ ...\n", "@@@@@@@.@@...@@@....@.@@@@.@@@@@@@@@.@@@.@@.@@..@...@@@@@.@@@..@.@@@@@@@@@@.@@@.@..@@@.@@@@.@.@@ ...\n", "...\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n" ] } ], "source": [ "paper_grid = Grid(parse(day=4), directions=directions8)" ] }, { "cell_type": "markdown", "id": "4dd00e21-228c-41f6-a28c-e2213e60d4ce", "metadata": {}, "source": [ "\"Gary\n", "\n", "\n", "### Part 4.1: How many rolls of paper can be accessed by a forklift?\n", "\n", "A roll is **accessible** by forklift if there are fewer than four rolls of paper in the eight adjacent positions (that's why I specified `directions8` in defining `paper_grid`). Counting the number of accessible rolls is easy, but I decided to make `accessible rolls` return a list of positions rather than a count, in anticipation of Part 2." ] }, { "cell_type": "code", "execution_count": 27, "id": "6fe5bd44-8a28-4d7a-bc8b-edc4af8f23c3", "metadata": {}, "outputs": [], "source": [ "def accessible_rolls(grid: Grid) -> list[Point]:\n", " \"\"\"The positions of all the accessible rolls of paper on the grid.\"\"\"\n", " return [p for p in grid if is_accessible(p, grid)]\n", "\n", "def is_accessible(p: Point, grid: Grid) -> bool:\n", " \"\"\"A roll of paper is accessible if there are fewer than \n", " four rolls of paper in the eight adjacent positions.\"\"\"\n", " return grid[p] == '@' and grid.neighbor_contents(p).count('@') < 4" ] }, { "cell_type": "markdown", "id": "714b9eed-bdee-4e3f-b0be-1a3f727dddfb", "metadata": {}, "source": [ "Here's the answer:" ] }, { "cell_type": "code", "execution_count": 28, "id": "a5ef09cf-b204-41eb-80d8-de107d385dbb", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 4.1: 18.8 msec, correct answer: 1569 " ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(4.1, 1569, lambda:\n", " len(accessible_rolls(paper_grid)))" ] }, { "cell_type": "markdown", "id": "550312ae-a70b-405c-90e6-5df9c9afc0e8", "metadata": {}, "source": [ "### Part 4.2: How many rolls of paper can be removed?\n", "\n", "If a paper roll is accessible, it can be removed by forklift. That may in turn make other rolls accessible, and hence removable. How many rolls in total can be removed?\n", "\n", "It looks like I was right to make `accessible_rolls` return a list of points rather than a count! I can answer the question by repeatedly finding the accessible rolls, removing them (on a copy of the grid so I don't mess up the original grid), and repeating until there are no more accessible rolls." ] }, { "cell_type": "code", "execution_count": 29, "id": "0ed53853-268c-4c2f-a929-cb3e6005a348", "metadata": {}, "outputs": [], "source": [ "def removable_rolls(grid: Grid) -> Iterable[Point]:\n", " \"\"\"The positions of paper rolls that can be removed, in any nuber of iterations.\"\"\"\n", " grid2 = grid.copy() # To avoid mutating the original input grid\n", " while (points := accessible_rolls(grid2)):\n", " yield from points\n", " grid2.update({p: '.' for p in points})" ] }, { "cell_type": "code", "execution_count": 30, "id": "2fb17a51-05f7-42ec-8d6c-222121a026cf", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 4.2: 466.6 msec, correct answer: 9280 " ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(4.2, 9280, lambda:\n", " quantify(removable_rolls(paper_grid))) " ] }, { "cell_type": "markdown", "id": "7143f73e-3b9b-49f3-bfa9-625899a56e37", "metadata": {}, "source": [ "That's the right answer, but the run time is a bit slow. The main issue is that `accessible_rolls` has to look at the whole grid on every iteration. But if the previous iteration only removed one roll, all we really need to look at on the next iteration is the neighbors of the removed roll. So I'll keep a queue of possibly removable points and repeatedly pop a point off the queue, and if it is an accessible roll, remove it and put all its neighbors on the queue. When the queue is empty, no more rolls can be removed." ] }, { "cell_type": "code", "execution_count": 31, "id": "54f20b5e-6713-459c-8d40-e545ce6b8e42", "metadata": {}, "outputs": [], "source": [ "def removable_rolls(grid: Grid) -> Iterable[Point]:\n", " \"\"\"The positions of paper rolls that can be removed, in any number of iterations.\"\"\"\n", " grid2 = grid.copy() # To avoid mutating the original input grid\n", " Q = grid2.findall('@') # A queue of possibly removable positions in the grid\n", " while Q:\n", " p = Q.pop()\n", " if is_accessible(p, grid2):\n", " yield p\n", " grid2[p] = '.'\n", " Q.extend(grid2.neighbors(p))" ] }, { "cell_type": "code", "execution_count": 32, "id": "bcba970b-09aa-479b-9c6d-4f6a7ac49fed", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 4.2: 50.1 msec, correct answer: 9280 " ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(4.2, 9280, lambda:\n", " quantify(removable_rolls(paper_grid)))" ] }, { "cell_type": "markdown", "id": "4aae3157-9c06-40d1-b0cd-c6f5515b0064", "metadata": {}, "source": [ "That's almost 10 times faster!\n", "\n", "Let's visualize the paper rolls before and after removal:" ] }, { "cell_type": "code", "execution_count": 33, "id": "402e78e0-cf05-4285-bd9c-07b6ebd9b602", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "before = set(paper_grid.findall('@'))\n", "after = before - set(removable_rolls(paper_grid))\n", "\n", "naked_plot(before, 'o', markersize=2)\n", "naked_plot(after, 'o', markersize=2)" ] }, { "cell_type": "markdown", "id": "1f9a1e40-192a-4386-8cfb-bc5f69c88a9b", "metadata": {}, "source": [ "# Day 5: Cafeteria (Counting IDs within ranges)\n", "\n", "On [**Day 5**](https://adventofcode.com/2025/day/5) we're in the cafeteria, and the elves need to figure out which of their ingredients are fresh or spoiled. The input file has two parts (paragraphs), the first consisting of ranges of fresh ingredient IDs, like \"6-7\" and the second consisting of the available ingredient IDs, like \"8\". I can parse the data like this:" ] }, { "cell_type": "code", "execution_count": 34, "id": "4b508db5-aeae-410e-a062-1b2d4ce41253", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "Puzzle input ➜ 1184 strs of size 0 to 31:\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "292632986393425-296797126337251\n", "428261559408337-431275643240865\n", "197704206528056-198822557342819\n", "36791726875734-37049023408764\n", "134880223152389-139959748438608\n", "31870818340663-32138457068292\n", "443613579514078-447616030778273\n", "284142407577672-288117756872436\n", "...\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "Parsed representation ➜ 2 tuples of size 183 to 1000:\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "((292632986393425, 296797126337251), (428261559408337, 431275643240865), (197704206528056, 19882 ...\n", "(92087202605588, 314304587960778, 19184152482180, 331502336245673, 104093299503920, 224082459481 ...\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n" ] } ], "source": [ "def parse_ingredients(text: str) -> tuple:\n", " \"\"\"Parse either ranges like \"3-5\", or integers like \"8\".\"\"\"\n", " if '-' in text:\n", " return mapt(positive_ints, lines(text))\n", " return mapt(positive_ints, lines(text)) if '-' in text else ints(text)\n", " \n", "fresh_ranges, available_ingredient_ids = parse(day=5, parser=parse_ingredients, sections=paragraphs)" ] }, { "cell_type": "markdown", "id": "ebb61d5f-4683-4ff6-986c-69154d512e1b", "metadata": {}, "source": [ "### Part 5.1: How many of the available ingredient IDs are fresh?\n", "\n", "Keep it simple: For each ingredient ID, check to see if it is contained in any of the ranges (then we'll see if this is fast enough):" ] }, { "cell_type": "code", "execution_count": 35, "id": "ae5b33e4-92f5-4fe2-bd5a-6b22095724fa", "metadata": {}, "outputs": [], "source": [ "def count_fresh_ingredients(fresh_ranges, available_ingredient_ids) -> int:\n", " \"\"\"How many of the available ingredient IDs are in one of the fresh ranges?\"\"\"\n", " return quantify(any(lo <= id <= hi for (lo, hi) in fresh_ranges)\n", " for id in available_ingredient_ids)" ] }, { "cell_type": "code", "execution_count": 36, "id": "112a84f7-9bb8-45f0-9d7e-f600f37f0fdf", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 5.1: 4.4 msec, correct answer: 635 " ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(5.1, 635, lambda:\n", " count_fresh_ingredients(fresh_ranges, available_ingredient_ids))" ] }, { "cell_type": "markdown", "id": "01c2c322-e873-412f-9c47-59ffdf9adf79", "metadata": {}, "source": [ "Fast enough! Let's move on.\n", "\n", "### Part 5.2: How many ingredient IDs are fresh?\n", "\n", "In Part 2 we are asked how many of the possible ingredient IDs are fresh, regardless of whether the ID is available or not. I could convert a range like \"3-5\" into the set {3, 4, 5} and then union the sets together. How many elements would be in that set? Here's an estimate: " ] }, { "cell_type": "code", "execution_count": 37, "id": "47a660d2-746c-433f-b4ae-9d01f70bc504", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "476036797138761" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sum(hi - lo for (lo, hi) in fresh_ranges)" ] }, { "cell_type": "markdown", "id": "1360869f-3ccb-4c71-8d00-35de1215389f", "metadata": {}, "source": [ "OK, switch to Plan B. Instead of explicitly building this set I can instead sort the fresh ID ranges (by their low number) and go through them, keeping track of the lowest ID that has not yet been explored for freshness, and a count of the fresh IDs found so far. For each range, the number of new fresh IDs is the length of the range that starts with either the start of the range or the first unexplored ID, and ends at the end of the range." ] }, { "cell_type": "code", "execution_count": 38, "id": "f52e8ecd-325e-4ed4-8928-de9365b5b7d4", "metadata": {}, "outputs": [], "source": [ "def count_fresh_ids(fresh_ranges) -> int:\n", " \"\"\"How many IDs are contained in the union of the ranges?\"\"\"\n", " fresh_count = 0 # The number of fresh IDs found so far\n", " unexplored = 0 # The highest ID number that we haven't considered yet\n", " for (lo, hi) in sorted(fresh_ranges):\n", " start = max(unexplored, lo)\n", " fresh_count += len(range(start, hi + 1))\n", " unexplored = max(unexplored, hi + 1)\n", " return fresh_count" ] }, { "cell_type": "code", "execution_count": 39, "id": "fab6f1ed-543f-4f42-b1d5-2551742e3a4f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 5.2: 0.0 msec, correct answer: 369761800782619" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(5.2, 369761800782619, lambda:\n", " count_fresh_ids(fresh_ranges))" ] }, { "cell_type": "markdown", "id": "6b83e353-3b77-4645-85b9-2f6ee6ff9e1d", "metadata": {}, "source": [ "# Day 6: Trash Compactor (Vertical arithmetic)\n", "\n", "Trash Compactor? [I've got a bad feeling about this!](https://youtu.be/CZgeYSqUeTA?si=5UPS_HiCOmTKrEWX&t=32) \n", "\n", "On [**Day 6**](https://adventofcode.com/2025/day/6) we've fallen into a garbage smasher and have been asked to help some of the resident cephalopod children with their math homework. We can parse the homework worksheet, but we were told that the exact alignment of columns matters, so I'll keep each line as a string rather than converting it to a list of ints.\n", "\n", "\"Gary" ] }, { "cell_type": "code", "execution_count": 40, "id": "bca852a9-e4c5-4706-abfc-afc6d4a4eeb5", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "Puzzle input ➜ 5 strs of size 3732:\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", " 4 82 68 85 74 6 56 14 2 8669 66 13 927 3 235 44 52 16 37 61 82 1774 96 15 775 789 91 ...\n", " 6 87 39 72 56 12 69 79 58 4378 86 49 146 5 412 85 7751 577 69 813 55 9942 753 49 734 587 15 ...\n", " 827 446 82 72 76 21 31 32 96 3257 21 21 171 2 31 17 9178 977 11 469 58 712 162 4 1 132 91 ...\n", "9472 154 36 76 5 89 37 5 28 6 95 49 82 66 7 44 8183 524 38 819 11 7 825 9 8 397 48 ...\n", "+ + + * * * + * * + * + * * + + + + * + * + * + * * * ...\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n" ] } ], "source": [ "worksheet = parse(6, str)" ] }, { "cell_type": "markdown", "id": "ae8a7f1d-07ec-46e4-880f-abbd82d46a67", "metadata": {}, "source": [ "### Part 6.1: What is the grand total of the answers to the individual problems?\n", "\n", "We humans are used to arithmetic problems written in left-to-right order, but cephalopods use top-to-bottom order, with a postfix operator in the last row. We need to compute the sum or product for each column and add all those results together. So the problem in the first column above would be \"`4 + 6 + 827 + 9472`\". Here's the code:" ] }, { "cell_type": "code", "execution_count": 41, "id": "92f320f4-c7a3-4dfd-ae61-6b1b180bdc93", "metadata": {}, "outputs": [], "source": [ "def grand_total(worksheet):\n", " \"\"\"The sum of the individual sum/product problems, where each column is a problem.\"\"\"\n", " columns = T(map(str.split, worksheet)) # Columns are the transpose of the rows; `T` is transpose\n", " operations = {'*': prod, '+': sum}\n", " return sum(operations[op](mapt(int, numbers)) \n", " for (*numbers, op) in columns)" ] }, { "cell_type": "code", "execution_count": 42, "id": "92a47f3a-127f-41e8-bee1-6276885bd36b", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 6.1: 0.9 msec, correct answer: 5877594983578 " ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(6.1, 5877594983578, lambda:\n", " grand_total(worksheet))" ] }, { "cell_type": "markdown", "id": "226772ae-0d6e-43b8-9159-171ec1b36a5d", "metadata": {}, "source": [ "### Part 6.2: What is the grand total of the answers to the individual problems with the new rules?\n", "\n", "In Part 2 we learn that we did all the problems wrong. Cephalopodish number notation is different; numbers are read vertically rather than horizontally and the exact column alignment of each digit matters. Given the worksheet:\n", "\n", " 4 82 68 85 74 6 56 14 2 8669 66 13 927 3 235 44 \n", " 6 87 39 72 56 12 69 79 58 4378 86 49 146 5 412 85 \n", " 827 446 82 72 76 21 31 32 96 3257 21 21 171 2 31 17 \n", " 9472 154 36 76 5 89 37 5 28 6 95 49 82 66 7 44 \n", " + + + * * * + * * + * + * * + + \n", "\n", "The problem in the leftmost column is not \"`4 + 6 + 827 + 9472`\"; rather it is \"`9 + 84 + 27 + 4672`\". But the numbers are not always right-justified; the problem in the sixth colun is \"`6128 * 219`\".\n", "\n", "That means I can't just split each line into numbers, I'll have to be careful to maintain the blank spaces to the right and left of the digits, and I have to know in what position each column starts and ends. That part was tricky, so here's an explanation:\n", "- I note from the worksheet above that each column starts at a position above a `+` or `*` sign.\n", "- Each column ends one character before the next `+` or `*` sign.\n", "- For the last column there is no terminator, so I'll add the string `' *'` to the operator line before computing the start positions.\n", "\n", "In `grand_total2` I first break each line into columns, take the transpose of that (to give a list of problems), do the math on each problem, and return the sum of the results. Within `cephalopodish_math` I call `vertically`, whioch again does a transpose and then puts the digits together into an integer." ] }, { "cell_type": "code", "execution_count": 43, "id": "5866583b-245d-4a43-a037-229bf35f1be2", "metadata": {}, "outputs": [], "source": [ "def grand_total2(worksheet: list[str]):\n", " \"\"\"Solve the problem in each column with cephalopodish math and return the sum.\"\"\"\n", " problems = T(break_into_columns(worksheet))\n", " return sum(map(cephalopodish_math, problems))\n", "\n", "def break_into_columns(worksheet: list[str]) -> list[list[str]]:\n", " \"\"\"Break a whole worksheet into columns where each operator position starts a column.\"\"\"\n", " *number_lines, operator_line = worksheet\n", " operator_line = operator_line.ljust(len(worksheet[0])) + ' *'\n", " column_starts = [i for i, ch in enumerate(operator_line) if ch != ' ']\n", " return [break_line_into_columns(line, column_starts) for line in worksheet]\n", "\n", "def break_line_into_columns(line: str, column_starts: list[int]) -> list[str]:\n", " \"\"\"Break one line into columns, as specified by the list of `blanks` positions.\"\"\"\n", " return [line[column_starts[i]:column_starts[i + 1]-1] \n", " for i in range(len(column_starts) - 1)]\n", "\n", "def cephalopodish_math(problem) -> int:\n", " \"\"\"Return the sum or product of the vertically-arranged numbers.\"\"\"\n", " *numbers, op = problem\n", " sum_or_prod = (sum if op.strip() == '+' else prod)\n", " return sum_or_prod(vertically(numbers))\n", "\n", "def vertically(numbers: list[str]) -> list[int]:\n", " \"\"\"Return a list of integers found by reading numbers vertically by column.\"\"\"\n", " return [int(cat(digits)) for digits in T(numbers)]" ] }, { "cell_type": "code", "execution_count": 44, "id": "39a8fa78-946f-45aa-8d36-76883f4aeaff", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 6.2: 1.3 msec, correct answer: 11159825706149 " ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(6.2, 11159825706149, lambda:\n", " grand_total2(worksheet))" ] }, { "cell_type": "markdown", "id": "ca461ef3-50c3-4189-b724-5f2b3898f27d", "metadata": {}, "source": [ "I initially had an `IndexError` **bug** because the operator line is shorter then the numbers lines; the `ljust` fixed that. Then I had an off-by-one **bug** that messed up the problem in the last column. To debug my errors I worked on a smaller example worksheet, doing things like this:" ] }, { "cell_type": "code", "execution_count": 45, "id": "a13dbe89-3178-433f-9a50-28ed9a2f8358", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[['123', '328', ' 51', '64 '],\n", " [' 45', '64 ', '387', '23 '],\n", " [' 6', '98 ', '215', '314'],\n", " ['* ', '+ ', '* ', '+']]" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example = lines(\"\"\"\\\n", "123 328 51 64 \n", " 45 64 387 23 \n", " 6 98 215 314\n", "* + * +\"\"\")\n", "\n", "break_into_columns(example)" ] }, { "cell_type": "code", "execution_count": 46, "id": "13392d9c-fef8-4946-b945-48ad6bc7eca9", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[('123', ' 45', ' 6', '* '),\n", " ('328', '64 ', '98 ', '+ '),\n", " (' 51', '387', '215', '* '),\n", " ('64 ', '23 ', '314', '+')]" ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "T(break_into_columns(example))" ] }, { "cell_type": "code", "execution_count": 47, "id": "e29df77c-7385-4ba9-a27b-4074a78a0d74", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 24, 356]" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vertically(['123', \n", " ' 45', \n", " ' 6'])" ] }, { "cell_type": "code", "execution_count": 48, "id": "9a25ff50-f465-4de3-95ca-71b7a3d9569b", "metadata": {}, "outputs": [], "source": [ "assert cephalopodish_math(('123', \n", " ' 45', \n", " ' 6', \n", " '* ')) == 1 * 24 * 356 == 8544" ] }, { "cell_type": "markdown", "id": "953679f2-8b55-4bcb-b46f-db0d7c435ea3", "metadata": {}, "source": [ "# Day 7: Laboratories (Counting paths through a grid)\n", "\n", "In the lab on [**Day 7**](https://adventofcode.com/2025/day/7) is a tachyon manifold in need of repair. We find a diagram of the manifold, with `S` marking the start of the tachyon beams and `^` marking a splitter. \n", "\n", "I could parse this as a `Grid`, but I think I will just keep it as a list of strings. The main advantage of a `Grid` is dealing with the 4 or 8 neighbors; a concept that this problem does not use." ] }, { "cell_type": "code", "execution_count": 49, "id": "e85af831-b6cf-4073-a131-ce68debaea75", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "Puzzle input ➜ 142 strs of size 141:\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "......................................................................S......................... ...\n", "................................................................................................ ...\n", "......................................................................^......................... ...\n", "................................................................................................ ...\n", ".....................................................................^.^........................ ...\n", "................................................................................................ ...\n", "....................................................................^.^.^....................... ...\n", "................................................................................................ ...\n", "...\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n" ] } ], "source": [ "manifold = parse(7)" ] }, { "cell_type": "markdown", "id": "59927e26-3252-4c26-8aef-014afdb6deaf", "metadata": {}, "source": [ "### Part 7.1: How many times will the beam be split?\n", "\n", "Tachyon beams move downwards unless they enounter a `^` splitter, in which case they split into two beams, one immediately to the left of the splitter and one to the right. We're asked how many splits occur. If two beams end up in the same place they count as one beam, so if that beam is split again, that's just one more split, not two more.\n", "\n", "That suggests I should keep a `set` of current horizontal beam positions, and update the set every time we go down one line. (It is a set rather than a list so that duplicate beam positions count as one, not as two. (Also, if I kept a list of positions then given the size of the input there would be trillions of beams by the end, so it would take a very long time to get the wrong answer.)) I use the idiom of iterating with `for b in list(beams)` rather than `for b in beams` so that I can mutate the set `beams` during the iteration. I also need to keep track of the split count, and return that at the end:" ] }, { "cell_type": "code", "execution_count": 50, "id": "d4d3bdbb-d8b2-4e22-adb4-c99a212a2ca7", "metadata": {}, "outputs": [], "source": [ "def count_splits(manifold: list[str]) -> int:\n", " \"\"\"How many beam split events occur as the beams make their way through the manifold?\"\"\"\n", " start = manifold[0].index('S')\n", " beams = {start}\n", " split_count = 0\n", " for line in manifold:\n", " for b in list(beams):\n", " if line[b] == '^': # Replace the beam position with one on each side and count a split\n", " split_count += 1\n", " beams.remove(b)\n", " beams.update({b - 1, b + 1})\n", " return split_count" ] }, { "cell_type": "code", "execution_count": 51, "id": "0e14ad5e-6871-4a9c-bd94-5a863c2341e0", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 7.1: 0.4 msec, correct answer: 1681 " ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(7.1, 1681, lambda:\n", " count_splits(manifold))" ] }, { "cell_type": "markdown", "id": "7e8174b9-2b66-41ce-9677-807a90b88ec5", "metadata": {}, "source": [ "### Part 7.2: In total, how many different timelines would a single tachyon particle end up on?\n", "\n", "Now we're told this is a *quantum* tachyon manifold and we need to know how many different *timelines* a single tachyon appears in, or in other words, how many different paths can the tachyon beams take to get to the last line.\n", "\n", "We can't just count the number of beams in the last line, because if a beam in position *b* takes two different paths to get there, that counts as two, not one. Instead, I'll replace the `set` from Part 1 with a `Counter` of `{beam_position: number_of_paths_to_get_here}`. If a beam at position *b* with *n* paths to get there encounters a splitter, then in the next step both positions *b* - 1 and *b* + 1 are incremented by *n*, and position *b* is decremented by *n*. In the end we return the sum of all the counts of paths." ] }, { "cell_type": "code", "execution_count": 52, "id": "df96165c-4e55-447a-bc5c-fba2f0462ebf", "metadata": {}, "outputs": [], "source": [ "def count_timelines(manifold: list[str]) -> int:\n", " \"\"\"How many possible paths are there to the final line of the manifold?\"\"\"\n", " start = manifold[0].index('S')\n", " beams = Counter({start: 1})\n", " for line in manifold:\n", " for (b, n) in list(beams.items()):\n", " if line[b] == '^':\n", " beams[b - 1] += n\n", " beams[b] -= n\n", " beams[b + 1] += n\n", " return sum(beams.values())" ] }, { "cell_type": "code", "execution_count": 53, "id": "ee179d56-ce86-473d-9801-39f1b90d03ab", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 7.2: 0.7 msec, correct answer: 422102272495018" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(7.2, 422102272495018, lambda:\n", " count_timelines(manifold))" ] }, { "cell_type": "markdown", "id": "135b532d-d9ac-4400-9c6d-3b316d4596e1", "metadata": {}, "source": [ "# Day 8: Playground (Unioning sets, in closest distance order)\n", "\n", "In a playground on [**Day 8**](https://adventofcode.com/2025/day/8), some elves are setting up an ambitious Christmas light decoration project using electrical junction boxes. They have a list of the junction box coordinates in 3D space:" ] }, { "cell_type": "code", "execution_count": 54, "id": "a5cc43b2-3c5d-4d28-8c94-112bbb5739e7", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "Puzzle input ➜ 1000 strs of size 13 to 17:\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "83023,97914,59845\n", "95221,6604,47587\n", "15200,13848,533\n", "91106,47235,95124\n", "91396,58746,56994\n", "72070,33359,10785\n", "13733,43410,23707\n", "84853,78378,68689\n", "...\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "Parsed representation ➜ 1000 tuples of size 3:\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "(83023, 97914, 59845)\n", "(95221, 6604, 47587)\n", "(15200, 13848, 533)\n", "(91106, 47235, 95124)\n", "(91396, 58746, 56994)\n", "(72070, 33359, 10785)\n", "(13733, 43410, 23707)\n", "(84853, 78378, 68689)\n", "...\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n" ] } ], "source": [ "junction_boxes = parse(8, ints)" ] }, { "cell_type": "markdown", "id": "ee9f47ae-09f5-479e-9e34-34246d723952", "metadata": {}, "source": [ "\"Gary\n", "\n", "### Part 8.1: What is the product of the sizes of the three largest circuits?\n", "\n", "The goal is to start connecting junction boxes, starting with the two boxes that are closest to each other in 3D space, then the next two closest, and so on. (I assume that a box can connect to an unlimited number of other boxes.) After connecting the 1000 pairs that are closest together, what do you get if you multiply together the sizes of the three largest circuits?\n", "\n", "I recognize this as a [**greedy algorithm**](https://en.wikipedia.org/wiki/Greedy_algorithm), consuming shortest links first, and I've [done that before](TSP.ipynb). I also recognize this as a [**Union-Find**](https://en.wikipedia.org/wiki/Disjoint-set_data_structure) problem, and I know there are efficient data structures for that problem. However, for this problem we don't make heavy use of the union-find functionality, so I'll keep it simple. (After finishing my code I feel vindicated: I see in my [other notebook](Advent2025-AI.ipynb) that Claude Opus 4.5 implemented a `UnionFind` class, and ended up with code that ran slower than my simpler approach.)\n", "\n", "The function `largest_circuits` calls `greedy_connect` to do 1000 connections, then finds the lengths of the unique circuits, and chooses the 3 largest. The function `greedy_connect` keeps a dict that maps each box to the circuit it is part of (initially just itself), and updates that dict when two circuits are connected together. The function goes through the 1000 `closest_pairs` of boxes, updating the dict for each one, and returns the dict at the end. We use the `heapq` functions `nlargest` to find the 3 largest circuits and `nsmallest` to find the `1000 closest pairs of boxes; these functions offer a speed advantage over sorting the whole list." ] }, { "cell_type": "code", "execution_count": 55, "id": "fb7744c9-105b-439b-aa57-caf93b8117b8", "metadata": {}, "outputs": [], "source": [ "def largest_circuits(boxes, n=1000, k=3) -> list[int]: \n", " \"\"\"Lengths of the `k` largest circuits (ones with the most boxes) after connecting `n` closest boxes.\"\"\"\n", " circuits = greedy_connect(boxes, n).values()\n", " return heapq.nlargest(k, map(len, unique(circuits)))\n", " \n", "def greedy_connect(boxes: tuple[Point], n=1000) -> dict:\n", " \"\"\"Go through the `n` closest pairs of boxes, shortest first.\n", " If two boxes can be connected to form a new circuit, do it.\"\"\"\n", " circuits = {B: (B,) for B in boxes} # A dict of {box: circuit_that_box_is_in}\n", " for (A, B) in closest_pairs(boxes, n):\n", " if circuits[A] != circuits[B]:\n", " new_circuit = circuits[A] + circuits[B]\n", " for C in new_circuit: # Keep the circuits table up to date\n", " circuits[C] = new_circuit\n", " return circuits\n", "\n", "def closest_pairs(points, n=1000) -> list[tuple[Point, Point]]:\n", " \"Return the `n` closest pairs of points, sorted shortest first.\"\n", " pairs = combinations(points, 2)\n", " return heapq.nsmallest(n, pairs, key=lambda link: distance_squared(*link))\n", "\n", "def distance_squared(P: Point, Q: Point) -> float:\n", " \"\"\"The square of the distance between 3D points P and Q.\"\"\"\n", " # We only care about sorting, so the distance squared is cheaper to compute than distance\n", " return (P[0] - Q[0]) ** 2 + (P[1] - Q[1]) ** 2 + (P[2] - Q[2]) ** 2" ] }, { "cell_type": "code", "execution_count": 56, "id": "337ab7d6-d142-4c56-a0a3-2b6cd06cd895", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 8.1: 93.0 msec, correct answer: 24360 " ] }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(8.1, 24360, lambda:\n", " prod(largest_circuits(junction_boxes)))" ] }, { "cell_type": "markdown", "id": "3839cac0-b8ef-408e-b33b-427e65c8eaf7", "metadata": {}, "source": [ "What were the sizes of the three biggest circuits?" ] }, { "cell_type": "code", "execution_count": 57, "id": "bf63af0e-e4df-43d2-9208-c44eaf9a5fb3", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[30, 29, 28]" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "largest_circuits(junction_boxes)" ] }, { "cell_type": "markdown", "id": "2f18d9ff-6d96-48e0-bcb5-c1af0dec6514", "metadata": {}, "source": [ "### Part 8.2: What is the product of the X coordinates of the last two junction boxes connected?\n", "\n", "Now we are asked to connect all the boxes into one circuit, still closest first, and compute the product of the X coordinates of the final pair of boxes to be connected. I don't see a clean way to make the `greedy_connect` function do both parts of the puzzle; I'll have to copy and paste most of `greedy_connect` to form `last_connected`, which keeps connecting until all the boxes are connected into one circuit, and then returns the two boxes that made the final connection. \n", "\n", "At first, I had `last_connected` call `closest_pairs` with the value of `n=len(boxes) ** 2` to make sure we consider every connection. But I noticed that this puzzle's run time was the slowest of all the puzzles, so I looked for an optimization and came up with one: guess an initial value of `n`, and then if that does not give enough pairs to connect all the boxes, double `n` and try again: " ] }, { "cell_type": "code", "execution_count": 58, "id": "abf5d30b-f6e7-47bf-8534-3817af9d1fd3", "metadata": {}, "outputs": [], "source": [ "def last_connected(boxes, n=10000) -> tuple[Point, Point]:\n", " \"\"\"Go through pairs of boxes, in closest first order. \n", " Return the last two boxes that finally make it all one big circuit.\"\"\"\n", " circuits = {B: [B] for B in boxes} # A dict of {box: circuit}\n", " for (A, B) in closest_pairs(boxes, n):\n", " if circuits[A] != circuits[B]:\n", " new_circuit = circuits[A] + circuits[B]\n", " if len(new_circuit) == len(boxes):\n", " return (A, B)\n", " for C in new_circuit:\n", " circuits[C] = new_circuit\n", " return last_connected(boxes, 2 * n) # If above didn't return then `n` was too small; try again" ] }, { "cell_type": "code", "execution_count": 59, "id": "58f06244-ca67-47c9-8ca5-3346a249e1fc", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 8.2: 113.5 msec, correct answer: 2185817796 " ] }, "execution_count": 59, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(8.2, 2185817796, lambda:\n", " prod(Xs(last_connected(junction_boxes))))" ] }, { "cell_type": "markdown", "id": "9e75bcf2-d62b-47b1-bec0-b2449351d819", "metadata": {}, "source": [ "# Day 9: Movie Theater (Maximal rectangle inside a polygon)\n", "\n", "On [**Day 9**](https://adventofcode.com/2025/day/9) the Elves are redecorating the movie theater floor by switching out some of the square tiles in the big grid they form. Some of the tiles are red; their *x*, *y* coordinates form the day's input file:" ] }, { "cell_type": "code", "execution_count": 60, "id": "2dba6fa4-a09b-4ab3-a163-0f94f98e82f2", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "Puzzle input ➜ 496 strs of size 10 to 11:\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "98214,50351\n", "98214,51580\n", "98424,51580\n", "98424,52775\n", "97835,52775\n", "97835,54031\n", "98280,54031\n", "98280,55255\n", "...\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "Parsed representation ➜ 496 tuples of size 2:\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "(98214, 50351)\n", "(98214, 51580)\n", "(98424, 51580)\n", "(98424, 52775)\n", "(97835, 52775)\n", "(97835, 54031)\n", "(98280, 54031)\n", "(98280, 55255)\n", "...\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n" ] } ], "source": [ "red_tiles = parse(9, ints)" ] }, { "cell_type": "markdown", "id": "f8d3b123-234d-41b9-bb5b-090ad1b11e78", "metadata": {}, "source": [ "\"Gary\n", "\n", "### Part 9.1: What is the largest area of any rectangle you can make?\n", "\n", "The Elves would like to find the largest rectangle that uses red tiles for two of its opposite corners. That's easy; we can try all combinations of two corners and take the corners with the maximum area. (I'll define a pair of corner points to be a type called `Rectangle`.) The only **tricky part** is remembering that we have to add one to the delta-x and delta-y values before multiplying them; the area of a square with corners (0, 0) and (1, 1) is 4 tiles, not 1. Initially I had a **bug** and forgot this on my first submission." ] }, { "cell_type": "code", "execution_count": 61, "id": "75f2742e-9dbd-4005-a882-3d3931fb1b36", "metadata": {}, "outputs": [], "source": [ "Rectangle = tuple[Point, Point] # Type: a rectangle is defined by two opposite corners\n", "\n", "def tile_area(rect: Rectangle):\n", " \"\"\"Area, in tiles, of a rectangle defined by two opposite corner positions.\"\"\"\n", " (x1, y1), (x2, y2) = rect\n", " dx, dy = abs(x1 - x2), abs(y1 - y2)\n", " return (dx + 1) * (dy + 1)" ] }, { "cell_type": "markdown", "id": "271f2f81-dc40-41db-9912-0c45f4d75dbb", "metadata": {}, "source": [ "That's all there is to Part 1; just maximize the area over all combinations of two corners:" ] }, { "cell_type": "code", "execution_count": 62, "id": "27f350c5-7866-4b7b-8d32-91512fcec5b9", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 9.1: 11.7 msec, correct answer: 4772103936 " ] }, "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(9.1, 4772103936, lambda:\n", " max(map(tile_area, combinations(red_tiles, 2))))" ] }, { "cell_type": "markdown", "id": "dbd4e094-109f-420c-90b9-0ada15b1da9d", "metadata": {}, "source": [ "### Part 9.2: What is the largest area of any rectangle that has only red and green tiles?\n", "\n", "In Part 2 we pay attention to the **green** tiles on the floor. Every red tile is connected to the red tile before and after it (in the input list order) by a straight line of green tiles. (It is guaranteed this will always be a straight horizontal or vertical line.) The last red tile loops around and is connected to the first one. This forms a closed polygon, and the interior of the polygon is also all green. (The color of the tiles outside of the polygon is not stated, but I'm going to say **white**.) The elves want to know: What is the largest area of any rectangle that consists of only red and green tiles?\n", "\n", "**This is a tough one!** More difficult than all the previous puzzles. There are only 496 red tiles, so enumerating all pairs of them in Part 1 was easy. But the *x* and *y* coordinates range from 0 to 100,000, so there are roughly 10 billion total tiles to consider. I need some way of finding the biggest rectangle without having to consider tiles one by one for every candidate rectangle. \n", "\n", "I really think it will help to see what the red and green tiles look like:" ] }, { "cell_type": "code", "execution_count": 63, "id": "b5967a65-338d-4198-9f59-986ff74132e6", "metadata": {}, "outputs": [ { "data": { "image/png": "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YMzn9iM/3x4HAACa57XXZOE1N9OxR8ZX9J555hnp16+fXHbZZXL00UfLKaecIrNmzYpe/8EHH8i2bdvsdm1E+/btZcCAAbJy5Up7Xk91u1a/T4Qen5eXZ1cAI8cMHTpUCgsLo8foquDGjRvtqmLkmNifEzkm8nMS1dXV2ZXC2I+cmG2bny8BLb6IWVZ28zIyAACuHInmQhkP9N5//3159NFHpbS0VJ5//nkZP368/PjHP5Z52uBXxAZ5qnPnznFfp+cj1+mpBomxCgoK5Mgjj4w7xul7xP6MVMdErk9UUVFhg87Ih+b9ZXO27QVXivymn0ht1QKRuXNDy8pahaunuswMAAAyo7Q0lI/nhGKMA4LBoJx66qnyq1/9yq7maV7dtddea/Pxct3kyZNl586d0Y+tW7dmdeTZoidFbnhVpOjiy0Ijz3QFT2fcspIHAEDz7qaJeGIXLeMrelpJ+/Wvfz3ushNOOEG2bNliP+/SpYs9/eSTT+KO0fOR6/T0008/jbu+vr7eVuLGHuP0PWJ/RqpjItcnat26ta3yjf3ICkaeAQCQld204yeKDCsXqX15mSd20TIe6GnFrebJxXr33Xdtdazq0aOHDbReeOGF6PWaC6e5d4MGDbLn9XTHjh22mjZi6dKldrVQc/kix2gl7v79+6PHaIVunz59ohW+ekzsz4kcE/k5OYuRZwAAZM3RuyUU4GnvPJeu5EWZDFuzZo0pKCgwd911l9m0aZOZP3++adOmjfnd734XPebuu+82HTp0ME8//bRZt26dueCCC0yPHj3M3r17o8d85zvfMaeccopZvXq1efnll01paakZOXJkXKVu586dzejRo83bb79tFixYYH9OZWVl9JgVK1bY23L//febDRs2mGnTpplWrVqZt956K7erbtesSa6y1Y81a1r2dgAA4CO1j003DbGvu4GAMbNnt+htyHTskfFAT/3lL38xJ510km2Z0rdvXzNz5sykFitTpkyxgZoec+6555qNGzfGHfP555/bwK5t27amXbt25uqrrzZffPFF3DFvvvmmbeWi3+PYY4+1AWSihQsXmt69e5vCwkJz4oknmmeffbbR/4+sBXrGmH2jR0WDPXtaXt7itwEAAOP39ip5eS3azizTsUdA/8n2qmKu0i1lrb7VwoyWztfbvW+3DJvQVgZvFamYskyKBw9t0Z8PAICv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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def plot_tiles(red_tiles: Sequence[Point], figsize=(7, 7)) -> None:\n", " \"\"\"Plot the red tiles (as dots) and the green border (as lines), but not the green interior.\"\"\"\n", " red_tiles = red_tiles + red_tiles[:1] # Close the loop\n", " plt.figure(figsize=figsize) \n", " plt.axis('equal')\n", " plt.plot(*T(red_tiles), 'g-')\n", " plt.plot(*T(red_tiles), 'r.')\n", "\n", "plot_tiles(red_tiles)" ] }, { "cell_type": "markdown", "id": "cd555e6f-897d-4d0f-bdb7-e946b79a9cc9", "metadata": {}, "source": [ "**Very Interesting!** Here's what I'm thinking:\n", "- Most of the lines of green tiles are very short, except for the two long lines across the \"equator.\"\n", "- A maximal-area red-and-green rectangle can't cross the two equator lines, because there are white tiles between them.\n", "- Therefore one of the corners of the maximal rectangle has to be one of the two points on the east end of the equator lines, and the other corner has to be somewhere on the left side of the circle.\n", "- The points are all roughly in a circle, so we're looking for a rectangle roughly inscribed in the circle.\n", "- A roughly correct way to check if a candidate rectangle is all red-and-green is to make sure **the rectangle contains no red tile** in its interior. If the red tile is in the middle of the rectangle, then there must be white tiles on at least one side of the red tile, and thus in the rectangle (with some caveats).\n", "- The red tiles are serving two purposes: as potential **corners** of the maximal rectangle, and as **obstacles** that disqualify a candidate rectangle.\n", "- To be more precise, consider the diagram below, in which the two large red circles mark the corners of a rectangle depicted with small purple squares. I have filled in the green tiles that connect the red tiles to form a polygon, and used light green for the interior of the polygon.\n", "\n", "        " ] }, { "cell_type": "markdown", "id": "279fc8b1-bcf6-4b09-a9b7-ed5875242f76", "metadata": {}, "source": [ "- Does the purple rectangle contain only red and green tiles? Let's consider red tiles that are potential obstacles:\n", " - The two **corners** are obviously **ok**; they define the rectangle and they're red.\n", " - The two red tiles **on the border** at the bottom right are **ok**; they don't let a white square in.\n", " - The two red tiles that **extend one square in** to the rectangle at the top middle are **ok**; they don't let a white square in.\n", " - The two red tiles that are **adjacent** to each other the left side are **ok**, even though they extend three squares in, because there is no room for any white squares to fit between them. This only applies when the two adjacent tiles form a 180° U-turn like this.\n", " - The red tile that **extends two squares in** from the lower right corner **disqualifies** the rectangle; it lets in the three white squares in the lower right corner.\n", "- Besides red tile obstacles inside the rectangle, we also have to worry about two red tiles that are both outside the rectangle, but whose connecting green line passes through the interior of the rectangle. But if we assume that the largest rectangle has width and height of at least *d* spaces, then we can lay down an additional obstacle every *d* spaces, and that means there will always be an obstacle inside the rectangle. I call such obstacles \"breadcrumbs.\" \n", "- If there were more red tiles we could put them into a data structure like a [quadtree](https://en.wikipedia.org/wiki/Quadtree).\n", "- Normally in problems like this we have to check if the rectangle we are considering is inside the polygon or outside of it. But for polygons that are anything like mine (i.e., mostly convex), and if we are only considering rectangles with corners on tiles, any sufficiently large rectangle must be on the inside, so I didn't bother checking.\n", "\n", "I'm ready to start coding! I'll start with some functions that manipulate the sequence of red tiles: finding obstacles, laying down breadcrumbs, finding adjacent tiles, and finding the 2 corners on the equator." ] }, { "cell_type": "code", "execution_count": 64, "id": "e08d6c65-5b4e-456e-b4de-38339d209372", "metadata": {}, "outputs": [], "source": [ "GAP = 10000 # How big a gap between red tiles to put in a \"breadcrumb\" red tile\n", "\n", "def find_obstacles(red_tiles: Sequence[Point], d:int=GAP) -> set[Point]:\n", " \"\"\"Obstacles are tiles that, when found inside a rectangle, disqualify that rectangle.\n", " They are the set of red tiles with breadcrumbs added, minus the adjacent tiles with 180° turns.\"\"\"\n", " return (set(red_tiles) | set(breadcrumbs(red_tiles, d))) - adjacent_180_tiles(red_tiles)\n", " \n", "def breadcrumbs(red_tiles: Sequence[Point], d:int=GAP) -> Iterator[Point]:\n", " \"\"\"Extra obstacles to lay down along the trail when the gap between red tiles is too big.\"\"\"\n", " for (p, q) in sliding_window(red_tiles, 2):\n", " if distance(p, q) > d: \n", " dx, dy = d * sign(X_(p) - X_(q)), d * sign(Y_(p) - Y_(q))\n", " for i in range(1, distance(p, q) // d + 1):\n", " yield (X_(q) + i * dx, Y_(q) + i * dy)\n", "\n", "def adjacent_180_tiles(red_tiles: Collection[Point]) -> set[Point]:\n", " \"\"\"Yield all adjacent points that form a 180 degree U-turn.\"\"\"\n", " return union({q, r} for (p, q, r, s) in sliding_window(red_tiles, 4)\n", " if distance(q, r) == 1 and direction(p, q) == direction(s, r))\n", "\n", "def find_2_corners(red_tiles, d:int=GAP) -> list[Point] | None:\n", " \"\"\"Find two adjacent corners, separated on each side by a gap of at least `d`.\"\"\"\n", " return first([q, r] for [p, q, r, s] in sliding_window(red_tiles, 4)\n", " if distance(p, q) > d and distance(r, s) > d)\n", "\n", "def direction(p: Point, q: Point) -> Point:\n", " \"\"\"A unit vector in the orthogonal direction from p to q.\"\"\"\n", " ((x1, y1), (x2, y2)) = p, q\n", " return (sign(x2 - x1), sign(y2 - y1))" ] }, { "cell_type": "markdown", "id": "4425bb14-d9ca-4afb-8f1c-5787bf3e17a4", "metadata": {}, "source": [ "Let's visualize the breadcrumbs (blue squares) and the two corners (black diamonds):" ] }, { "cell_type": "code", "execution_count": 65, "id": "9dabf8bd-bdac-4b9a-941f-9de68480ca5d", "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAnoAAAJGCAYAAADMEijaAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjgsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvwVt1zgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAdalJREFUeJzt3Ql4lOW5+P97khASpAhKBRSJUgJYta0KAiKISE0tPcd9oUhTi4KIVtRjEc8BrNbG7ajVgoalQi2Vgv+2WsRaKhER2bQqKhzEqkCs6E8poJAEknn+1/3MwuwkMMm8y/dzXWEyMy/JZCaZued57iVgjDECAAAAz8nL9Q0AAABA8yDQAwAA8CgCPQAAAI8i0AMAAPAoAj0AAACPItADAADwKAI9AAAAjyrI9Q1wsmAwKP/617/ka1/7mgQCgVzfHAAA4HHGGPnyyy/l6KOPlry8Q1+PI9DLQIO8Y4899pDvZAAAgKbYunWrdO3aVQ4VgV4GupIXubPbtWt3yHc2AABAJrt27bKLTJEY5FAR6GUQ2a7VII9ADwAAtJRspYxRjAEAAOBRBHoAAAAeRaAHAADgUQR6AAAAHkWgBwAA4FEEegAAAB5FoAcAAOBRBHoAAAAe1eRA7+WXX5b/+I//sDPYtJnfn//856QZbVOmTJEuXbpIcXGxDBs2TDZt2hR3zPbt22XkyJG2CXH79u1l9OjR8tVXX8Uds27dOhk0aJAUFRXZDtH33Xdf0m1ZuHCh9O7d2x5z8skny+LFi5t8WwAAALyqyYHe7t275dvf/rZMmzYt5fUakD3yyCPy+OOPy+rVq+Wwww6TsrIyqa2tjR6jQd67774rS5YskUWLFtngccyYMXHjP84991wpKSmR119/Xe6//3654447ZMaMGdFjXn31VRkxYoQNEt944w254IIL7Mc777zTpNsCAADgWeYQ6H//05/+FD0fDAZN586dzf333x+9bMeOHaZ169bmqaeesufXr19v/9/atWujxzz//PMmEAiYjz/+2J6fPn266dChg6mrq4seM3HiRNOrV6/o+csuu8wMHz487vb069fPjB07ttG35UB27txpb6ueAgAANLdsxx5ZzdH78MMPZdu2bXaLNOLwww+Xfv36ycqVK+15PdXt2j59+kSP0ePz8vLsqlvkmMGDB0thYWH0GF2J27hxo/z73/+OHhP7fSLHRL5PY25Lorq6OruaGPsBAADgVlkN9DSwUp06dYq7XM9HrtPTo446Ku76goICOeKII+KOSfU1Yr9HumNirz/QbUlUUVFhg8HIh+YGAgAAuBVVtzEmTZokO3fujH5s3bo1d48MAACAkwK9zp0729NPP/007nI9H7lOTz/77LO46+vr620lbuwxqb5G7PdId0zs9Qe6LYlat25tK4FjPwAAANwqq4He8ccfb4OoF198MXqZ5rlp7t2AAQPseT3dsWOHraaNWLp0qQSDQZs/FzlGK3H37dsXPUYrdHv16iUdOnSIHhP7fSLHRL5PY24LAACApzW1euPLL780b7zxhv3Q//7ggw/azzdv3myvv+eee0z79u3NM888Y9atW2fOP/98c/zxx5uampro1/je975nTjnlFLN69WrzyiuvmNLSUjNixIi46thOnTqZUaNGmXfeecfMnz/ftGnTxlRWVkaPWbFihSkoKDAPPPCA2bBhg5k6dapp1aqVefvtt6PHNOa2ZELVLQAAaEnZjj2aHOhVVVXZG5D4UV5eHm1rMnnyZBuoaSuTc845x2zcuDHua3zxxRc2sGvbtq1p166dueqqq2wAGeutt94yZ555pv0axxxzjA3aEi1YsMD07NnTFBYWmhNPPNE899xzcdc35rZkQqAHIKWtW41ZujR02pTrAKCFY4+A/pPrVUWn0q1erb7Vwgzy9QAPq64W0ak5paUiXbtmvnz2bDFjxkggGBSTlyd7pz8q9VeV26sKnpgrhdfdYK+TvDwRbfI+enTo/61dK7J8ucigQSJ9+x74ewPwpV1Zjj0I9FrwzgbgQGkCt5RBW1mZmJKS0GVh9QGR4yaEPt/yUHzis369mk0bpNUdd0rBk/MkEN4CqR81UvbOqswcGBIAAr60i0DPvXc2AIeprk4ZuA0YLbJqtkh+7H5Hfr7I738vcvnlSV9mSLnIUbtFFjyd/C1uGypSsVRskBehX/YHI0T+8lTqwDB/yd/TB4AAPG1XlmMP+ugB8K9Nm+KCPFVgRAZuTQjyVEOD1NbXiQnEhmxizy+eslHmXjA35bfo9Xl8kKf0/KXvJj8B62256YZeUjBu/P7bpadjx4ZW+A6W/t+qquSvke5yAJ5BoAfAGdIFHZrb9uCDodPG/p/GXl5aalfRYpn8fKkYu9CuusVdLiIXL/qRFrDFXR4IBKRNYRspPmuonon/P4GAXHFH6q91+cVTU94NnXenDjLl/fcP7mfWrelu3USGDrWndZXTZffe3fZUVzP1ctHT2bNT3h4ALpeVkg6PouoWaCGzZplgXp6GUPa09vFp5qu6r8zeUSNNUJ+m9HIRe14v1w89JvJ/jJ7OmrX/awUCof8TCES/Vrrj9fJ9ke8RuVyrZsOXxX7cWJZ8mf2oqop+b5PqNmlXgtjj9bxW5YZvZ+RDb++eV5ZFb3/08rw8s/ufG5v8M+v/Sfxa9SKmz9Vi6gMJP0N+PpXCgAPkvL2KnxDoAS1g69b9wUv4Y19AzPdHhIK7uIAnHKQcc5OYhsTr8vJSBkmRwCbV8RoI7Zz2YDToiQZ6GoQl3KZgfn7o6ydcnhQg6eca+CW2V1mzxpiHHgqdRqQKDPX+aMLPkO5n1vvokktSB6ZTzjpAwEqLGMAzsQdbtwAcmSd33qbUuW2aP3fG1tT5bdNvOUtbCcRdni8iI95Onw932PU3R7dKA5F8OKUFEFqAYb9IvgQqK6V44GAJJFwulZXxbVH08yFDklulaEuVCRPiW6togcXmzaEtVz3V83p/pPgZhr/XtJ95wNbk+y/i9osfTs41zMuTPd2OzrylS04f4DoEegCaR6agIPa6NHlyo29PndtWMXlZ2sKHdIHN+L7jm54Pp0HXRx+FbqeeRqpe011+sBIDQ+2nl+L+mHjxQ036mZ+88Lcy596NSQGdfu3W/c9IOl7HUJ5V0UtaXRtfCKKtZ/Z88B45fYBbZWVd0KPYugWym3OXLlcuZZ5cutw21YT8Nvs9dLs03fEH2orNBf359XZEbk9kO7kpP3PkZ0j1tdLkIE4dnHpLd8z3D5DTp/fv//5v/La0YgsYaDJy9FoQgR6QvZw7zRlLl1u36xdTkvPkMuW2ZSp8SBXYHMzxuZYq1+9gf4bEr5UuB/FXDzUpp2/P3xanLZhJWzgS+f6MiQNSYgRaC6JhMnAQdEtT87ua0FS4IZxXFqW5b7oteqCRYLr1q9usPXokjy7LxuVOlK2fQXPvNB9Rt6ojuYZlZSLaiiUm50+3fmv/vwVSdNGlSU2fy88XmftMFptBMw0EECZjtCACPSA70yY0x6zmvfUSWLlKiq8MzYVtVMCouWtoPqmCQw0Ax4wJNWqOBGLdu6cM3n/dR+T615K/7Jxvifx4XfLlY78v8thipoEAmTAZA4Dziitimxp37RqaFxuzkqMVq22690zbVDipYEBXmDT4QPNKVSGcqhI4TYFIuoKZdM2ge31xkNNAqPYFDhpVtwDipXpRTTNdQT/2/ehKMaefLnLLLfZUz9c11CXGcyEaUMycuT9o0CBw5kz7kbFlCXIbAOppqnYzF14igfL4FVo9X/yTq1MG9ON++FCTqp9rNrxNtS9wiAKa+HeoX8Sr2LqF72hAN2aMXVnRlThdmWv47jAp7tE7rleb5tSV3CTS5UuRNbOSc7SCB8q5S7Vl6KY8Ob9K9xjpSu6KFSIDB+7vE5hqC7iJOYCa6/fs/IQgMPZ3iZw+eNCuXbvk8MMPl507d0q7du0O+esVZOVWAXCfxBdJza0LB3lKT/PHjZefnidSmfB2MNKQt+uu1E2N44K82N50sStEicFcqsvgLOkeIw3uYhtBK93y1cAuMTDU1duYAFAbUBe3PzLpS+rvUen29Ct9ec89m76oA0AUK3oZsKIHP63cBY8/TorLhicdesdgkTteTv4StfN+a4suis48K2klRgUOpooW/lwZ1PM6hSOhgKd24fyDW+kDXGxXllf0yNED/JZzl2bl7pI5w1Mm1k+csDDldIWiwWeHRoKlyNEKzJpFzh0OPQew/ZEpV4zTrfTZ4JHCDSAOW7eAH1fuUsyW1RfPVC+qxR06hrbbEnuuRV6k58wRGT8+OUcr1bYdkE6qrV4N2nRbNmGlr2LyUjF/GxKXN2p/v1etkMJzzmE7F4jB1m0GbN3Ca/3s6gMi518hsuip5AKK2j8ulKJLLo87PinxncANLS1NY2et/k4sELK/srH/l+1cuBBbtwAaZ9Om+KCtESt3mhifts1Jqp5rQEus9OmbDU0/0FM9r7/bCQ0j8jMVAQE+xtYt4FWlpaFmxam2vZacnbxyp9tlGsix5QqnV/tGGjjH/m7reWPiA8DExtvaBmb5cpFBg/anGNCiBR5HMQbgVZEJFYH9QZ5NcNcCClbu4GapijdmzJD6K38YLSjS030/vEJ2H9UhfWPvyuk2vcGOd9NT3SYGPIYcvQzI0YMrxaxQ6IvckPFtZeAWkYopy2yQF3ccOXdws9jfYQ3uUuSkHjehiY29V64U+eqr/f0lgRZGw2QA6bectMr2mmvs9pW2RMn74aWy6vehVhTm72fHN5WlQTHcLvZ3uKoqZU5qj+0ip3zS+Mbepl+/0PYvTZjhEazoZcCKHtw+qkw/o3ExfCFN0+Wa99ZL4JNtjWrszd8LnICqW8Dv0jQ8vumGXkmViImrGFQhwrPSNF1u071n6sbeZWUpV/niULULD6DqFnDbFm2atildvmrE10qsQgS8JN183VSNvbt0SV4BTLUCzt8LXI6qW8DpW7ThqkA91SrBPSXHJI0k0/MTf7kseVSZntdco1R98QAvytTvUVuqTJgQOk2xAlg/amRclTp/L/ACcvQyIEcPTpxsMWC0yOpZCe/SNJjbvFnkhRdSThGguhZI/3cW+fuIVqlvFamYnFClnq4PX7rCKOAgUXULeFnsC0aaLVp9EUpaitfj9MUq3dYVLz7AASt3Cyqny6rZ4Sr1JWdLnfahvCqU21d49VgpeHKe3drVLV5d/ds7q1IKnpgrhdfdwHxdOBYrehmwooecVtLefacU3j45voo2EJDa5S9J0eCz08+kBZC1FfRMffh+MELk2fmhwDDub5FefDgEVN0Cfqmkvf1/xCRW0QYCUlzSPfNkCwBNl2YFXfvwnbkldR++895PCPJievExbQNOwYpeBqzooSW3ae0LQ2PocHdNNmeyBZDTPny1Mx6XojHX0osPWcWKHuDFatrVr6aspE2qoo1t95CpuhBA8/bhKy+X4h496cUHx2NFLwNW9JAViRV5aXKB8nTqUmIl7T33iEyaFF9FGxlhBiD7Mq2Ua9VtpA+fVt2mWgVkGg0OEVW3gMtHlQWPP06KU+QCJdFj9MVEiyzSvfAAyK5MM6D17zG2rUpkFTCmpVH9D6+QwO/m2b9pE14V5O8WucSKXgas6OGQpFm5O/8KkUVPJVfw2T/I2P9PJS3gnV589NpDI7GiB7h8VFnp9tQVfPJf/yXy0EPx27Ss4AGu78Wn6LWHXGFFLwNW9HAoW7QN3x0mxT16N60PnmKbFvDUKn7AiIRLPEJYrUcGVN0CTli50xYnepquB9648XJWRa+m98GjkhZwrzSr+HFBntJVe31Dl+r5BMiypElKAJrQFqVyutSsX3dwo8p0BU+f4PWUSlrA/TRtQ6vlY+gKf2KtlV62p9vR9vkj8nxiq3dnz27Rmwt/INADGivNyt0lc4YnP5GLSMXYhfYJPQ598AB/9eK7915dyo87LBgM2hX/gnHj979J1FOt3o3ZKWClD9lAoAc0VhOLK4o7dGRUGeA3iav1p50Wl6erNAzUFf9U49NqNrzNSh+yimKMDCjGwIESrbVPVu2ypemLK8INkimwAHwqzWi12oXzpeiiS5PaLP1ghMiz8xOCQIo3fGXXrl1y+OGHy86dO6Vdu3aH/PVY0QMOJLKFImKraevDF+u2rDZDteOR0hVXKAosAP9KM1qtuP2RKXcCdIcg1UqfLFxIwQYOCoEe0ITii+DyZYnpNiEUVwBIJ9XzQ6rCjfx822Q5ae61/nPzzRRs4KCwdZsBW7c+l2qrlukVALJFq2xjxqfZnYCyMjHduiXl9UWxjet5u9i6BZpRbKVbiuKLQKZ+WABwqCt9+ryTLsjjOQcHoeBg/hPgi+kWd98phYFA/GSLVCt6PXrk4tYC8Nj4NCuypZvwJjOK5xw0ETl6QLoeebf/T8rJFtG8GubRAmjm4g1909kQk8PHDGw0FSt6QIYeeUk08PvDH0S+/vXQSl7sO3EAyAbdwi0rs2khNd2Ots2Vte9exeSltsrfCqeX2BVAnoeQAYEeoEpLQ+1SYgsvdOXOmPh8GX1HPWAAT6wAWmRLN79yuqyaHWq5YpacLXXTH7VXF153Q+j5Sp+ndAWQMYpIg6rbDKi69RedO6kjzXQlz4R7XVmJVXE8oQLIUeV/fUBfuEPTNaKoxPWUXVmuumVFD/4Ws/1Rf1W5nPnaeBm4RaRiSswWSXgLha1aAI5MKYlU/7OFixQI9OBfCVW2eSMukVW/D2+R/P3s/dshiVVxANASUlTgpk0pOeywUJsWcvaQgKpb+FOKKtuieQuio4fs5bplqyt+AOCU8WkzZkj9lT8MTcsIt3yq79tHTP/+doKPnaurjZiBMHL0MiBHz8P0na8+KTbmuCFDWuIWAUBq+oYzkj6iwR0TezxtFzl6QBZy8tq2Ta6ypRkyACeKTR+pqmr8xB5STsDWLXyXk6fbGkOH2m2OfX1Pjdv+CJxxRtwWCY1JATg2by9GUn0G0zMQgxw9+DYnr9Xq16LvhO3p6tUiK1fGz50EAIfn7dWPGmnbrkSLNbQNVGQ1L3Z+N3yJQA/elPjklqJNQcrtjt27Qzl5bHkAcCp9E6pvRsNvSoMDz7C99SxjpK6+Tnbv3W17g0Z2MSjS8C+KMTKgGMMbbVP2Tn9UGr47TIp79I5rSZAyJ0+fPAnyALi8qfKA0RKdqJH0HKcYn+ab2IMVPbhXqi2JFFu0Ou1CZ0Wa2L5Tel0gsD/XhZw8AB5qqqyzceOCPNXQIHsffIBVPp8h0IP7CytKSuwWhW5V1Kxfl/ZJL+mXXQO/+fPJyQPgreKM/HypGLswqUhDz+c/9Kv9z5H0C/UFAj24T5pVu163tZXBC4enfHKzT3oJT4Z2FW/AAHLyAHirqXJlpRS3PzIpD1nPx83IjW3FAs8i0INntip6bBdpuy+5yELPF3foaDvK0z4FgNeLM+z5VCt9eXliNGUlVSsWqnM9i2KMDCjGcE/ysW5V1Ly33n5eXHpCfCAYW2QR22GeogsAXqaj0HSUo67ahfOQ9y2rkoIn59k3wHZ82qiRtmq38LobQs+bGhxG5nzDE7EHgV4L3tnIHs3J0+1aXckz4a2K6BNTiic3nrQA+NIBxqdpha62Zonb0qUDQU4xAg3QJ6eryuUbG8fb7drFU9ZLm+49998vGvCVlbFyBwAHGJ+mb5aTMELNUwpyfQOAJquulrz166TLlymaHqd6cgMA7M/bi0170fPGxPUYtSt6hx0WyvnT/8NzqatRjAFXtlUpLhsua2aJVM0N5eTZ7VoAQNMqdGfMkPorfxg397u+bx87D5yJGt5Ajl4G5Og5TIoijChySgAgK3l7TA3KLSZjwL9StFWJohcUADR+ZS8y07uxc8Dpteda5OjBHe8+dS5j27Y2nyTtil743SkA4BDy9lLNAef51bXI0YN7Rp317y/7+p4al0tiMacWALKWt6e99bTtin2e1SBQW1RF+pAmzheH4xHowVWjzlqtfi36TtOe6pPQypX0yQOALE3W0AbK2lvPMkbq6uts79LIm27RUwrgXIOtWzhvizZSzt+Y3BG9fvfulryVAOA9kZZU1dWhKRnhi7Xtijan18AvEPu8q03ptV8prVccjxU9OG+LtqTEvnvcU3JM0lzGpN6e5I4AQLPPEo+bnBEp0NDdFLZyHY9AD47cotV3kGdV9BIT28RTr9PALzKom9w8AGie4owYmqeX+CZb34Sbyy9nK9cFCPTg2HeQA7em+AXVwG/+/GguCTNsAaCZmyrfe6++y056Lo5O04hs5VKk4UgEesidSAVXuG1KLJOfLxWTlyVdbp98BgzY3wMKANCsxRly2mnxI9LotecqBHpwZNuUwJVXSvHAwXY8T+w7y2iZPwCgZZoqp9rOTTyefGnHItCDM9um/O53oRW/xHeWeh4A4Lxee4riDMch0EPLa+rIndh3lgAAx/Xa27esij57DhUwiWWNaLbBwohZ0WOINgC4E8/hroo9WNFDy+vaVfZOf3T/sr9WdZWXk4sHAF7clUFOMRkDOVF/Vbl8Y+N46bFdZPGU9dKme0+RX/wi9MSgw7PZpgUAZ4oUZ8QEe7aILvYYijMcgxU9tLzqasl7aZl0+TLhiYFcPADwRnHGTTfl9CZiPwI95KStSnHZcFkzS6Rqrkhx6QkMyAYArxRn6ErfAw+IaAut2bNzfENBMUYGFGM0fwJvlL4z1CcNtmwBwF14bvdXMUZDQ4NMnjxZjj/+eCkuLpZvfOMbctddd8XNLNXPp0yZIl26dLHHDBs2TDZt2hT3dbZv3y4jR460P2T79u1l9OjR8tVXX8Uds27dOhk0aJAUFRXJscceK/fdd1/S7Vm4cKH07t3bHnPyySfL4sWLs/0j4xASeKNI3AUAd+K53dGyHujde++98thjj8mvf/1r2bBhgz2vAdijjz4aPUbPP/LII/L444/L6tWr5bDDDpOysjKpra2NHqNB3rvvvitLliyRRYsWycsvvyxjxoyJi3jPPfdcKSkpkddff13uv/9+ueOOO2SG5g2EvfrqqzJixAgbJL7xxhtywQUX2I933nkn2z82DjTmTE9LS5NHmkWQuAsA7pRickYUz+25Z7Js+PDh5ic/+UncZRdddJEZOXKk/TwYDJrOnTub+++/P3r9jh07TOvWrc1TTz1lz69fv16X/8zatWujxzz//PMmEAiYjz/+2J6fPn266dChg6mrq4seM3HiRNOrV6/o+csuu8zenlj9+vUzY8eObdTPsnPnTns79BQHYdYsE8zL07Vce1r7+DSzZ+RlJmjba0r01OTn22MBAC6lz+H6XB7z3B7kuf2gZDv2yPqK3hlnnCEvvviivPfee/b8W2+9Ja+88oqcd9559vyHH34o27Zts9u1EboX3a9fP1m5cqU9r6e6XdunT5/oMXp8Xl6eXQGMHDN48GApLCyMHqOrghs3bpR///vf0WNiv0/kmMj3SVRXV2dXCmM/kL0xZ/njxkvhvAXxo870XaA+How2AwDXF2fU/G2xnH61yJBykZr31vPc7sU+erfddpsNkDQvLj8/3+bs3X333XYrVmmQpzp16hT3//R85Do9Peqoo+JvaEGBHHHEEXHHaB5g4teIXNehQwd7mun7JKqoqJCf//znh3gPIF3ORkGqGSx6zO7d3GkA4HZdu0rwqA7yyfMipdvDl2najubg6/YuxXY5kfUVvQULFsi8efPk97//vfzjH/+QuXPnygMPPGBPnW7SpEm2yiXysXXr1lzfJPdKkY+n500goX86+RsA4BkFT8yVzQ+HW2f16C2mWzeRoUNpteKlQO/WW2+1q3pXXHGFrXIdNWqU3HTTTXa1THXu3Nmefvrpp3H/T89HrtPTzz77LO76+vp6W4kbe0yqrxH7PdIdE7k+UevWrW2Vb+wHDrL4QiQ05iwmyAvMmCGBmTMZdQYAXlRdLYXX3SD54d2bgDH2I7p7M3Zs6DUC7g709uzZY3PpYukWbjC8jafbrRpoaR5fhG71au7dgAED7Hk93bFjh62mjVi6dKn9GprLFzlGK3H37dsXPUYrdHv16mW3bSPHxH6fyDGR74PmaYas7970NLh8mSQu4CU22SQ3DwB80GZF0UYrN0yWlZeXm2OOOcYsWrTIfPjhh+aPf/yj6dixo/nZz34WPeaee+4x7du3N88884xZt26dOf/8883xxx9vampqosd873vfM6eccopZvXq1eeWVV0xpaakZMWJEXKVup06dzKhRo8w777xj5s+fb9q0aWMqKyujx6xYscIUFBSYBx54wGzYsMFMnTrVtGrVyrz99tuN+lmoum2CrVujFbYmsao2trp269amfFUAgFvo83vC6wCvAU2X7dgj64Herl27zI033mi6detmioqKTPfu3c1///d/x7VB0RYrkydPtoGatlU555xzzMaNG+O+zhdffGEDu7Zt25p27dqZq666ynz55Zdxx7z11lvmzDPPtF9Dg0sNIBMtWLDA9OzZ0xQWFpoTTzzRPPfcc43+WQj0mmDp0vR/3LEfVVVN+aoAALe2WcnLM/WRN/4aAGpbNX2t4A1/i8YejEDLgBFohzYCR39T43ZuGXMGAN6neXjvvy91q1ZIwaT/kfzw64Hm8ticPU3v0uEGtNVy5wg0+FC4fH7v3XfGF1+Ul1N4AQB+o21UevSQwv+eYoM8Cb/ppzDDI3304MMCjHBj5MJAIPSuLWLQIJFf/MK+s9M/enooAYBPNLYwg956zY4VPWRv+oUx0V+oQKSUXg0Zwh8zAPhJpvm3ih6qLYZADwePUnoAQCq6Uqd5eBrQhdN5GsJX2Wb6lZWhM9pqi956zYpAD1mdfhGHd2wA4F8xfVM1hzvKGNm3rCrad1X0dPbsXN5STyPQQ/YKMLQ7cqRDsgZ5+o6N/AsA8K9UhRnGSMGT8/bn8DE1o1lRjIHsFWBokHfvvSJ9+lB8AQBIm+aTODSJ4ozmQ6CHQy7AiPzB2stuuy20VM9KHgAgtjDjQH1WtTsDso6tWzQNBRgAgEMozNDT+lEjpT6QUJwRWSDQ1CCKNLKGQA9NQwEGAOAQCjP0NDjwDAlE8n6Mkbr6Otm9d7fUVU6nSCPLGIGWASPQUtM/xPxx46XAhCdgRCbZRgowGGsDAGjCyExd3RswWmTVbJF84+/RmbsYgYacCS+nN3x3mP2DnHCuSO3LVSJbtkTfpRHkAQCamgKkCwcDtyYEeZEJGgsX0mvvELCilwEreqkrbbWNiglPwbAregynBgA0ZdFAe+fFFmfk50vtsqVSNGjI/pm4sUUbmsfnk9eaXazowZGjzuhsDgA4yOKMQGWlFJd0Tzo0WpnLa81BoxgDyRIrnqi0BQA0Y3GGPa+vNTGreUl0G/f993kcmog+eki/RZuXJ3unP2pz8ooDgfR/gPQ/AgAczMpebJFFin57vNYcOlb0kH6LNhi01bVnVfSyOXkpMeoMANAMW7q62NAQk8PHWM2DQ6CHRlVCpfxFeeghKm0BAM2ypVuzaYP0v1rkjsEitQ8+IFJWxj19EKi6zcB3VbcpehtFK6EGnx0fBPqwtxEAoGV7tra6dvz+hQadpz5zpucrb3dRdYtm07WrzcmLjqWJVEINHBxqoRJTIcUSOgCg2VRXS+F1N8TvJmkK0ZgxdHloIooxEKIVtps22cKLM0eLDNwiUjFlqQ3yLH0HpcvmWvGkg6dZyQMANJd03R70Mn0d4jWo0Qj0EFdpq9W1q00oJ8/8/ez4BpWJFVIAADSHdBW4epkuNqDRKMbwO5ohAwAcWoGrlbcROpXJLj6w4NAkBHp+RzNkAIATjR5tK28vvUTsR837/+f5QozmQKDnd6Wlce+YktAMGQCQI6brMbLyWJHPD0szuQkHRKDnd4mVthr06fK4oroWAJBDBU/Mlc0Pi1TNFSnu0VtMt24iQ4eKlJTY/HIcGH30MvBLH73de3dLr9vaSo/tIounbJQ2hW2orgUAOK63axyP9nPdleXYg6pbWF2+FDnlE5HAJ9tEtKWKx/5wAAAezSHn9Sojtm4hhVePlTWzRB76m0jRmWeJ/PjH3CsAAGe0WEmHHPJGIdDzu7VrpeDJeRLOygudzp1rLwcAINctViJTmTSHvEFi8skrK0PHUKCREYGe3y1fHg3y4qxY0fK3BQCAWNpORfPwqqpk79137r/cGKmrr7PzcDWPjwKN9CjG8Hsxxtq1Yk4/PTnYW7NGpG/f3NwmAAAOUJih3SICRiQ8hd0zBRq7shx7sKLnV5Gl7i5dpH7USDHhi+1peTlBHgDA0YUZBYlBXmyBBqII9Pw62za81K2n9cF9Eows6Wnew6BBOb6BAABkLszQPD07Fi0WBRpJCPT8Pts2GJSieQskP7ykZy8fO5au4wAAxxZm6Glgxgxp6Hd6/I5Uv36u3rZtDgR6fpNi+TspP4+lbwCAgwsz7Om3viX5q1bHd4149VW6RiQg0PObFLNtI++Golj6BgA4ka7WDRkSOqVrRKMQ6PmtAGPTJluiXh++SIO+gBZfxCyHR3sTAQDgVIMGJS9UqIEDW/62OBgj0PxUgBHOzSsMBOL/OLT44he/YL4tAMA9+va1XSMiTf/1dc0uXNAaLA599PzQR8+ng6EBAN62e+9uGTK+rQzcKlIxeZkU66x2l9tFHz0022BoAABc5pOvibzVWcR06Rx/BaPRLHL0fFqAEYfiCwCACxU8MVc2PyxSNVekuPQEOxJNV/kYjbYfgZ5Xxb6T6dpV9k5/dH8BhjaYjDSZpPgCAOBG1dVSeN0NcX1g88eNt1u5BePG79/JCvq7PyzFGB4vvNCVPA3y6hrq5LBotmpA5N57Rfr0EenRg9w8AIBnxqJpvl4k+EtKUfJhLjrFGF4rxvDR4GcAgI/pCp2O84x5vTP5+VK7bKkUDT47PgjMd89rHsUYyIzBzwAAv45Fq6y0lbf1I0fEtxFraBB54QXxI1b0fLCiZwsxjNEH25XvbgAAyLiyp9uykVSkdC3F8vJENm92/OseK3rILFJ4Edi/jK2DnwMzZzL9AgDg7bFomVqKBYO+bCVGMYYH1V9VLt/YOF56bBdZPGW9tOneM3RFWRnTLwAA3lZaGlq9S7Wi16OH+A3tVTzs67tF8lau2l9SnviuBwAAj+buxfaPNdptQvP5fPj6R6Dn0QaSWx4SWfi0SNGV5SLdutmWKwAA+MLo0VKzaYOM/b7I1LNEape/FNrVivSX9RGKMbxYjNGtW3zhhaL4AgDgIzodo2DceNtTz67ohYKe0Bauru6NHi1ORDEGMtMk1MQgTzHPFgDg16kZJqbzhM8mZbB168Uk1Mh4s1jMswUA+EW6ylsfLn4Q6HmJvjvZtMmON4ssUyv7eWWlL5NQAQA+rrxNx0eLHwR6Xppvq6Nghg4Vc9ttUnf+DyT6XibVCh8AAD6ZmmHy8qRB9veX9dPiB8UYXijGSDUNQx/c2GMoxgAA+HRqxp5uR8tZFb1k+HsiEy9+SIovusSxgR7FGGhULkLAx/kIAADE9o/NX/J3WT1L5I6XRYpvvMlXbcfYuvWC0tK4xpDK+DgfAQCAxArcvNi7RCtwx4zxReUtgZ6b6S+oNn8UCc23DV+sQV+gvJzZtgAAbPL37FsCPS8UX5SUSHD5sviai0GDRD76KBQI6qlDG0MCAJCTCtw8f8y+JdBzIy2+GDMm+g5FT4vmLdjfGDLSDFIx2xYA4Gdd/T37lkDPjSi+AADgoGbfPthPpPbhB0Ozb32AQM+NKL4AAKBJ8pf8XR5bLHLzan9V3hLouVHXrqHii8D+5o8UXwAAkEa1fytvCfRcquG7w+T680SmDhapXbZUZM4cii8AAEhlk38rbwtyfQNwEGbPluJrrpHHw8UXZtAQkZkzQ5W1PkgsBQDgoCpvg0HfVd6youfWiltdcg4L+GT5GQCAg9LVv5W3BHpu4+PlZwAAslF5O/UskdrlL4V2wiLDBzy6WMLWrUsrbgM+XH4GAOBQK2+nPy+276wZfLbsGzlCCuY9FXpN1ddRXeHz2IABVvRcWnHbEDsFwyfLzwAAHGrlbX7McIGCJ+ftXziJDBvw2MoegZ4L1V9VLiUTRC69RKRm3m9Ftmzx3DsQAACyalNy6lPsmonV0OC5NCgCPRcKVH8sZ2wNfW7692MlDwCAg5h5axKPyc/3XBoUgZ4bW6v06C0LnhZZ+LTYz/3Q2RsAgGxU3ooGcyo/X+pHjYwbPiCVlZ5bPAkYE9OnA3F27dolhx9+uOzcuVPatWvnjNYqJSWpCzE2b/bcLycAAFlXXR3anu3RQ3Yf1UEu+3FbOW+TyOjbF0rxhZd4Lvag6tZLrVUI9AAAyKxr1+jrZeGPrpRFT4Vy9cxFl4qUl4cmTXkIW7cubK2ShNYqAAA0zdq1oarb8Fl7OneuvdxLCPRcZt+NN0hD7AW0VgEAoOmWL0+uulUrVnjq3mTr1i1mz7ajzwqDwWiVkI5vCdx3H61VAABoqkGD7OtpUrA3cKCn7ktW9Nw03zacnxddZtY6mttu81xzRwAAml3fvrbqNrp4ov9ojl7fvp668wn03FyE4dHmjgAAtIS9syrlByNEft1XpHbG46FAz2OLJ2zdunm+rUebOwIA0BIKnpgrz84Pz75de23oQo/NvGVFz0XzbaNNHSOXe7S5IwAALT77VsSTM29Z0XPRfNtvbBwvPbaLPH/NMineFwyt5BHkAQDQPGlRXd2/kEKg5yJdvhQ55ZPwmSFDcnxrAADwwOzboLfToti6dYnCq8fKmlkiD/1NpOjMs0R+/ONc3yQAADwz+9aIN2feEui5gU+6dwMA0KJGjxb56COp+dtiW307oUykdtnS0OWao1dV5fpcPQI9N/BJ924AAFpc166S98GHtvr24RdEigafLft+dKWYkhKRoUNF9HT2bNc+MAR6LureLR7v3g0AQM6rb4PB0C5aJHfP5VW4BHpOFlk27tLFF927AQBwQvVtwEPDCQj0nDzbNrxsrKf1wX0SjPzmaZXQoEE5voEAAHio+jaG8VAVbrMEeh9//LFceeWVcuSRR0pxcbGcfPLJ8tprr0WvN8bIlClTpEuXLvb6YcOGyaZNm+K+xvbt22XkyJHSrl07ad++vYwePVq++uqruGPWrVsngwYNkqKiIjn22GPlvvvuS7otCxculN69e9tj9HYsXrxYXDfbNhiUonkL4paV3byMDACAU6tvJT9fGr57jjREhhRoEOjiKtysB3r//ve/ZeDAgdKqVSt5/vnnZf369fK///u/0qFDh+gxGpA98sgj8vjjj8vq1avlsMMOk7KyMqmtrY0eo0Heu+++K0uWLJFFixbJyy+/LGPGjIlev2vXLjn33HOlpKREXn/9dbn//vvljjvukBn6YIW9+uqrMmLECBskvvHGG3LBBRfYj3feeUcczePLyAAAOLH6Vv7rv8Rojt6SFyUvmi+VMkvePUyWTZw40Zx55plprw8Gg6Zz587m/vvvj162Y8cO07p1a/PUU0/Z8+vXr9d71axduzZ6zPPPP28CgYD5+OOP7fnp06ebDh06mLq6urjv3atXr+j5yy67zAwfPjzu+/fr18+MHTu2UT/Lzp077e3Q0xa1dasJ5uXpr1b0Ixjzuf3Iz7fHAQCA5nntNTl4zc127JH1Fb1nn31W+vTpI5deeqkcddRRcsopp8jMmTOj13/44Yeybds2u10bcfjhh0u/fv1k5cqV9rye6natfp0IPT4vL8+uAEaOGTx4sBQWFkaP0VXBjRs32lXFyDGx3ydyTOT7JKqrq7MrhbEfjphtm58vAS2+iFlWdvMyMgAArhyJ5kJZD/Q++OADeeyxx6S0tFReeOEFGTdunPz0pz+VudrgV8QGeapTp05x/0/PR67TUw0SYxUUFMgRRxwRd0yqrxH7PdIdE7k+UUVFhQ06Ix+a95fL2bbnXyHy6z4itQvni8yZE1pW1ipcPdVlZgAAkB2lpaF8vFQoxtgvGAzKqaeeKr/85S/tap7m1V1zzTU2H8/pJk2aJDt37ox+bN26NacjzxY9JXL9ayJFF10aGnmmK3g645aVPAAAmnc3TcQTu2hZX9HTStpvfvObcZedcMIJsmXLFvt5586d7emnn34ad4yej1ynp5999lnc9fX19bYSN/aYVF8j9nukOyZyfaLWrVvbKt/Yj5xg5BkAADnZTTtugsiQcpHaV5Z5Yhct64GeVtxqnlys9957z1bHquOPP94GWi+++GL0es2F09y7AQMG2PN6umPHDltNG7F06VK7Wqi5fJFjtBJ337590WO0QrdXr17RCl89Jvb7RI6JfB/HYuQZAAA5c9RuCQV42jvPpSt5USbL1qxZYwoKCszdd99tNm3aZObNm2fatGljfve730WPueeee0z79u3NM888Y9atW2fOP/98c/zxx5uamproMd/73vfMKaecYlavXm1eeeUVU1paakaMGBFXqdupUyczatQo884775j58+fb71NZWRk9ZsWKFfa2PPDAA2bDhg1m6tSpplWrVubtt992dtXtmjXJVbb6sWZNy94OAAB8pPbxaaYh9nU3EDBm1qwWvQ3Zjj2yHuipv/zlL+akk06yLVN69+5tZsyYkdRiZfLkyTZQ02POOeccs3HjxrhjvvjiCxvYtW3b1rRr185cddVV5ssvv4w75q233rKtXPRrHHPMMTaATLRgwQLTs2dPU1hYaE488UTz3HPPNfrnyFmgZ4zZO2pkNNizp+XlLX4bAAAwfm+vkpfXou3Msh17BPSfXK8qOpVuKWv1rRZmtHS+3u69u2XI+LYycKtIxeRlUjxwcIt+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AI8i0AMAAPAoAj0AAACPItADAADwKAI9AAAAjyLQa0bTpk2T4447ToqKiqRfv36yZs2a5vx2nlZRUSF9+/a14+iOOuooueCCC2Tjxo1xx9TW1sr48ePlyCOPlLZt28rFF18sn376adwxW7ZskeHDh0ubNm3s17n11lulvr4+7piXXnpJTj31VFse36NHD5kzZ07S7eGxTXbPPffYUYETJkzgMcmxjz/+WK688kr7t1BcXCwnn3yyvPbaa3EjlqZMmSJdunSx1w8bNkw2bdoU9zW2b98uI0eOtN3927dvL6NHj5avvvoq7ph169bJoEGD7HOcjn267777km7LwoULpXfv3vYYvR2LFy8WP2poaJDJkyfL8ccfb+/zb3zjG3LXXXfFDa7ncWl+L7/8svzHf/yHHS+mz1d//vOf46530mPQmNvSKAbNYv78+aawsND85je/Me+++6655pprTPv27c2nn37KPX4QysrKzBNPPGHeeecd8+abb5rvf//7plu3buarr76KHnPttdeaY4891rz44ovmtddeM/379zdnnHFG9Pr6+npz0kknmWHDhpk33njDLF682HTs2NFMmjQpeswHH3xg2rRpY26++Wazfv168+ijj5r8/Hzz17/+lcc2gzVr1pjjjjvOfOtb3zI33ngjj0kObd++3ZSUlJgf//jHZvXq1fZ3+oUXXjDvv/9+9Jh77rnHHH744ebPf/6zeeutt8x//ud/muOPP97U1NREj/ne975nvv3tb5tVq1aZ5cuXmx49epgRI0ZEr9+5c6fp1KmTGTlypP27fOqpp0xxcbGprKyMHrNixQr793PffffZv6f/+Z//Ma1atTJvv/228Zu7777bHHnkkWbRokXmww8/NAsXLjRt27Y1v/rVr6LH8Lg0v8WLF5v//u//Nn/84x81wjZ/+tOf4q530mPQmNvSGAR6zeT0008348ePj55vaGgwRx99tKmoqGiub+krn332mf0jXbZsmT2/Y8cO+0eiT54RGzZssMesXLky+geel5dntm3bFj3mscceM+3atTN1dXX2/M9+9jNz4oknxn2vyy+/3AaaETy28b788ktTWlpqlixZYs4666xooMdjkhsTJ040Z555Ztrrg8Gg6dy5s7n//vujl+lj1bp1a/uCpPSFR/921q5dGz3m+eefN4FAwHz88cf2/PTp002HDh2ifzuR792rV6/o+csuu8wMHz487vv369fPjB071viN3g8/+clP4i676KKLbDCgeFxaniQEek56DBpzWxqLrdtmsHfvXnn99dftMmtEXl6ePb9y5crm+Ja+s3PnTnt6xBFH2FO9v/ft2xd3n+uSeLdu3aL3uZ7q8ninTp2ix5SVlcmuXbvk3XffjR4T+zUix0S+Bo9tMt0u1+3wxPuNxyQ3nn32WenTp49ceumlNj3hlFNOkZkzZ0av//DDD2Xbtm1xj5cOUNf0kti/Fd2S0q8Tocfr89jq1aujxwwePFgKCwvj/lY0peLf//53o/6e/OSMM86QF198Ud577z17/q233pJXXnlFzjvvPHuexyX3PnTQ30ZjbktjEeg1g88//9zmY8QGFErP6wOHQxMMBm0e2MCBA+Wkk06yl+n9qn9U+geY7j7X01SPSeS6TMdoMFhTU8Njm2D+/Pnyj3/8w+ZQJuIxyY0PPvhAHnvsMSktLZUXXnhBxo0bJz/96U9l7ty50cdFZXp+0lMNEmMVFBTYN1bZ+Hvy4/PgbbfdJldccYV9A9qqVSsbgOvzmOZ6KR6X3NvmoL+NxtyWxipo0tGAQ1aQ3nnnHftuGLmzdetWufHGG2XJkiU2mRjOeSOkqw2//OUv7XkNKPTv5fHHH5fy8vJc3zzfWrBggcybN09+//vfy4knnihvvvmmDfS0KIDHBc2JFb1m0LFjR8nPz0+q+NTznTt3bo5v6RvXX3+9LFq0SKqqqqRr167Ry/V+1W3VHTt2pL3P9TTVYxK5LtMxWl2lVU88tvFbs5999pmtUNZ3tPqxbNkyeeSRR+zn+s6Tx6TlaYXeN7/5zbjLTjjhBFtxHvu7nun5SU/1sY2l1elabZiNvyc/Pg9qhX9kVU9TSEaNGiU33XRTdDWcxyX3Ojvob6Mxt6WxCPSagW4hnnbaaTYfI/Zdtp4fMGBAc3xLz9O8WQ3y/vSnP8nSpUtti4JYen/rdkjsfa75EPriFrnP9fTtt9+O+yPV1SgN4iIvjHpM7NeIHBP5Gjy2+51zzjn2/tSViciHriTpVlTkcx6TlqcpDYmthzQvrKSkxH6ufzv6QhH7e66pCZpfFPu3om+aNJiP0L87fR7THKHIMdqqQnNjY/9WevXqJR06dGjU35Of7Nmzx+ZxxdIFAb1PFY9L7h3voL+NxtyWRmtS6Qaa1F5Fq2PmzJljq3TGjBlj26vEVnyi8caNG2fLzF966SXzySefRD/27NkT115FW64sXbrUtlcZMGCA/Uhsr3LuuefaFi3aMuXrX/96yvYqt956q63anTZtWsr2Kjy2qcVW3fKY5K7VTUFBgW3nsWnTJjNv3jz7O/273/0urm2DPh8988wzZt26deb8889P2ULilFNOsS1aXnnlFVtZHdtCQisAtYXEqFGjbAsJ/bvQ75PYQkJvywMPPGD/nqZOnerb9irl5eXmmGOOibZX0fYe2t5JK/0jeFxapkvAG2+8YT80BHrwwQft55s3b3bcY9CY29IYBHrNSHuwaeCh/fS0JYf23MHB0T/IVB/aWy9Cf/mvu+46W9auf1QXXnihDQZjffTRR+a8886zPY30SfaWW24x+/btizumqqrKfOc737GPW/fu3eO+B49t0wI9HpPc+Mtf/mLf1Ogbkt69e5sZM2bEXa+tGyZPnmxfjPSYc845x2zcuDHumC+++MK+eGmvN21BdNVVV9kXyVja20tbuejX0CBGX5gSLViwwPTs2dP+PWnroueee8740a5du+zfhr4mFBUV2ecW7ecW24KDx6X5VVVVpXwt0UDcaY9BY25LYwT0n6atAQIAAMANyNEDAADwKAI9AAAAjyLQAwAA8CgCPQAAAI8i0AMAAPAoAj0AAACPItADAADwKAI9AAAAjyLQAwAA8CgCPQAAAI8i0AMAABBv+v8BVCehcT6MsC4AAAAASUVORK5CYII=", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plot_tiles(red_tiles)\n", "plt.plot(*T(breadcrumbs(red_tiles)), 'bs');\n", "plt.plot(*T(find_2_corners(red_tiles)), 'kD');" ] }, { "cell_type": "markdown", "id": "d8039a9d-1af7-4a74-80c9-18bba48aeb7b", "metadata": {}, "source": [ "Now I'll define `biggest_rectangle` to find the maximal-area all-red-and-green rectangle. I'll do that by considering pairs of corner points, where the first corner can be any red tile, and by default the second corner can also be any red tile, but you can optionally pass in the result of `find_2_corners` to speed things up. We then sort the possible rectangles by area, biggest first, and go through them one at a time. When we find one that does not have `any_intrusions`, we return it; it must be the biggest. \n", "\n", "The function `any_intrusions` checks to see if a red tile is completely inside the rectangle defined by the corners, by checking the x and y coordinates of each red tile against the bounds of the rectangle." ] }, { "cell_type": "code", "execution_count": 66, "id": "922d721e-5330-466b-8a54-8a273522c44d", "metadata": {}, "outputs": [], "source": [ "def biggest_rectangle(red_tiles, second_corners=None, d:int=GAP) -> Rectangle:\n", " \"\"\"Find the biggest rectangle that stays within the interior-and-border of the red tiles.\n", " You can pass in a hint for `second_corners`, or they can default to `red_tiles`.\"\"\"\n", " obstacles = find_obstacles(red_tiles, d)\n", " rectangles = cross_product(second_corners or red_tiles, red_tiles)\n", " for rect in sorted(rectangles, key=tile_area, reverse=True):\n", " if not any_intrusions(obstacles, rect):\n", " return rect\n", " raise ValueError('No rectangle') # Shouldn't get here unless there are no corners\n", "\n", "def any_intrusions(obstacles: list[Point], rect: Rectangle) -> bool:\n", " \"\"\"Does any ostacle point intrude inside the rectangle?\"\"\"\n", " # OK for an obstacle to be on border or just one square in, but not 2 squares in\n", " xlo, xhi = min(Xs(rect)) + 2, max(Xs(rect)) - 2\n", " ylo, yhi = min(Ys(rect)) + 2, max(Ys(rect)) - 2\n", " return any(xlo <= x <= xhi and ylo <= y <= yhi\n", " for (x, y) in obstacles)" ] }, { "cell_type": "markdown", "id": "683f5366-8c80-445f-813f-1b894871a295", "metadata": {}, "source": [ "We're ready to solve the puzzle:" ] }, { "cell_type": "code", "execution_count": 67, "id": "7ff60bbf-9cb6-4102-8b1c-5ef72be03c92", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 9.2: 2.0 msec, correct answer: 1529675217 " ] }, "execution_count": 67, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(9.2, 1529675217, lambda:\n", " tile_area(biggest_rectangle(red_tiles, find_2_corners(red_tiles))))" ] }, { "cell_type": "markdown", "id": "53ef7a00-aef7-4c20-8a2b-d735df8f28dd", "metadata": {}, "source": [ "Let's see what the biggest rectangle looks like (at a bigger scale to see more detail):" ] }, { "cell_type": "code", "execution_count": 68, "id": "8ba7df82-cef0-4c94-8ffa-1822910d21f7", "metadata": {}, "outputs": [ { "data": { "image/png": "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ykcffeTY5vXXX5eJEyfaa4khQ4bInXfemfRZHn30URk5cqTdRj/H6tWru/D/HGHW3Nws8+fPl5NPPtnul6eeeqr86Ec/svtrDPsuguCvf/2rfPWrX5VBgwbZa4MnnnjC8fMg7adePosvBoHwyCOPmIKCAvPLX/7SvPHGG2bGjBnmuOOOMwcOHOjpj4YsNGXKFLN8+XKzdetW8+qrr5qvfOUrZujQoeajjz6Kb/Od73zHDBkyxKxZs8Zs2rTJfPGLXzTnnntu/OdHjhwxZ555prnwwgvNK6+8YlavXm0GDBhgbr311vg2b7/9tunTp4+58cYbzZtvvmnuuece06tXL/PUU0/Ft2HfR0ds2LDBDBs2zHz+8583N9xwA/stAu399983paWl5tvf/rZ56aWX7LHx6aefNm+99VZ8mzvuuMOUlJSYJ554wrz22mvma1/7mjn55JNNQ0NDfJsvf/nL5qyzzjIvvviiWbdunRk+fLi56qqr4j+vq6szJ554opk6dao9vv/61782RUVFZvHixfFt1q9fb4/Dd955pz0u//CHPzTHHHOM2bJlSzf+RhAWt99+uzn++OPNk08+aXbt2mUeffRR069fP/Ozn/0svg37LoJg9erV5gc/+IH53e9+p3ebzOOPP+74eZD2Uy+fxQ8C+oAYO3asqa6ujr9ubm42gwYNMgsXLuzRz4XccPDgQXvwW7t2rX39wQcf2IOPnrhjtm3bZrd54YUX4gfOvLw8s3///vg2999/vykuLjaNjY329fe//31zxhlnOP6uK664wt5QiGHfh18ffvihKSsrM88884yZPHlyPKBnv0VQ3XLLLWbChAlt/rylpcUMHDjQ/OQnP4l/T/fn3r172wtGpReGegzeuHFjfJs///nPJhKJmHfffde+XrRokenfv3/8GBz7u0eMGBF//a1vfctcfPHFjr9/3LhxZubMmRn6v0U20X3lmmuucXzv0ksvtQGNYt9FEIkroA/Sfurls/hFyn0ANDU1yebNm226RUxeXp59/cILL/ToZ0NuqKurs8+f+tSn7LPuj4cPH3bsk5o6NHTo0Pg+qc+aRnTiiSfGt5kyZYrU19fLG2+8Ed8m8T1i28Teg30fHaGlIFrq4d632G8RVH/4wx9k9OjRcvnll9vypHPOOUceeOCB+M937dol+/fvd+zTJSUltvwu8ZirKaD6PjG6vV4vvPTSS/FtJk2aJAUFBY5jrpZU/etf//J0XAYSnXvuubJmzRrZsWOHff3aa6/J888/LxdddBH7LkJjV4COsV4+i18E9AHw3nvv2RqlxMBI6Wv9Bwe6UktLi61BLi8vlzPPPNN+T/c7PVjpga2tfVKfU+2zsZ+l20aD/oaGBvZ9+PbII4/Iyy+/bPtAuLHfIqjefvttuf/++6WsrEyefvppmTVrlnz3u9+VmpoaxzEz3XWAPuvNgET5+fn2RmwmjstcbyCVefPmyZVXXmlv6h9zzDH2ZpReM2idMfsuwmJ/gI6xXj6LX/kd+lMAsmq1c+vWrfaOOxBke/fulRtuuEGeeeYZ22gGCNONU131+fGPf2xfa1Ckx91f/OIXUllZ2dMfD2jTqlWrZOXKlfKrX/1KzjjjDHn11VdtQK+Nx9h3gWBghT4ABgwYIL169UrqIK6vBw4c2GOfC9nv+uuvlyeffFJqa2tl8ODB8e/rfqfp8B988EGb+6Q+p9pnYz9Lt412D9Wunuz78ENT6g8ePGinJuhdc32sXbtWfv7zn9uv9e42+y2CSDsZf/azn3V87/TTT7eTQhKPmemuA/RZ9/9EOlVEuzJn4rjM9QZS0ek1sVV6LbObNm2afO9734tnSbHvIgwGBugY6+Wz+EVAHwCa2jxq1Chbo5R4N19fjx8/vkc/G7KT9gvRYP7xxx+XZ5991o6jSaT7o6bWJe6TWh+kF5+xfVKft2zZ4jj46cqpBuuxC1fdJvE9YtvE3oN9H35ccMEFdp/TFaLYQ1c9NfUz9jX7LYJIS5rco0G1Jrm0tNR+rcdgvZBLPF5qaZLWbSYec/Umq97YitHjt14vaO1lbBsd3aQ9UBKPuSNGjJD+/ft7Oi4DiT7++GNbQ5xIF6F0v2PfRVicHKBjrJfP4luHWukh43R0l3Y3XLFihe2yWFVVZcfWJXYQBzJl1qxZdlzGc889Z/7+97/HHx9//LFjbJ2Osnv22Wft2Lrx48fbh3ts3Ze+9CU7+k5H0X36059OObbu5ptvtl3y77vvvpRj69j30VGJXe7ZbxHkMYv5+fl2BNjOnTvNypUr7bHx4Ycfdowx0vP+73//e/P666+br3/96ylHKp1zzjl29N3zzz9vpz0kjlTSTsk6UmnatGl2pJIeX/XvcY9U0s/y05/+1B6Xb7vtNsbWoU2VlZXmpJNOio+t05FgOqJWp9iw7yJoE3BeeeUV+9AQ96677rJfv/POO4E7xnr5LH4Q0AeIzujWAErn0esoL52BCHQFPdCleuhs+hg9qMyePduO59CD1SWXXGKD/kS7d+82F110kZ3BqSf4m266yRw+fNixTW1trTn77LPtfn3KKac4/g72fWQ6oGe/RVD98Y9/tDdB9QbmyJEjzZIlSxw/11FG8+fPtxeLus0FF1xgtm/f7tjmn//8p7241DngOiJ0+vTp9iI2kc401hF5+h4aiOmFo9uqVavMaaedZo/LOlr0T3/6Uxf9XyPs6uvr7TFWr08LCwvteVxnfSeO7WLfRRDU1tamvLbVm1JB20+9fBY/Ivqfjq3tAwAAAACAnkINPQAAAAAAIURADwAAAABACBHQAwAAAAAQQgT0AAAAAACEEAE9AAAAAAAhREAPAAAAAEAIEdADAAAAABBCBPQAAAAAAIQQAT0AAAAAACFEQA8AAAAAQAgR0AMAAAAAIOHz/+ADRkNFbdVvAAAAAElFTkSuQmCC", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def plot_rect(rect: Rectangle, fmt='b:') -> None:\n", " \"\"\"Plot a rectangle.\"\"\"\n", " ((x1, y1), (x2, y2)) = rect\n", " plt.plot([x1, x1, x2, x2, x1], [y1, y2, y2, y1, y1], fmt)\n", " \n", "plot_tiles(red_tiles, figsize=(12, 12))\n", "plot_rect(biggest_rectangle(red_tiles, find_2_corners(red_tiles)))" ] }, { "cell_type": "markdown", "id": "d7016370-a8b6-4d7a-9787-70a50b3207b9", "metadata": {}, "source": [ "We see that if the upper-left corner of the blue rectangle were any higher, then there would be red (and white) tiles in the upper-right corner of the rectangle. If the upper-left corner of the blue rectangle were any further southwest that would be ok, but would result in a slightly smaller area. You'll just have to take it for granted that all the possible rectangles formed below the equater lines are also a little bit smaller in area.\n", "\n", "What if we didn't rely on the second corner being an equatorial point? Would the answer be the same? Would it be a lot slower? Let's check:" ] }, { "cell_type": "code", "execution_count": 69, "id": "d3b44691-da52-4794-ab77-bc4326aa6ca2", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 272 ms, sys: 3.35 ms, total: 275 ms\n", "Wall time: 275 ms\n" ] }, { "data": { "text/plain": [ "True" ] }, "execution_count": 69, "metadata": {}, "output_type": "execute_result" } ], "source": [ "R = red_tiles\n", "\n", "%time tile_area(biggest_rectangle(R, R)) == tile_area(biggest_rectangle(R, find_2_corners(R)))" ] }, { "cell_type": "markdown", "id": "b7161525-d572-455f-b6d0-cfe9e86405c8", "metadata": {}, "source": [ "Yes, it gets the correct answer, and yes, it is slower.\n", "\n", "In my puzzle input there were no adjacent points, and thus no `adjacent_180_tiles`. (And if Eric Wastl is being fair (which he always is), then everybody's puzzle would be the same.) But here is a test case with five pairs of adjacent points, just to show it works. We can see that `adjacent_180_tiles` correctly found the ten adjacent points (the magenta \"o\"s) and eliminated them as obstacles. It also correctly did not eliminate obstacles for the adjacent points that do not form 180° U-turns (one on the left and one at the top). Finally, `biggest_rectangle` returns the blue rectangle, which appears to be the right answer." ] }, { "cell_type": "code", "execution_count": 70, "id": "437bd73a-6c8f-4196-8095-3299e5f8ef9d", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "points = [(-16, 3), (-16, 24), (-17, 24), (-17, 39), (-17, 32), (-5, 32), (-5, 33), (-17, 33), \n", " (-17, 39), (6, 39), (6, 40), (41, 40), (41, 0), \n", " (40, 0), (40, 27), (18, 27), (18, 26), (34, 26), (34, 3), (16, 3), (16, 15), \n", " (30, 15), (30, 16), (10, 16), (10, -3), (2, -3), (2, 27), (1, 27), (1, 3)]\n", "\n", "plot_tiles(points) # Green dots and red lines\n", "plt.plot(*T(adjacent_180_tiles(points)), 'mo') # The eliminated obstacles are magenta dots\n", "plot_rect(biggest_rectangle(points)) # Rectangle is blue dotted line" ] }, { "cell_type": "markdown", "id": "b4e35203-687a-434e-88f5-0afea9f31c57", "metadata": {}, "source": [ "**Three final remarks**:\n", "1) This was the first puzzle of the year that was **difficult**; we had to work to find an efficient solution.\n", "2) My solution is **unsatisfying** in that it works for *my* input, and I strongly suspect that it would work for *your* input, because Eric Wastl probably created them all to be similar. But it does not work on every possible input. With a highly non-convex polygon as input (imagine a crescent moon shape), it can find a maximal-area rectangle that is completely outside the polygon.\n", "3) In retrospect, I could have done the standard edge-edge intersection algorithm for determining if the rectangle intersects the polygon formed by the red tiles. I was scared away from that because the geometry is tricky for general polygon intersection, when the edges can have any slope. But the geometry is actually easy when all lines are axis-aligned, and that approach (while slower) would handle the non-convex cases." ] }, { "cell_type": "markdown", "id": "555e1ce1-9cf2-4f74-b5f4-9f94fb9ddaa0", "metadata": {}, "source": [ "# Day 10: Factory (Integer linear programming)\n", "\n", "On [**Day 10**](https://adventofcode.com/2025/day/10) we find the machines in the factory are offline. Each machine has some lights, some buttons that can be pressed, and a joltage requirement for each light. For example, the machine described by:\n", "\n", " [.##.] (3) (1,3) (2) (2,3) (0,2) (0,1) {3,5,4,7}\n", "\n", "has four lights, and the goal configuration `.##.` means that the second and third light should be on and the others off. There are six buttons (each delimited by parentheses): the first button toggles light number 3, the second toggles lights 1 and 3, and so on. (The machine uses 0-based indexing, so light number 3 is the fourth light.) Finally, the joltage requirements for the four lights are `3,5,4,7`. We can parse the input lines into machine descriptions like this:" ] }, { "cell_type": "code", "execution_count": 71, "id": "84cd63a7-4d50-4f14-9807-3cb439f80c88", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "Puzzle input ➜ 165 strs of size 30 to 209:\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "[.##....#..] (0,1,3,4,5,6,7,8,9) (0,1,2,4,5,6,7,8,9) (0,1,2,4,6,7,9) (1,2,3,5,7,8,9) (1,3,8) (7) ...\n", "[..#.....#] (0,2,4,6,7) (0,4,6,7) (0,1,2,5,7,8) (0,3,5,8) (0,1,2,3,4,7,8) (3,5,7) (3,6) (0,1,2,3 ...\n", "[.#....###] (4,7) (2,6,7,8) (0,1,2,4,6,7,8) (0,5) (5,8) (1,4,5) (0,2,3,5,6) (2,4,5,8) (2,3) (0,6 ...\n", "[.###.##.##] (1,3,4,6,7,8) (0,1,2,4,8) (1,2,5,6,8,9) (3) (0,2,4,8) (1,4,5,6) (2,4,6,8,9) (0,1,3, ...\n", "[#.##..###.] (2,3,5,7,8) (4,5) (0,1,2,4,5,7) (2,6,7) (2,3,4,5,6,7,8,9) (0,3,5,6,8,9) (0,1,2,3,5, ...\n", "[#....] (0,2,3) (0,2,3,4) (2,3) (0,1,2) (0,3,4) (3) (1,2) {75,18,60,71,39}\n", "[##.##..] (1,2,3,4,6) (2,4) (0,1,3,5) (0,2,3,5) (0,1,3,4) {14,25,30,34,25,10,20}\n", "[...#.#] (0) (1,4) (3,5) (2,4) (0,1,2,3) (1,2) (0,1,2,4) {50,56,62,34,48,17}\n", "...\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "Parsed representation ➜ 165 Machines of size 3:\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "Machine(lights='.##....#..', buttons=((0, 1, 3, 4, 5, 6, 7, 8, 9), (0, 1, 2, 4, 5, 6, 7, 8, 9), ...\n", "Machine(lights='..#.....#', buttons=((0, 2, 4, 6, 7), (0, 4, 6, 7), (0, 1, 2, 5, 7, 8), (0, 3, 5 ...\n", "Machine(lights='.#....###', buttons=((4, 7), (2, 6, 7, 8), (0, 1, 2, 4, 6, 7, 8), (0, 5), (5, 8) ...\n", "Machine(lights='.###.##.##', buttons=((1, 3, 4, 6, 7, 8), (0, 1, 2, 4, 8), (1, 2, 5, 6, 8, 9), ( ...\n", "Machine(lights='#.##..###.', buttons=((2, 3, 5, 7, 8), (4, 5), (0, 1, 2, 4, 5, 7), (2, 6, 7), (2 ...\n", "Machine(lights='#....', buttons=((0, 2, 3), (0, 2, 3, 4), (2, 3), (0, 1, 2), (0, 3, 4), (3,), (1 ...\n", "Machine(lights='##.##..', buttons=((1, 2, 3, 4, 6), (2, 4), (0, 1, 3, 5), (0, 2, 3, 5), (0, 1, 3 ...\n", "Machine(lights='...#.#', buttons=((0,), (1, 4), (3, 5), (2, 4), (0, 1, 2, 3), (1, 2), (0, 1, 2, ...\n", "...\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n" ] } ], "source": [ "Machine = namedtuple('Machine', 'lights, buttons, joltage')\n", "\n", "def parse_machine(line: str) -> tuple:\n", " \"\"\"Parse a line into lights, buttons, joltage.\"\"\"\n", " lights, *buttons, joltage = line.split()\n", " return Machine(lights[1:-1], mapt(ints, buttons), ints(joltage) )\n", " \n", "machines = parse(10, parse_machine)" ] }, { "cell_type": "markdown", "id": "d5d91403-5dc4-4fb5-be36-58a1e45e9eab", "metadata": {}, "source": [ "\n", "\n", "### Part 10.1: What is the fewest button presses to configure the lights on all the machines?\n", "\n", "The lights are initially all off, and we want to get them to the goal configuration with the minimum number of button presses. It makes no sense to press any button twice; that just toggles lights on and off and we end up where we started. So we want to find the smallest subset of buttons that when pressed gives the goal light configuration. The function `powerset` (from the [itertools recipes](https://docs.python.org/3/library/itertools.html#itertools-recipes)) yields subsets in smallest first order, so just look for the first subset of the buttons that toggles every light the proper odd/even number of times. " ] }, { "cell_type": "code", "execution_count": 72, "id": "179e62b1-e4cb-43e4-8dc7-b87a28d21e8d", "metadata": {}, "outputs": [], "source": [ "def minimal_button_presses(machine) -> int:\n", " \"\"\"How many button presses to configure lights on this machine?\n", " First try all ways of pressing 1 button, then all ways of pressing 2 buttons, ...\n", " Return as soon as one way matches the goal configuration of lights.\"\"\"\n", " light_goals = [int(ch == '#') for ch in machine.lights] # e.g., goal = [0, 1, 1, 0] for '.##.'\n", " for pressed in powerset(machine.buttons):\n", " # Check that total presses for each light mod 2 is equal to goal for that light\n", " toggles = Counter(flatten(pressed))\n", " if all(toggles[light] % 2 == goal for (light, goal) in enumerate(light_goals)):\n", " return len(pressed)\n", " return inf # Couldn't solve; return infinity" ] }, { "cell_type": "code", "execution_count": 73, "id": "d1368c2f-d792-4353-82e7-b0161ece784f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 10.1: 21.5 msec, correct answer: 441 " ] }, "execution_count": 73, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(10.1, 441, lambda:\n", " sum(map(minimal_button_presses, machines)))" ] }, { "cell_type": "markdown", "id": "ecd76248-e224-44fb-91cf-e843a0f4f8f3", "metadata": {}, "source": [ "### Part 10.2: What is the fewest button presses to configure the joltage levels on all the machines?\n", "\n", "In Part 2 we move a lever, and now the function of the buttons changes: they control the joltage levels of the lights, not the lights themselves. The joltage levels all start at zero. Pressing the button `(2, 3)` increments the joltage level of lights numbered 2 and 3 by one unit each. Our task is to get the joltage levels all exactly to the target levels in the minimum number of presses.\n", "\n", "My first thought when reading the puzzle description was \"*This is an [**integer linear programming**](https://en.wikipedia.org/wiki/Integer_programming) problem.*\" My thought was confirmed by the instructions that said \"*You have to push each button an integer number of times; there's no such thing as 0.5 presses (nor can you push a button a negative number of times),*\" because having fractional or negative results is exactly what you might get from linear programming (you have to take extra steps to constrain the results to be non-negative and to be integers).\n", "\n", "Still, I was reluctant to use an integer linear programming package; that would mean that someone else is writing most of the code. This could also be seen as a search problem; I started programming an A* search solution, but it was way too slow. Why is it slow? Let's investigate. First, the number of buttons per machine is not too bad:" ] }, { "cell_type": "code", "execution_count": 74, "id": "1d2683fa-5126-4d2a-9dad-6a0e155f3449", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "7.181818181818182" ] }, "execution_count": 74, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mean(len(m.buttons) for m in machines)" ] }, { "cell_type": "markdown", "id": "d7776686-d2a6-4645-b46b-86a7187ff6b5", "metadata": {}, "source": [ "The showstopper is the expected number of button presses per machine (total joltage requirements divided by average joltage added by each button press):" ] }, { "cell_type": "code", "execution_count": 75, "id": "a714c2c2-d433-41d0-8d1e-01832b35a1a9", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "114.81498043610085" ] }, "execution_count": 75, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mean(sum(m.joltage) / mean(map(len, m.buttons)) for m in machines)" ] }, { "cell_type": "markdown", "id": "fcbf4426-ce35-4270-aa51-7fcacdf86e24", "metadata": {}, "source": [ "That means a completely naive search would have to consider about 7115 possible button press sequences. Of course we can take advantage of the structure of the problem to make some optimizations to the search:\n", "1) Many joltage states will be repeated; we can cache them.\n", "2) Button presses are commutative; we can impose a canonical ordering.\n", "3) We can keep track of the best solution found so far and eliminate states that can't reach the goal in that number of presses.\n", "4) Some actions will be forced: if there is only one button that increments a given light, we *must* press it until the light hits its goal.\n", "5) If there are only two buttons that increment a given light, then the total presses of those two buttons must equal the joltage requirement for that light.\n", "6) And if there are three buttons that increment a given light, maybe we can somehow eliminate one button to get to two, and then to one.\n", "7) Come to think of it, that process of button elimination already has a name: [Gaussian elimination](https://en.wikipedia.org/wiki/Gaussian_elimination). Reluctantly, I will give in to the power of linear programming.\n", "\n", "A linear programming solver finds a solution **x** to the equation **A** **x** = **b** that minimizes the dot product **c** · **x**, where **A** is a two-dimensional matrix and the other variables are one-dimensional vectors.\n", "\n", "For our problem we have:\n", "- **b** is the vector of joltage requirements for each light,\n", "- **c** is the cost vector: it says how much it costs to press each button, which is one press each so **c** is a vector of all ones,\n", "- **A** is a matrix where **A***i,j* says how much button *j* increments joltage *i* (either 0 or 1),\n", "- **x** will be the solution returned by the solver: a vector of number-of-pushes for each button.\n", "\n", "\n", "\n", "\n", "\n", "I started researching integer programming packages that run in Python. [Z3](https://github.com/Z3Prover/z3) seems to be the most popular, but it is a separate step to install it. I know that I (and many other people) already have **scipy** installed, and it turns out the [**scipy.optimize**](https://docs.scipy.org/doc/scipy/tutorial/optimize.html) package contains the function [**milp**](https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.milp.html#scipy.optimize.milp), for \"mixed integer linear programming.\" The \"mixed\" part means that we can declare that some of the variables must be integers, while others can be continuous. (For our problem they will all be integers.)\n", "\n", "The arguments to **milp** are:\n", "- **c**: the cost vector (a 1 for every button in our problem),\n", "- **integrality**: indicates which variables must be integers (a 1 (True) for every button in our problem),\n", "- **constraints**: a linear constraint. I want to say **A** **x** = **b**, but in this package I have to say **lb** ≤ **A** **x** ≤ **ub**, where **lb** and **ub** are the lower and upper bounds on **b**. In our problem both **lb** and **ub** are the joltage requirements.\n", "\n", "If we give it the right inputs, **milp** will magically return a minimal-cost result for **x**. Here's how we get the data out of a `machine` and feed it to **milp**:" ] }, { "cell_type": "code", "execution_count": 76, "id": "713a1503-ae14-445f-91ea-714fcd618ad0", "metadata": {}, "outputs": [], "source": [ "from scipy.optimize import milp, LinearConstraint\n", "import numpy as np\n", "\n", "def minimal_joltage_presses(machine) -> int:\n", " \"\"\"The minimal number of button presses to set the joltages on this machine.\"\"\"\n", " A = [[int(i in button) for button in machine.buttons]\n", " for i in range(len(machine.lights))]\n", " ones = [1] * len(machine.buttons)\n", " b = machine.joltage\n", " x = milp(c=ones, \n", " integrality=ones,\n", " constraints=LinearConstraint(A, lb=b, ub=b)).x\n", " return round(sum(x))" ] }, { "cell_type": "markdown", "id": "6ceb9e41-4e5e-442a-b162-db3384b07728", "metadata": {}, "source": [ "I made a few mistakes in not understanding the parameters of **milp**, but eventually I got it right and I was absolutely ***amazed*** at the speed:" ] }, { "cell_type": "code", "execution_count": 77, "id": "46d0d274-bd4c-44af-83e9-35c791a8e96b", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 10.2: 44.3 msec, correct answer: 18559 " ] }, "execution_count": 77, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(10.2, 18559, lambda:\n", " sum(map(minimal_joltage_presses, machines)))" ] }, { "cell_type": "markdown", "id": "6be27520-1a83-42c9-841c-deb3f6422b4e", "metadata": {}, "source": [ "**This felt like cheating!** I only wrote a few lines of code, and **milp** did the rest. My main contribution was just recognizing that this was an integer programming problem.\n", "\n", "At least I can do a bit of analysis. One thing I was interested in: a system of linear equations can be determined, underdetermined, or overdetermined:\n", "- **Determined**: Same number of (independent) equations as variables (same number of buttons as lights); one unique solution.\n", "- **Underdetermined**: Fewer equations than variables (fewer buttons than lights); usually multiple solutions; we want the minimal one.\n", "- **Overdetermined**: More equations than variables (more buttons than lights); no exact solutions unless you are lucky.\n", "\n", "I'm confident that Eric Wastl made sure that every player was lucky: every system has a unique solution, and it consists of exact integers.\n", "\n", "How under- or over-determined are the equations for our machines?" ] }, { "cell_type": "code", "execution_count": 78, "id": "b9f82fef-612b-48a5-9de1-6ff0b137f7fb", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Counter({-1: 68, 1: 65, 0: 32})" ] }, "execution_count": 78, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Counter(sign(len(m.lights) - len(m.buttons)) for m in machines)" ] }, { "cell_type": "markdown", "id": "a094063d-cd1d-446a-88c4-748d87506d92", "metadata": {}, "source": [ "This says that 32 machines are determined, 68 are underdetermined and 65 are overdetermined. By how much?" ] }, { "cell_type": "code", "execution_count": 79, "id": "e536441d-64d4-410d-bb40-2343f6e01d88", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Counter({1: 34, -1: 32, 0: 32, -2: 31, 2: 31, -3: 5})" ] }, "execution_count": 79, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Counter(len(m.lights) - len(m.buttons) for m in machines)" ] }, { "cell_type": "markdown", "id": "541e9ab9-fdcd-4a06-be5a-3f6bac052652", "metadata": {}, "source": [ "Most by only 1 or two variables, but `(-3, 5)` means that 5 of the machines are underdetermined by 3 variables. Most of the time taken by **milp** must have been in searching for a minimal solution to these underdetermined cases." ] }, { "cell_type": "markdown", "id": "6ff8655e-d1cc-4524-b207-c1e425b2a408", "metadata": {}, "source": [ "Here are some tests on a smaller machine that I used when I had a **bug** in understanding how I should call **milp**:" ] }, { "cell_type": "code", "execution_count": 80, "id": "b72544c8-6069-4310-a6dc-b4acd77981b4", "metadata": {}, "outputs": [], "source": [ "machine = parse_machine('[...#.] (0,2,3,4) (2,3) (0,4) (0,1,2) (1,2,3,4) {7,5,12,7,2}')\n", "assert 3 == minimal_button_presses(machine)\n", "assert 12 == minimal_joltage_presses(machine)" ] }, { "cell_type": "markdown", "id": "2e4af311-07cb-4777-ad81-7973ba5a3633", "metadata": {}, "source": [ "# Day 11: Reactor (Counting paths through a graph)\n", "\n", "On [**Day 11**](https://adventofcode.com/2025/day/11) there are a bunch of servers here in the reactor room. Today's input consists of a list of device connectivity specifications; the line \"`wfc: ond mpw vsz`\" means that device `wfc` outputs to 3 devices, `ond`, `mpw`, and `vsz`. I'll capture the data like this:" ] }, { "cell_type": "code", "execution_count": 81, "id": "11e17f6a-acba-44c4-b704-7e4ff7471e7e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "Puzzle input ➜ 643 strs of size 8 to 104:\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "wfc: ond mpw vsz\n", "qxn: mow khk\n", "nzf: rti sqv\n", "ehm: von pgy fxk\n", "nlt: pdl hwf\n", "xqa: qvc cih\n", "ghq: ren\n", "jze: gbj\n", "...\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "Parsed representation ➜ 643 tuples of size 2 to 26:\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "('wfc', 'ond', 'mpw', 'vsz')\n", "('qxn', 'mow', 'khk')\n", "('nzf', 'rti', 'sqv')\n", "('ehm', 'von', 'pgy', 'fxk')\n", "('nlt', 'pdl', 'hwf')\n", "('xqa', 'qvc', 'cih')\n", "('ghq', 'ren')\n", "('jze', 'gbj')\n", "...\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n" ] } ], "source": [ "devices = parse(11, atoms)" ] }, { "cell_type": "markdown", "id": "0ab28991-5875-4d2d-b6c5-eeef20ea8f81", "metadata": {}, "source": [ "### Part 11.1: How many different paths lead from \"you\" to \"out\"?\n", "\n", "We are asked how many distinct output paths there are from the device named `'you'` to the device named `'out'`. It is a simple recursive count, but I'll make two optimizations:\n", "- I'll convert the list of devices into a `dict`, for *O*(1) lookup instead of *O*(*n*).\n", "- It is likely that multiple paths will lead to the same intermediate devices, so I should memoize the counting function. (Note that a `dict` is not hashable and thus can't be in a `@cache`, so I make an inner function, `count`, and decorate that.)" ] }, { "cell_type": "code", "execution_count": 82, "id": "7540a982-988a-4822-af0d-6581f6f848c6", "metadata": {}, "outputs": [], "source": [ "def count_paths(devices, start='you', end='out'):\n", " \"\"\"How many distinct paths are there from start to end?\"\"\"\n", " lookup_table = {device: outputs for (device, *outputs) in devices}\n", " @cache\n", " def count(here, there) -> int:\n", " if here == there:\n", " return 1\n", " else:\n", " return sum(count(mid, there) for mid in lookup_table[here])\n", " return count(start, end)" ] }, { "cell_type": "markdown", "id": "95f75267-37e0-4ab4-949d-73956ea0450a", "metadata": {}, "source": [ "All very straightforward." ] }, { "cell_type": "code", "execution_count": 83, "id": "0c2d68a5-843b-49d6-aff6-23045968207f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 11.1: 0.1 msec, correct answer: 574 " ] }, "execution_count": 83, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(11.1, 574, lambda:\n", " count_paths(devices))" ] }, { "cell_type": "markdown", "id": "fdfb6e5a-99e5-4bcd-b31b-6dc051bca4c9", "metadata": {}, "source": [ "### Part 11.2: How many paths from \"svr\" to \"out\" visit both \"dac\" and \"fft\"?\n", "\n", "Now we are asked for a count of the paths from a different start device, `svr`, to the end device `out`, but the paths are constrained to visit some other devices along the way. That's easy; copy the structure from Part 1, but keep track of what other devices we still need to visit:" ] }, { "cell_type": "code", "execution_count": 84, "id": "0294e044-c7ef-418a-9c02-71615a453002", "metadata": {}, "outputs": [], "source": [ "def count_constrained_paths(devices, start='svr', end='out', others=frozenset({'dac', 'fft'})):\n", " \"\"\"How many distinct paths are there from start to end, visiting all the others?\"\"\"\n", " lookup_table = {device: outputs for (device, *outputs) in devices}\n", " @cache\n", " def count(here, there, others) -> int:\n", " others -= {here}\n", " if here == there:\n", " return (1 if not others else 0)\n", " else:\n", " return sum(count(mid, there, others) for mid in lookup_table[here])\n", " return count(start, end, others)" ] }, { "cell_type": "code", "execution_count": 85, "id": "677a97b3-183b-474e-87ba-7db0d6b763d8", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 11.2: 0.9 msec, correct answer: 306594217920240" ] }, "execution_count": 85, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(11.2, 306594217920240, lambda:\n", " count_constrained_paths(devices))" ] }, { "cell_type": "markdown", "id": "dc115ac2-5357-499d-8917-3fff29f4063b", "metadata": {}, "source": [ "# Day 12: Christmas Tree Farm (Checking for trivial cases first)\n", "\n", "On the [**twelfth day**](https://adventofcode.com/2025/day/12), we're in a cavern full of Christmas trees and the elves would like help arranging presents under the trees. The day's input is in two sections. The first section is a list of 6 present shapes, each annotated with their sequential shape ID. The second section is a list of regions, where each region has a width and length, and a desired number of presents of each shape to fit, in shape-ID order. Each shape is a separate paragraph, but the regions are all in on paragraph, so I can parse them like this:" ] }, { "cell_type": "code", "execution_count": 86, "id": "a1b304e8-339e-4e32-a462-3ba88103c415", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "Puzzle input ➜ 1030 strs of size 0 to 24:\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "0:\n", "###\n", ".##\n", "##.\n", "\n", "1:\n", "##.\n", "##.\n", "###\n", "\n", "2:\n", "#..\n", "##.\n", "###\n", "\n", "3:\n", "###\n", "#.#\n", "#.#\n", "\n", "4:\n", "#.#\n", "###\n", "#.#\n", "\n", "5:\n", "##.\n", ".##\n", "..#\n", "\n", "45x41: 52 43 45 41 47 59\n", "45x41: 29 27 34 34 34 36\n", "41x37: 44 34 38 35 40 44\n", "...\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "Parsed representation ➜ 7 lists of size 3 to 1000:\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n", "['###', '.##', '##.']\n", "['##.', '##.', '###']\n", "['#..', '##.', '###']\n", "['###', '#.#', '#.#']\n", "['#.#', '###', '#.#']\n", "['##.', '.##', '..#']\n", "[Region(W=45, L=41, quantities=[52, 43, 45, 41, 47, 59]), Region(W=45, L=41, quantities=[29, 27, ...\n", "────────────────────────────────────────────────────────────────────────────────────────────────────\n" ] } ], "source": [ "Region = namedtuple('Region', 'W, L, quantities') # width, length, and list of quantities of each present shape\n", "\n", "def parse_presents(text: str):\n", " \"\"\"Parse either a single present (e.g. \"5: ###...\") or list of regions (e.g. \"12x5: 1 0 1 0 2 2\\n...\").\"\"\"\n", " if 'x' in text:\n", " return [Region(W, L, quantities) for (W, L, *quantities) in map(ints, text.splitlines())]\n", " else:\n", " id, *shape = text.splitlines()\n", " return shape\n", " \n", "*shapes, regions = parse(12, parse_presents, paragraphs, show=33)" ] }, { "cell_type": "markdown", "id": "e735589a-634d-4ef9-b3b1-db9019aacf9d", "metadata": {}, "source": [ "### Part 12.1: How many of the regions can fit all of the presents listed?\n", "\n", "Every present shape fits in a 3x3 **box**, so we could just start laying down presents next to each other, box by box. So 2 presents fit in a 6x3 region:\n", "\n", " ### XXX ###XXX\n", " #.# + X.X = #.#X.X\n", " #.# X.X #.#X.X\n", "\n", "But if we rotate some presents and squish them together we can do better. We could fit two presents into a 4x4 region:\n", "\n", " ### X.X ###.\n", " #.# + X.X = #X#X\n", " #.# XXX #X#X\n", " .XXX\n", "\n", "I want to know how much squishing we have to do; is this going to be easy or hard? Will a search for good squishing positions take milliseconds or days? First, what's the average area of the regions?" ] }, { "cell_type": "code", "execution_count": 87, "id": "388d13ab-b5db-47e4-9f33-50f7062424b9", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1822.223" ] }, "execution_count": 87, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mean(region.W * region.L for region in regions)" ] }, { "cell_type": "markdown", "id": "cefca7b5-a9a2-4fb9-bd4b-071f7ecd5db0", "metadata": {}, "source": [ "And average total quantity of presents in a region?" ] }, { "cell_type": "code", "execution_count": 88, "id": "5d982737-cbca-4739-be1c-fa1dce319ef4", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "240.488" ] }, "execution_count": 88, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mean(sum(region.quantities) for region in regions)" ] }, { "cell_type": "markdown", "id": "af3fe830-aa75-469b-9046-3f36ff3a03e2", "metadata": {}, "source": [ "Next I want to get a feel for the variation in how tight the packing is. Each present can definitely fit into a 3x3 box, so what's the ratio of the total quantity of presents to the number of 3x3 boxes? I'll call that the **occupancy ratio**. I'll make a histogram of occupancy ratio for each region:" ] }, { "cell_type": "code", "execution_count": 89, "id": "b8cf45b6-5513-426a-86c2-425d0d74d781", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def boxes(region: Region) -> int: \n", " \"\"\"Number of 3x3 boxes that can fit into the region.\"\"\"\n", " return (region.W // 3) * (region.L // 3)\n", " \n", "occupancy_ratios = [sum(region.quantities) / boxes(region) for region in regions]\n", "plt.hist(occupancy_ratios, bins=120);" ] }, { "cell_type": "markdown", "id": "54f2eaa0-b8b6-4a60-bcde-28eeefa26e8c", "metadata": {}, "source": [ "**Very interesting!** There's a real split:\n", "- About half the regions have an occupancy ratio below 1.0 and thus trivially fit into the region: plop one present into each 3x3 box.\n", "- The rest of the regions have occupancy ratios above 1.35. The average shape looks like it could overlap with another piece to save about two \".\" squares. So an occupancy rato of 1 + 2/9 = 1.22 looks like it could be made to fit, but 1.35 or more seems very unlikely. I can prove it is impossible if the total area of the solid parts of the presents (the '#' squares) is more than the total area of the region (the width times length). \n", "\n", "I can do **triage** on the regions, yielding 1 for regions where every present fits in a box; 0 for regions where there are more present area that region area, and `'?'`to signify that neither of those holds, we are uncertain if the presents fit, and we'll need to do a search. I'm hoping we don't get any of those." ] }, { "cell_type": "code", "execution_count": 90, "id": "8d2ef858-2367-44b1-adfd-f5b18c53b2a6", "metadata": {}, "outputs": [], "source": [ "def triage(regions, shapes) -> Iterator[int | str]:\n", " \"\"\"Count how many regions fit, fail to fit, or are uncertain at first glance.\"\"\"\n", " shape_area = [cat(shape).count('#') for shape in shapes] # total number of '#' in each shape\n", " for region in regions:\n", " yield (1 if sum(region.quantities) <= boxes(region) else\n", " 0 if dotproduct(shape_area, region.quantities) > region.W * region.L else\n", " '?')" ] }, { "cell_type": "markdown", "id": "9e85a2de-8e75-4be0-8324-de816df889fb", "metadata": {}, "source": [ "Let's see:" ] }, { "cell_type": "code", "execution_count": 91, "id": "6768fa83-2af7-4aab-a930-9106da3859bd", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Counter({0: 546, 1: 454})" ] }, "execution_count": 91, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Counter(triage(regions, shapes))" ] }, { "cell_type": "markdown", "id": "cbedea21-3bed-4c99-9b57-fc1f1e03f76b", "metadata": {}, "source": [ "**The problem is solved**; there are no uncertain regions that require a search. \n", "\n", "*Sometimes the real treasure is the code you don't have to write along the way.*" ] }, { "cell_type": "code", "execution_count": 92, "id": "0ec553c4-85eb-40a6-8bed-7adddf75e512", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Puzzle 12.1: 0.4 msec, correct answer: 454 " ] }, "execution_count": 92, "metadata": {}, "output_type": "execute_result" } ], "source": [ "answer(12.1, 454, lambda:\n", " sum(triage(regions, shapes)))" ] }, { "cell_type": "markdown", "id": "0f9aa492-91ad-457a-b83e-13a12b899bc5", "metadata": {}, "source": [ "You might well object that I didn't solve the problem, that there *could* have been uncertain regions. From the comments in [**r/adventofcode/**](https://www.reddit.com/r/adventofcode/) it looks like nobody got any uncertain regions, so I solved the problem that Eric Wastl intended, but I didn't solve for all possible inputs. You can see [an AI-generated solution](Advent-2025-AI.ipynb). For now, I'll just consider one part of a more general solution: what if the input shapes are not all 3x3? You could handle that with this updated version of boxes:" ] }, { "cell_type": "code", "execution_count": 93, "id": "edc1a7eb-f47e-4995-a775-ceee79045484", "metadata": {}, "outputs": [], "source": [ "def boxes(region, shapes=shapes) -> int: \n", " \"\"\"Number of boxes that can fit into a region. Compute the box dimensions from `shapes`.\"\"\"\n", " def dimensions(shape) -> tuple[int, int]: return len(shape), len(shape[0])\n", " shape_S = max(min(dimensions(shape) for shape in shapes)) # The smallest dimension of each box\n", " shape_L = max(max(dimensions(shape) for shape in shapes)) # The largest dimension of each box\n", " # Try to fit the boxes into the region both ways (i.e. one turned 90 degrees)\n", " return max((region.W // shape_S) * (region.L // shape_L),\n", " (region.W // shape_L) * (region.L // shape_S))" ] }, { "cell_type": "markdown", "id": "7f31ae9b-6606-40b0-9bb1-ed9b3fe3cbf0", "metadata": {}, "source": [ "# Summary\n", "\n", "Here are the run times and the correct answers for each of the puzzles:" ] }, { "cell_type": "code", "execution_count": 94, "id": "4d512a50-c6ae-4803-a787-b8f6e0103e31", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Time in milliseconds: sum = 366.2, mean = 15.9, median = 0.9, max = 113.5\n", "\n", "Puzzle 1.1: 0.2 msec, correct answer: 1182 \n", "Puzzle 1.2: 0.4 msec, correct answer: 6907 \n", "Puzzle 2.1: 0.1 msec, correct answer: 23560874270 \n", "Puzzle 2.2: 0.2 msec, correct answer: 44143124633 \n", "Puzzle 3.1: 0.3 msec, correct answer: 17085 \n", "Puzzle 3.2: 0.8 msec, correct answer: 169408143086082\n", "Puzzle 4.1: 18.8 msec, correct answer: 1569 \n", "Puzzle 4.2: 50.1 msec, correct answer: 9280 \n", "Puzzle 5.1: 4.4 msec, correct answer: 635 \n", "Puzzle 5.2: 0.0 msec, correct answer: 369761800782619\n", "Puzzle 6.1: 0.9 msec, correct answer: 5877594983578 \n", "Puzzle 6.2: 1.3 msec, correct answer: 11159825706149 \n", "Puzzle 7.1: 0.4 msec, correct answer: 1681 \n", "Puzzle 7.2: 0.7 msec, correct answer: 422102272495018\n", "Puzzle 8.1: 93.0 msec, correct answer: 24360 \n", "Puzzle 8.2: 113.5 msec, correct answer: 2185817796 \n", "Puzzle 9.1: 11.7 msec, correct answer: 4772103936 \n", "Puzzle 9.2: 2.0 msec, correct answer: 1529675217 \n", "Puzzle 10.1: 21.5 msec, correct answer: 441 \n", "Puzzle 10.2: 44.3 msec, correct answer: 18559 \n", "Puzzle 11.1: 0.1 msec, correct answer: 574 \n", "Puzzle 11.2: 0.9 msec, correct answer: 306594217920240\n", "Puzzle 12.1: 0.4 msec, correct answer: 454 \n" ] } ], "source": [ "summary(answers)" ] }, { "cell_type": "markdown", "id": "1098c017-2746-403c-bfb0-1a08cacc835d", "metadata": {}, "source": [ "**I solved all the puzzles**. The total run time is under a half-second, with the two parts of Day 8 taking the longest at about 100 milliseconds each. The median is under 1 millisecond.\n", "\n", "Happy Advent everyone, and thank you [Eric Wastl](https://was.tl/) for the interesting puzzles! I'm very supportive of your decisions to (a) only go 12 days, and (b) no longer have a leaderboard. I'm feeling surprisingly relaxed on December 12th!\n", "\n", "\n", "And thank you Gary Grady for the drawings!\n", "\n", "\"Gary\n", "\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.3" } }, "nbformat": 4, "nbformat_minor": 5 }