From 69a2b1f887e6a3e80373c45bc044484b0fdb7b6b Mon Sep 17 00:00:00 2001 From: Peter Norvig Date: Sat, 20 Dec 2025 16:52:30 -0800 Subject: [PATCH] Add files via upload --- ipynb/Advent-2025.ipynb | 425 +++++++++++++++++++----------------- ipynb/lander-parkin66.ipynb | 149 +++++++++++++ 2 files changed, 371 insertions(+), 203 deletions(-) create mode 100644 ipynb/lander-parkin66.ipynb diff --git a/ipynb/Advent-2025.ipynb b/ipynb/Advent-2025.ipynb index 60c57bd..487a3b1 100644 --- a/ipynb/Advent-2025.ipynb +++ b/ipynb/Advent-2025.ipynb @@ -46,7 +46,7 @@ "source": [ "# Day 1: Secret Entrance (Rotating 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 24 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", + "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, after replacing each 'L' with a minus sign and each 'R' with a plus sign. " ] @@ -146,7 +146,7 @@ "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:" + "I submitted \"1182\" to AoC and got back ***That's the right answer!***, so I record the answer (and its run time) like this:" ] }, { @@ -158,7 +158,7 @@ { "data": { "text/plain": [ - "Puzzle 1.1: .0004 seconds, answer 1182 correct" + "Puzzle 1.1: .0006 seconds, answer 1182 correct" ] }, "execution_count": 5, @@ -180,19 +180,19 @@ "\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.)" + "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": "bfb5bd2d-d768-47b3-9897-d28f83f2202a", + "id": "053717d0-fe49-4b95-95a4-06202357883d", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 1.2: .0906 seconds, answer 6907 correct" + "Puzzle 1.2: .0574 seconds, answer 6907 correct" ] }, "execution_count": 6, @@ -202,7 +202,7 @@ ], "source": [ "answer(1.2, 6907, lambda:\n", - " count_zeros(sign(r) for r in rotations for _ in range(abs(r))))" + " count_zeros(flatten(abs(r) * [sign(r)] for r in rotations)))" ] }, { @@ -220,7 +220,7 @@ "metadata": {}, "outputs": [], "source": [ - "def zero_clicks(rotations, position=50, dial=100) -> int:\n", + "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", @@ -252,7 +252,7 @@ ], "source": [ "answer(1.2, 6907, lambda:\n", - " zero_clicks(rotations))" + " count_all_zeros(rotations))" ] }, { @@ -346,51 +346,71 @@ "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 \"123456\" is \"123\".\n", + "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", - "Suppose the range is 123456-223000. I enumerate from 123 to 223, and for each number generate an invalid ID:\n", - "[123123, 124124, 125125, ... 223223]. I then yield the IDs that are within the range (in this case all but the first and the last are in the range 123456-223000). Altogether I only have to consider 101 half IDs rather than 100,001 full IDs. (The algorithm scales with the square root of the size of the range, not with the size of the range itself.)" + "Suppose the range is 123456-223456. We can see the first-half strategy has to consider far fewer numbers:\n", + "\n", + "|strategy|range|start|end|numbers to consider|\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": "1345f93d-84c5-43f8-b6c2-9fc7b8f5ed90", + "id": "c65d1ca2-571a-497a-afe7-6f3ab01c23ab", "metadata": {}, "outputs": [], "source": [ "def invalids_in_range(lo: int, hi: int) -> Iterable[int]:\n", " \"\"\"Yield all the invalid IDs between lo and hi inclusive.\n", " An ID is invalid if it consists of a digit sequence repeated twice.\"\"\"\n", - " first_half = str(lo)[:max(1, len(str(lo)) // 2)]\n", - " for i in count_from(int(first_half)):\n", + " for i in count_from(first_half(lo)):\n", " id = int(str(i) * 2)\n", " if lo <= id <= hi:\n", " yield id\n", " elif id > hi:\n", " return\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)\n", - "\n", - "assert invalids([(11, 22)]) == {11, 22}" + " 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": "8b0d12b3-f184-4149-8b49-f9ff78663d46", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 2.1: .0023 seconds, answer 23560874270 correct" + "Puzzle 2.1: .0003 seconds, answer 23560874270 correct" ] }, - "execution_count": 12, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } @@ -407,45 +427,42 @@ "source": [ "### Part 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, and introduce `all_invalids` to try all possible repeat lengths across all ID ranges:" + "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": 13, + "execution_count": 101, "id": "4fbf52e7-a06a-4000-8627-80d159788da1", "metadata": {}, "outputs": [], "source": [ "def invalids_in_range(lo: int, hi: int, repeat=2) -> Iterable[int]:\n", - " \"\"\"Yield all the invalid IDs between lo and hi inclusive\n", - " that are formed from exactly `repeat` repeated digit sequences.\"\"\"\n", - " first_half = int(str(lo)[:len(str(lo)) // repeat] or 1)\n", - " for i in count_from(int(first_half)):\n", + " \"\"\"Yield some of the invalid IDs between lo and hi inclusive.\n", + " An ID is invalid if it consists of a digit sequence repeated `repeat` times.\"\"\"\n", + " for i in count_from(first_half(lo, repeat)):\n", " id = int(str(i) * repeat)\n", " if lo <= id <= hi:\n", " yield id\n", " elif id > hi:\n", " return\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, according to the list of ranges, with any number of repeats.\"\"\"\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": "1e7d71d2-8c08-4673-8d12-661edd6ab6f5", - "metadata": {}, - "source": [ - "Since this is a bit tricky, I include some unit test assertions:" - ] - }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 102, "id": "5a29e5bc-3b07-4800-9a0f-4bd433e01c55", "metadata": {}, "outputs": [], @@ -464,17 +481,17 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 103, "id": "8a7c6c25-4b5f-4178-8559-166ba1a9f924", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 2.1: .0023 seconds, answer 23560874270 correct" + "Puzzle 2.1: .0004 seconds, answer 23560874270 correct" ] }, - "execution_count": 15, + "execution_count": 103, "metadata": {}, "output_type": "execute_result" } @@ -486,17 +503,17 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 104, "id": "32fefd65-df2a-4ea3-9acd-7525ebd32380", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 2.2: .0030 seconds, answer 44143124633 correct" + "Puzzle 2.2: .0005 seconds, answer 44143124633 correct" ] }, - "execution_count": 16, + "execution_count": 104, "metadata": {}, "output_type": "execute_result" } @@ -511,7 +528,9 @@ "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." + "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 `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." ] }, { @@ -526,7 +545,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 18, "id": "04ef4f2f-2b07-43cd-87d4-a8f63f7fe840", "metadata": {}, "outputs": [ @@ -565,7 +584,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 19, "id": "0168ada2-b53e-4215-9e6a-2468759f095c", "metadata": {}, "outputs": [], @@ -584,7 +603,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 20, "id": "3f6390f5-78b7-4472-acf9-8855d2c2453e", "metadata": {}, "outputs": [], @@ -595,17 +614,17 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 21, "id": "9cc62ae9-b313-4b82-b8fb-bab9c0ef5cb6", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 3.1: .0006 seconds, answer 17085 correct" + "Puzzle 3.1: .0005 seconds, answer 17085 correct" ] }, - "execution_count": 20, + "execution_count": 21, "metadata": {}, "output_type": "execute_result" } @@ -629,7 +648,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 22, "id": "b9507c12-421b-41af-b926-a4d3d83f622d", "metadata": {}, "outputs": [], @@ -652,7 +671,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 23, "id": "4a58a657-8f32-4001-a4ff-f30dfbe7e5e7", "metadata": {}, "outputs": [], @@ -672,7 +691,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 24, "id": "fe3cff78-81c0-4d4a-bb4d-f0f841067e0d", "metadata": {}, "outputs": [ @@ -682,7 +701,7 @@ "Puzzle 3.1: .0006 seconds, answer 17085 correct" ] }, - "execution_count": 23, + "execution_count": 24, "metadata": {}, "output_type": "execute_result" } @@ -694,17 +713,17 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 25, "id": "f971839e-81ea-49b4-a92f-a44884be645d", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 3.2: .0015 seconds, answer 169408143086082 correct" + "Puzzle 3.2: .0016 seconds, answer 169408143086082 correct" ] }, - "execution_count": 24, + "execution_count": 25, "metadata": {}, "output_type": "execute_result" } @@ -726,7 +745,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 26, "id": "c9f227d5-2748-48e1-80c1-7385dad46323", "metadata": {}, "outputs": [ @@ -768,7 +787,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 27, "id": "6fe5bd44-8a28-4d7a-bc8b-edc4af8f23c3", "metadata": {}, "outputs": [], @@ -793,17 +812,17 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 28, "id": "a5ef09cf-b204-41eb-80d8-de107d385dbb", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 4.1: .0356 seconds, answer 1569 correct" + "Puzzle 4.1: .0376 seconds, answer 1569 correct" ] }, - "execution_count": 27, + "execution_count": 28, "metadata": {}, "output_type": "execute_result" } @@ -827,7 +846,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 29, "id": "0ed53853-268c-4c2f-a929-cb3e6005a348", "metadata": {}, "outputs": [], @@ -842,17 +861,17 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 30, "id": "2fb17a51-05f7-42ec-8d6c-222121a026cf", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 4.2: .8029 seconds, answer 9280 correct" + "Puzzle 4.2: .8418 seconds, answer 9280 correct" ] }, - "execution_count": 29, + "execution_count": 30, "metadata": {}, "output_type": "execute_result" } @@ -872,7 +891,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 31, "id": "54f20b5e-6713-459c-8d40-e545ce6b8e42", "metadata": {}, "outputs": [], @@ -891,17 +910,17 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 32, "id": "bcba970b-09aa-479b-9c6d-4f6a7ac49fed", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 4.2: .0920 seconds, answer 9280 correct" + "Puzzle 4.2: .0968 seconds, answer 9280 correct" ] }, - "execution_count": 31, + "execution_count": 32, "metadata": {}, "output_type": "execute_result" } @@ -923,7 +942,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 33, "id": "402e78e0-cf05-4285-bd9c-07b6ebd9b602", "metadata": {}, "outputs": [ @@ -968,7 +987,7 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 34, "id": "4b508db5-aeae-410e-a062-1b2d4ce41253", "metadata": {}, "outputs": [ @@ -1018,7 +1037,7 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 35, "id": "ae5b33e4-92f5-4fe2-bd5a-6b22095724fa", "metadata": {}, "outputs": [], @@ -1031,17 +1050,17 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": 36, "id": "112a84f7-9bb8-45f0-9d7e-f600f37f0fdf", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 5.1: .0069 seconds, answer 635 correct" + "Puzzle 5.1: .0071 seconds, answer 635 correct" ] }, - "execution_count": 35, + "execution_count": 36, "metadata": {}, "output_type": "execute_result" } @@ -1065,7 +1084,7 @@ }, { "cell_type": "code", - "execution_count": 36, + "execution_count": 37, "id": "47a660d2-746c-433f-b4ae-9d01f70bc504", "metadata": {}, "outputs": [ @@ -1075,7 +1094,7 @@ "476036797138761" ] }, - "execution_count": 36, + "execution_count": 37, "metadata": {}, "output_type": "execute_result" } @@ -1094,7 +1113,7 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": 38, "id": "f52e8ecd-325e-4ed4-8928-de9365b5b7d4", "metadata": {}, "outputs": [], @@ -1112,7 +1131,7 @@ }, { "cell_type": "code", - "execution_count": 38, + "execution_count": 39, "id": "fab6f1ed-543f-4f42-b1d5-2551742e3a4f", "metadata": {}, "outputs": [ @@ -1122,7 +1141,7 @@ "Puzzle 5.2: .0001 seconds, answer 369761800782619 correct" ] }, - "execution_count": 38, + "execution_count": 39, "metadata": {}, "output_type": "execute_result" } @@ -1148,7 +1167,7 @@ }, { "cell_type": "code", - "execution_count": 39, + "execution_count": 40, "id": "bca852a9-e4c5-4706-abfc-afc6d4a4eeb5", "metadata": {}, "outputs": [ @@ -1183,7 +1202,7 @@ }, { "cell_type": "code", - "execution_count": 40, + "execution_count": 41, "id": "92f320f4-c7a3-4dfd-ae61-6b1b180bdc93", "metadata": {}, "outputs": [], @@ -1198,17 +1217,17 @@ }, { "cell_type": "code", - "execution_count": 41, + "execution_count": 42, "id": "92a47f3a-127f-41e8-bee1-6276885bd36b", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 6.1: .0016 seconds, answer 5877594983578 correct" + "Puzzle 6.1: .0017 seconds, answer 5877594983578 correct" ] }, - "execution_count": 41, + "execution_count": 42, "metadata": {}, "output_type": "execute_result" } @@ -1245,7 +1264,7 @@ }, { "cell_type": "code", - "execution_count": 42, + "execution_count": 43, "id": "5866583b-245d-4a43-a037-229bf35f1be2", "metadata": {}, "outputs": [], @@ -1281,17 +1300,17 @@ }, { "cell_type": "code", - "execution_count": 43, + "execution_count": 44, "id": "39a8fa78-946f-45aa-8d36-76883f4aeaff", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 6.2: .0028 seconds, answer 11159825706149 correct" + "Puzzle 6.2: .0029 seconds, answer 11159825706149 correct" ] }, - "execution_count": 43, + "execution_count": 44, "metadata": {}, "output_type": "execute_result" } @@ -1311,7 +1330,7 @@ }, { "cell_type": "code", - "execution_count": 44, + "execution_count": 45, "id": "a13dbe89-3178-433f-9a50-28ed9a2f8358", "metadata": {}, "outputs": [ @@ -1321,7 +1340,7 @@ "3263827" ] }, - "execution_count": 44, + "execution_count": 45, "metadata": {}, "output_type": "execute_result" } @@ -1338,7 +1357,7 @@ }, { "cell_type": "code", - "execution_count": 45, + "execution_count": 46, "id": "3aa0b661-367a-4316-905a-60f1d9e6df01", "metadata": {}, "outputs": [ @@ -1351,7 +1370,7 @@ " ['* ', '+ ', '* ', '+']]" ] }, - "execution_count": 45, + "execution_count": 46, "metadata": {}, "output_type": "execute_result" } @@ -1362,7 +1381,7 @@ }, { "cell_type": "code", - "execution_count": 46, + "execution_count": 47, "id": "13392d9c-fef8-4946-b945-48ad6bc7eca9", "metadata": {}, "outputs": [ @@ -1375,7 +1394,7 @@ " ('64 ', '23 ', '314', '+')]" ] }, - "execution_count": 46, + "execution_count": 47, "metadata": {}, "output_type": "execute_result" } @@ -1386,7 +1405,7 @@ }, { "cell_type": "code", - "execution_count": 47, + "execution_count": 48, "id": "e29df77c-7385-4ba9-a27b-4074a78a0d74", "metadata": {}, "outputs": [ @@ -1396,7 +1415,7 @@ "[1, 24, 356]" ] }, - "execution_count": 47, + "execution_count": 48, "metadata": {}, "output_type": "execute_result" } @@ -1409,7 +1428,7 @@ }, { "cell_type": "code", - "execution_count": 48, + "execution_count": 49, "id": "9a25ff50-f465-4de3-95ca-71b7a3d9569b", "metadata": {}, "outputs": [], @@ -1431,7 +1450,7 @@ }, { "cell_type": "code", - "execution_count": 49, + "execution_count": 50, "id": "e85af831-b6cf-4073-a131-ce68debaea75", "metadata": {}, "outputs": [ @@ -1472,7 +1491,7 @@ }, { "cell_type": "code", - "execution_count": 50, + "execution_count": 51, "id": "d4d3bdbb-d8b2-4e22-adb4-c99a212a2ca7", "metadata": {}, "outputs": [], @@ -1493,17 +1512,17 @@ }, { "cell_type": "code", - "execution_count": 51, + "execution_count": 52, "id": "0e14ad5e-6871-4a9c-bd94-5a863c2341e0", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 7.1: .0006 seconds, answer 1681 correct" + "Puzzle 7.1: .0008 seconds, answer 1681 correct" ] }, - "execution_count": 51, + "execution_count": 52, "metadata": {}, "output_type": "execute_result" } @@ -1527,7 +1546,7 @@ }, { "cell_type": "code", - "execution_count": 52, + "execution_count": 53, "id": "df96165c-4e55-447a-bc5c-fba2f0462ebf", "metadata": {}, "outputs": [], @@ -1547,17 +1566,17 @@ }, { "cell_type": "code", - "execution_count": 53, + "execution_count": 54, "id": "ee179d56-ce86-473d-9801-39f1b90d03ab", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 7.2: .0015 seconds, answer 422102272495018 correct" + "Puzzle 7.2: .0014 seconds, answer 422102272495018 correct" ] }, - "execution_count": 53, + "execution_count": 54, "metadata": {}, "output_type": "execute_result" } @@ -1579,7 +1598,7 @@ }, { "cell_type": "code", - "execution_count": 54, + "execution_count": 55, "id": "a5cc43b2-3c5d-4d28-8c94-112bbb5739e7", "metadata": {}, "outputs": [ @@ -1636,7 +1655,7 @@ }, { "cell_type": "code", - "execution_count": 55, + "execution_count": 56, "id": "fb7744c9-105b-439b-aa57-caf93b8117b8", "metadata": {}, "outputs": [], @@ -1671,17 +1690,17 @@ }, { "cell_type": "code", - "execution_count": 56, + "execution_count": 57, "id": "337ab7d6-d142-4c56-a0a3-2b6cd06cd895", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 8.1: .4011 seconds, answer 24360 correct" + "Puzzle 8.1: .4600 seconds, answer 24360 correct" ] }, - "execution_count": 56, + "execution_count": 57, "metadata": {}, "output_type": "execute_result" } @@ -1703,7 +1722,7 @@ }, { "cell_type": "code", - "execution_count": 57, + "execution_count": 58, "id": "1096ded6-749e-4787-9b90-2de917b147c4", "metadata": {}, "outputs": [], @@ -1724,17 +1743,17 @@ }, { "cell_type": "code", - "execution_count": 58, + "execution_count": 59, "id": "58f06244-ca67-47c9-8ca5-3346a249e1fc", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 8.2: .4378 seconds, answer 2185817796 correct" + "Puzzle 8.2: .5004 seconds, answer 2185817796 correct" ] }, - "execution_count": 58, + "execution_count": 59, "metadata": {}, "output_type": "execute_result" } @@ -1764,7 +1783,7 @@ }, { "cell_type": "code", - "execution_count": 59, + "execution_count": 60, "id": "2dba6fa4-a09b-4ab3-a163-0f94f98e82f2", "metadata": {}, "outputs": [ @@ -1817,7 +1836,7 @@ }, { "cell_type": "code", - "execution_count": 60, + "execution_count": 61, "id": "75f2742e-9dbd-4005-a882-3d3931fb1b36", "metadata": {}, "outputs": [], @@ -1840,17 +1859,17 @@ }, { "cell_type": "code", - "execution_count": 61, + "execution_count": 62, "id": "27f350c5-7866-4b7b-8d32-91512fcec5b9", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 9.1: .0239 seconds, answer 4772103936 correct" + "Puzzle 9.1: .0267 seconds, answer 4772103936 correct" ] }, - "execution_count": 61, + "execution_count": 62, "metadata": {}, "output_type": "execute_result" } @@ -1876,7 +1895,7 @@ }, { "cell_type": "code", - "execution_count": 62, + "execution_count": 63, "id": "b5967a65-338d-4198-9f59-986ff74132e6", "metadata": {}, "outputs": [ @@ -1940,7 +1959,7 @@ }, { "cell_type": "code", - "execution_count": 63, + "execution_count": 64, "id": "e08d6c65-5b4e-456e-b4de-38339d209372", "metadata": {}, "outputs": [], @@ -1986,7 +2005,7 @@ }, { "cell_type": "code", - "execution_count": 64, + "execution_count": 65, "id": "9dabf8bd-bdac-4b9a-941f-9de68480ca5d", "metadata": {}, "outputs": [ @@ -2019,7 +2038,7 @@ }, { "cell_type": "code", - "execution_count": 65, + "execution_count": 66, "id": "922d721e-5330-466b-8a54-8a273522c44d", "metadata": {}, "outputs": [], @@ -2053,17 +2072,17 @@ }, { "cell_type": "code", - "execution_count": 66, + "execution_count": 67, "id": "7ff60bbf-9cb6-4102-8b1c-5ef72be03c92", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 9.2: .0039 seconds, answer 1529675217 correct" + "Puzzle 9.2: .0037 seconds, answer 1529675217 correct" ] }, - "execution_count": 66, + "execution_count": 67, "metadata": {}, "output_type": "execute_result" } @@ -2083,7 +2102,7 @@ }, { "cell_type": "code", - "execution_count": 67, + "execution_count": 68, "id": "8ba7df82-cef0-4c94-8ffa-1822910d21f7", "metadata": {}, "outputs": [ @@ -2120,7 +2139,7 @@ }, { "cell_type": "code", - "execution_count": 68, + "execution_count": 69, "id": "d3b44691-da52-4794-ab77-bc4326aa6ca2", "metadata": {}, "outputs": [ @@ -2128,8 +2147,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 510 ms, sys: 4.08 ms, total: 515 ms\n", - "Wall time: 519 ms\n" + "CPU times: user 541 ms, sys: 5.34 ms, total: 546 ms\n", + "Wall time: 548 ms\n" ] }, { @@ -2138,7 +2157,7 @@ "True" ] }, - "execution_count": 68, + "execution_count": 69, "metadata": {}, "output_type": "execute_result" } @@ -2161,7 +2180,7 @@ }, { "cell_type": "code", - "execution_count": 69, + "execution_count": 70, "id": "437bd73a-6c8f-4196-8095-3299e5f8ef9d", "metadata": {}, "outputs": [ @@ -2214,7 +2233,7 @@ }, { "cell_type": "code", - "execution_count": 70, + "execution_count": 71, "id": "84cd63a7-4d50-4f14-9807-3cb439f80c88", "metadata": {}, "outputs": [ @@ -2272,7 +2291,7 @@ }, { "cell_type": "code", - "execution_count": 71, + "execution_count": 72, "id": "179e62b1-e4cb-43e4-8dc7-b87a28d21e8d", "metadata": {}, "outputs": [], @@ -2293,17 +2312,17 @@ }, { "cell_type": "code", - "execution_count": 72, + "execution_count": 73, "id": "d1368c2f-d792-4353-82e7-b0161ece784f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 10.1: .0492 seconds, answer 441 correct" + "Puzzle 10.1: .0541 seconds, answer 441 correct" ] }, - "execution_count": 72, + "execution_count": 73, "metadata": {}, "output_type": "execute_result" } @@ -2329,7 +2348,7 @@ }, { "cell_type": "code", - "execution_count": 73, + "execution_count": 74, "id": "1d2683fa-5126-4d2a-9dad-6a0e155f3449", "metadata": {}, "outputs": [ @@ -2339,7 +2358,7 @@ "7.181818181818182" ] }, - "execution_count": 73, + "execution_count": 74, "metadata": {}, "output_type": "execute_result" } @@ -2358,7 +2377,7 @@ }, { "cell_type": "code", - "execution_count": 74, + "execution_count": 75, "id": "a714c2c2-d433-41d0-8d1e-01832b35a1a9", "metadata": {}, "outputs": [ @@ -2368,7 +2387,7 @@ "114.81498043610085" ] }, - "execution_count": 74, + "execution_count": 75, "metadata": {}, "output_type": "execute_result" } @@ -2415,7 +2434,7 @@ }, { "cell_type": "code", - "execution_count": 75, + "execution_count": 76, "id": "713a1503-ae14-445f-91ea-714fcd618ad0", "metadata": {}, "outputs": [], @@ -2445,17 +2464,17 @@ }, { "cell_type": "code", - "execution_count": 76, + "execution_count": 77, "id": "46d0d274-bd4c-44af-83e9-35c791a8e96b", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 10.2: .1458 seconds, answer 18559 correct" + "Puzzle 10.2: .1553 seconds, answer 18559 correct" ] }, - "execution_count": 76, + "execution_count": 77, "metadata": {}, "output_type": "execute_result" } @@ -2482,7 +2501,7 @@ }, { "cell_type": "code", - "execution_count": 77, + "execution_count": 78, "id": "b9f82fef-612b-48a5-9de1-6ff0b137f7fb", "metadata": {}, "outputs": [ @@ -2492,7 +2511,7 @@ "Counter({-1: 68, 1: 65, 0: 32})" ] }, - "execution_count": 77, + "execution_count": 78, "metadata": {}, "output_type": "execute_result" } @@ -2511,7 +2530,7 @@ }, { "cell_type": "code", - "execution_count": 78, + "execution_count": 79, "id": "e536441d-64d4-410d-bb40-2343f6e01d88", "metadata": {}, "outputs": [ @@ -2521,7 +2540,7 @@ "Counter({1: 34, -1: 32, 0: 32, -2: 31, 2: 31, -3: 5})" ] }, - "execution_count": 78, + "execution_count": 79, "metadata": {}, "output_type": "execute_result" } @@ -2548,7 +2567,7 @@ }, { "cell_type": "code", - "execution_count": 79, + "execution_count": 80, "id": "b72544c8-6069-4310-a6dc-b4acd77981b4", "metadata": {}, "outputs": [], @@ -2575,7 +2594,7 @@ }, { "cell_type": "code", - "execution_count": 80, + "execution_count": 81, "id": "11e17f6a-acba-44c4-b704-7e4ff7471e7e", "metadata": {}, "outputs": [ @@ -2628,7 +2647,7 @@ }, { "cell_type": "code", - "execution_count": 81, + "execution_count": 82, "id": "7540a982-988a-4822-af0d-6581f6f848c6", "metadata": {}, "outputs": [], @@ -2655,17 +2674,17 @@ }, { "cell_type": "code", - "execution_count": 82, + "execution_count": 83, "id": "0c2d68a5-843b-49d6-aff6-23045968207f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 11.1: .0003 seconds, answer 574 correct" + "Puzzle 11.1: .0005 seconds, answer 574 correct" ] }, - "execution_count": 82, + "execution_count": 83, "metadata": {}, "output_type": "execute_result" } @@ -2687,7 +2706,7 @@ }, { "cell_type": "code", - "execution_count": 83, + "execution_count": 84, "id": "0294e044-c7ef-418a-9c02-71615a453002", "metadata": {}, "outputs": [], @@ -2707,17 +2726,17 @@ }, { "cell_type": "code", - "execution_count": 84, + "execution_count": 85, "id": "677a97b3-183b-474e-87ba-7db0d6b763d8", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 11.2: .0029 seconds, answer 306594217920240 correct" + "Puzzle 11.2: .0022 seconds, answer 306594217920240 correct" ] }, - "execution_count": 84, + "execution_count": 85, "metadata": {}, "output_type": "execute_result" } @@ -2739,7 +2758,7 @@ }, { "cell_type": "code", - "execution_count": 85, + "execution_count": 86, "id": "a1b304e8-339e-4e32-a462-3ba88103c415", "metadata": {}, "outputs": [ @@ -2836,7 +2855,7 @@ }, { "cell_type": "code", - "execution_count": 86, + "execution_count": 87, "id": "388d13ab-b5db-47e4-9f33-50f7062424b9", "metadata": {}, "outputs": [ @@ -2846,7 +2865,7 @@ "1822.223" ] }, - "execution_count": 86, + "execution_count": 87, "metadata": {}, "output_type": "execute_result" } @@ -2865,7 +2884,7 @@ }, { "cell_type": "code", - "execution_count": 87, + "execution_count": 88, "id": "5d982737-cbca-4739-be1c-fa1dce319ef4", "metadata": {}, "outputs": [ @@ -2875,7 +2894,7 @@ "240.488" ] }, - "execution_count": 87, + "execution_count": 88, "metadata": {}, "output_type": "execute_result" } @@ -2894,7 +2913,7 @@ }, { "cell_type": "code", - "execution_count": 88, + "execution_count": 89, "id": "b8cf45b6-5513-426a-86c2-425d0d74d781", "metadata": {}, "outputs": [ @@ -2925,14 +2944,14 @@ "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 unlikely. I could 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", + "- 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 to classify each one as a trivial fit, an impossible fit, or an uncertain fit (for which we would have to do a search):" + "I can do **triage** on the regions to classify each one as a fit, a fail, or an uncertain fit (for which we would have to do a search):" ] }, { "cell_type": "code", - "execution_count": 89, + "execution_count": 90, "id": "0cd74af7-a078-4e63-975a-ee459f3eb26d", "metadata": {}, "outputs": [], @@ -2943,7 +2962,7 @@ " counts = Counter()\n", " for region in regions:\n", " presents_area = sum(q * shape_area[i] for (i, q) in enumerate(region.quantities))\n", - " result = ('fit' if sum(region.quantities) <= boxes(region) # The presents all fit\n", + " result = ('fit' if sum(region.quantities) <= boxes(region) # The presents fit one per box\n", " else 'fail' if presents_area > region.W * region.L # The presents can't fit\n", " else 'uncertain') # We're uncertain\n", " counts[result] += 1\n", @@ -2960,7 +2979,7 @@ }, { "cell_type": "code", - "execution_count": 90, + "execution_count": 91, "id": "6768fa83-2af7-4aab-a930-9106da3859bd", "metadata": {}, "outputs": [ @@ -2970,7 +2989,7 @@ "Counter({'fail': 546, 'fit': 454})" ] }, - "execution_count": 90, + "execution_count": 91, "metadata": {}, "output_type": "execute_result" } @@ -2989,17 +3008,17 @@ }, { "cell_type": "code", - "execution_count": 91, + "execution_count": 92, "id": "0ec553c4-85eb-40a6-8bed-7adddf75e512", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Puzzle 12.1: .0012 seconds, answer 454 correct" + "Puzzle 12.1: .0013 seconds, answer 454 correct" ] }, - "execution_count": 91, + "execution_count": 92, "metadata": {}, "output_type": "execute_result" } @@ -3019,19 +3038,19 @@ }, { "cell_type": "code", - "execution_count": 92, + "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. Get the box dimensions from `shapes`.\"\"\"\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_W = max(min(dimensions(shape) for shape in shapes)) # The smallest dimension of each box\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_W) * (region.L // shape_L),\n", - " (region.W // shape_L) * (region.L // shape_W))" + " return max((region.W // shape_S) * (region.L // shape_L),\n", + " (region.W // shape_L) * (region.L // shape_S))" ] }, { @@ -3046,7 +3065,7 @@ }, { "cell_type": "code", - "execution_count": 93, + "execution_count": 94, "id": "4d512a50-c6ae-4803-a787-b8f6e0103e31", "metadata": {}, "outputs": [ @@ -3054,31 +3073,31 @@ "name": "stdout", "output_type": "stream", "text": [ - "Puzzle 1.1: .0004 seconds, answer 1182 correct\n", + "Puzzle 1.1: .0006 seconds, answer 1182 correct\n", "Puzzle 1.2: .0007 seconds, answer 6907 correct\n", - "Puzzle 2.1: .0023 seconds, answer 23560874270 correct\n", - "Puzzle 2.2: .0030 seconds, answer 44143124633 correct\n", + "Puzzle 2.1: .0003 seconds, answer 23560874270 correct\n", + "Puzzle 2.2: .0005 seconds, answer 44143124633 correct\n", "Puzzle 3.1: .0006 seconds, answer 17085 correct\n", - "Puzzle 3.2: .0015 seconds, answer 169408143086082 correct\n", - "Puzzle 4.1: .0356 seconds, answer 1569 correct\n", - "Puzzle 4.2: .0920 seconds, answer 9280 correct\n", - "Puzzle 5.1: .0069 seconds, answer 635 correct\n", + "Puzzle 3.2: .0016 seconds, answer 169408143086082 correct\n", + "Puzzle 4.1: .0376 seconds, answer 1569 correct\n", + "Puzzle 4.2: .0968 seconds, answer 9280 correct\n", + "Puzzle 5.1: .0071 seconds, answer 635 correct\n", "Puzzle 5.2: .0001 seconds, answer 369761800782619 correct\n", - "Puzzle 6.1: .0016 seconds, answer 5877594983578 correct\n", - "Puzzle 6.2: .0028 seconds, answer 11159825706149 correct\n", - "Puzzle 7.1: .0006 seconds, answer 1681 correct\n", - "Puzzle 7.2: .0015 seconds, answer 422102272495018 correct\n", - "Puzzle 8.1: .4011 seconds, answer 24360 correct\n", - "Puzzle 8.2: .4378 seconds, answer 2185817796 correct\n", - "Puzzle 9.1: .0239 seconds, answer 4772103936 correct\n", - "Puzzle 9.2: .0039 seconds, answer 1529675217 correct\n", - "Puzzle 10.1: .0492 seconds, answer 441 correct\n", - "Puzzle 10.2: .1458 seconds, answer 18559 correct\n", - "Puzzle 11.1: .0003 seconds, answer 574 correct\n", - "Puzzle 11.2: .0029 seconds, answer 306594217920240 correct\n", - "Puzzle 12.1: .0012 seconds, answer 454 correct\n", + "Puzzle 6.1: .0017 seconds, answer 5877594983578 correct\n", + "Puzzle 6.2: .0029 seconds, answer 11159825706149 correct\n", + "Puzzle 7.1: .0008 seconds, answer 1681 correct\n", + "Puzzle 7.2: .0014 seconds, answer 422102272495018 correct\n", + "Puzzle 8.1: .4600 seconds, answer 24360 correct\n", + "Puzzle 8.2: .5004 seconds, answer 2185817796 correct\n", + "Puzzle 9.1: .0267 seconds, answer 4772103936 correct\n", + "Puzzle 9.2: .0037 seconds, answer 1529675217 correct\n", + "Puzzle 10.1: .0541 seconds, answer 441 correct\n", + "Puzzle 10.2: .1553 seconds, answer 18559 correct\n", + "Puzzle 11.1: .0005 seconds, answer 574 correct\n", + "Puzzle 11.2: .0022 seconds, answer 306594217920240 correct\n", + "Puzzle 12.1: .0013 seconds, answer 454 correct\n", "\n", - "Time in seconds: sum = 1.216, mean = .053, median = .003, max = .438\n" + "Time in seconds: sum = 1.357, mean = .059, median = .002, max = .500\n" ] } ], diff --git a/ipynb/lander-parkin66.ipynb b/ipynb/lander-parkin66.ipynb new file mode 100644 index 0000000..bcd9e71 --- /dev/null +++ b/ipynb/lander-parkin66.ipynb @@ -0,0 +1,149 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "4c2c6cf3-da5e-4fef-b37b-cbed145f4eea", + "metadata": {}, + "source": [ + "[COUNTEREXAMPLE TO EULER'S CONJECTURE ON SUMS OF LIKE POWERS](https://projecteuclid.org/journals/bulletin-of-the-american-mathematical-society-new-series/volume-72/issue-6/Counterexample-to-Eulers-conjecture-on-sums-of-like-powers/bams/1183528522.full)\n", + "\n", + "![](https://i.sstatic.net/VQL6D.png)" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "id": "7de18ad5-b328-4618-911d-32c61ddab13d", + "metadata": {}, + "outputs": [], + "source": [ + "def sum_of_powers(M: int, n=5) -> list[tuple[int]]:\n", + " \"\"\"Return all (a, b, c, d, e), all < M, such that a^n + b^n + c^n + d^n = e^n.\n", + " This is O(M^3) in time and O(M^2) in space.\"\"\"\n", + " table = {a ** n + b ** n: (a, b)\n", + " for (a, b) in combinations(range(M), 2)}\n", + " results = []\n", + " for (c, d, e) in combinations(range(M), 3):\n", + " an_plus_bn = e ** n - (c ** n + d ** n)\n", + " if an_plus_bn in table:\n", + " a, b = table[an_plus_bn]\n", + " if a <= b <= c <= d: # Don't want duplicates\n", + " results.append((a, b, c, d, e))\n", + " return results" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "id": "00dc3732-ed29-4137-a3f8-fc7921e28d08", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[(27, 84, 110, 133, 144)]" + ] + }, + "execution_count": 59, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sum_of_powers(150)" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "id": "8c603613-b561-4a97-9779-c4d94269331a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 3.39 s, sys: 5.23 ms, total: 3.4 s\n", + "Wall time: 3.4 s\n" + ] + }, + { + "data": { + "text/plain": [ + "[[27, 84, 110, 133, 144], [54, 168, 220, 266, 288]]" + ] + }, + "execution_count": 56, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%time sum_of_powers(300)" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "id": "6e9de2d8-abf2-482d-adeb-c2ac01d10b4e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 1min 9s, sys: 227 ms, total: 1min 9s\n", + "Wall time: 1min 11s\n" + ] + }, + { + "data": { + "text/plain": [ + "[[27, 84, 110, 133, 144],\n", + " [54, 168, 220, 266, 288],\n", + " [81, 252, 330, 399, 432],\n", + " [108, 336, 440, 532, 576],\n", + " [135, 420, 550, 665, 720],\n", + " [162, 504, 660, 798, 864]]" + ] + }, + "execution_count": 57, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%time sum_of_powers(1000)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4b0ee9d9-d38d-4a63-8ccf-7baed27967f1", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}