diff --git a/ipynb/Advent-2024.ipynb b/ipynb/Advent-2024.ipynb
index 382b036..0ba049e 100644
--- a/ipynb/Advent-2024.ipynb
+++ b/ipynb/Advent-2024.ipynb
@@ -59,7 +59,7 @@
"source": [
"# [Day 1](https://adventofcode.com/2024/day/1) Historian Hysteria\n",
"\n",
- "According to the narrative, North Pole Historians created two lists of **location IDs**. We can parse them as a sequence of pairs of integers, and then use the transpose function, `T`, from my [AdventUtils](AdventUtils.ipynb) to get two lists of ID numbers:"
+ "According to the narrative, North Pole Historians created two lists of **location IDs**. We can parse them as a sequence of pairs of integers, and then use the transpose function, `T`, from my [AdventUtils](AdventUtils.ipynb) to get two tuples of ID numbers:"
]
},
{
@@ -100,7 +100,7 @@
}
],
"source": [
- "left, right = location_ids = T(parse(1, ints))"
+ "left, right = T(parse(1, ints))"
]
},
{
@@ -194,6 +194,14 @@
" similarity_score(left, right))"
]
},
+ {
+ "cell_type": "markdown",
+ "id": "b895bb80-2269-423f-a33c-abaa3d96561a",
+ "metadata": {},
+ "source": [
+ "As usual, the first day is something of a warm-up, coding up a solution is easy, and both parts run in under a millisecond (I don't need to know anything more precise than that)."
+ ]
+ },
{
"cell_type": "markdown",
"id": "b9fa4fe0-4194-47d7-b815-b571af98caee",
@@ -201,12 +209,12 @@
"source": [
"# [Day 2](https://adventofcode.com/2024/day/2): Red-Nosed Reports\n",
"\n",
- "Today's input is a sequence of **reports**, each of which is a sequence of integers:"
+ "Today's input is a sequence of engineering safety **reports**, each of which consists of a sequence of integers:"
]
},
{
"cell_type": "code",
- "execution_count": 13,
+ "execution_count": 14,
"id": "10e1ab83-a6ec-4143-ad9a-eaae220adcde",
"metadata": {},
"outputs": [
@@ -252,24 +260,24 @@
"source": [
"### Part 1: How many reports are safe?\n",
"\n",
- "A report is **safe** if it is monotonically strictly increasing or strictly decreasing, and if no difference between adjacent numbers is greater than 3 in absolute value."
+ "A report is **safe** if it is monotonically strictly increasing or strictly decreasing, and if no jump between adjacent numbers is greater than 3 in absolute value."
]
},
{
"cell_type": "code",
- "execution_count": 15,
+ "execution_count": 16,
"id": "0f6b6744-e93d-47cf-accd-daab9f3650d0",
"metadata": {},
"outputs": [],
"source": [
"def is_safe(report: Ints) -> bool:\n",
- " \"\"\"A report is safe if all adjacent-number-differences are either in {1, 2, 3} or in {-1, -2, -3}.\"\"\"\n",
- " deltas = diffs(report)\n",
- " return deltas.issubset({1, 2, 3}) or deltas.issubset({-1, -2, -3})\n",
+ " \"\"\"A report is safe if all adjacent-number-jumps are either in {1, 2, 3} or in {-1, -2, -3}.\"\"\"\n",
+ " jumps = set_of_jumps(report)\n",
+ " return jumps.issubset({1, 2, 3}) or jumps.issubset({-1, -2, -3})\n",
" \n",
- "def diffs(report: Ints) -> Set[int]:\n",
- " \"\"\"The set of differences between adjacent numbers in the report.\"\"\"\n",
- " return {report[i] - report[i - 1] for i in range(1, len(report))}"
+ "def set_of_jumps(numbers: Ints) -> Set[int]:\n",
+ " \"\"\"The set of differences between adjacent numbers.\"\"\"\n",
+ " return {numbers[i] - numbers[i - 1] for i in range(1, len(numbers))}"
]
},
{
@@ -282,12 +290,12 @@
},
{
"cell_type": "code",
- "execution_count": 17,
+ "execution_count": 18,
"id": "c0cc052b-e9ef-4757-a860-4cd34dd00fb8",
"metadata": {},
"outputs": [],
"source": [
- "assert diffs((7, 6, 4, 2, 1)) == {-1, -2}\n",
+ "assert set_of_jumps((7, 6, 4, 2, 1)) == {-1, -2}\n",
"assert is_safe((7, 6, 4, 2, 1)) == True"
]
},
@@ -301,7 +309,7 @@
},
{
"cell_type": "code",
- "execution_count": 19,
+ "execution_count": 20,
"id": "e662bf10-4d6a-40f1-95ce-dfc39f5b3fc2",
"metadata": {},
"outputs": [
@@ -311,7 +319,7 @@
"Puzzle 2.1: .000 seconds, answer 257 ok"
]
},
- "execution_count": 19,
+ "execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
@@ -330,13 +338,13 @@
"\n",
"### Part 2: How many reports are safe using the Problem Dampener?\n",
"\n",
- "The **problem dampener** says that a report is safe if there is some way to drop one element and get a safe report."
+ "The **problem dampener** says that a report is safe if there is some way to drop one number and get a safe report. So I'll generate all ways of dropping one number and check each one for safety."
]
},
{
"cell_type": "code",
- "execution_count": 21,
- "id": "67ba1d53-95b7-4811-b225-2ff15d6bdc5c",
+ "execution_count": 22,
+ "id": "6c78f864-5425-472f-9740-6f44650a98ca",
"metadata": {},
"outputs": [],
"source": [
@@ -344,16 +352,24 @@
" \"\"\"Is there any way to drop one element of `report` to get a safe report?\"\"\"\n",
" return any(map(is_safe, drop_one(report)))\n",
"\n",
- "def drop_one(seq: Sequence) -> Iterable:\n",
+ "def drop_one(seq: Sequence) -> Iterable[Sequence]:\n",
" \"\"\"All ways of dropping one element of the input sequence.\"\"\"\n",
- " return (seq[:i] + seq[i + 1:] for i in range(len(seq)))\n",
- "\n",
+ " return (seq[:i] + seq[i + 1:] for i in range(len(seq)))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 23,
+ "id": "7f492898-a704-4fb4-a93f-824f655d1f51",
+ "metadata": {},
+ "outputs": [],
+ "source": [
"assert set(drop_one('1234')) == {'234', '134', '124', '123'}"
]
},
{
"cell_type": "code",
- "execution_count": 22,
+ "execution_count": 24,
"id": "d1b9ffb5-af7a-465f-a063-c31df2d0605c",
"metadata": {},
"outputs": [
@@ -363,7 +379,7 @@
"Puzzle 2.2: .002 seconds, answer 328 ok"
]
},
- "execution_count": 22,
+ "execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
@@ -385,7 +401,7 @@
},
{
"cell_type": "code",
- "execution_count": 24,
+ "execution_count": 26,
"id": "78080200-0f9f-4492-9bee-c936737ee96f",
"metadata": {},
"outputs": [
@@ -424,7 +440,7 @@
},
{
"cell_type": "code",
- "execution_count": 26,
+ "execution_count": 28,
"id": "bf6366b1-6952-47d8-8b3c-09f8d05ec093",
"metadata": {},
"outputs": [],
@@ -438,7 +454,7 @@
},
{
"cell_type": "code",
- "execution_count": 27,
+ "execution_count": 29,
"id": "2032c903-5f23-4c16-ba68-410b6c1750e1",
"metadata": {},
"outputs": [
@@ -448,7 +464,7 @@
"Puzzle 3.1: .001 seconds, answer 156388521 ok"
]
},
- "execution_count": 27,
+ "execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
@@ -468,7 +484,7 @@
},
{
"cell_type": "code",
- "execution_count": 29,
+ "execution_count": 31,
"id": "85844f51-1396-4299-ba5b-c61064ee02b6",
"metadata": {},
"outputs": [],
@@ -488,7 +504,7 @@
},
{
"cell_type": "code",
- "execution_count": 31,
+ "execution_count": 33,
"id": "4525d01a-bac0-41c2-92b8-baf0fd395e88",
"metadata": {},
"outputs": [],
@@ -500,7 +516,7 @@
},
{
"cell_type": "code",
- "execution_count": 32,
+ "execution_count": 34,
"id": "ce40f258-ca76-48c3-9965-27a6979a4243",
"metadata": {},
"outputs": [
@@ -510,7 +526,7 @@
"Puzzle 3.2: .000 seconds, answer 75920122 ok"
]
},
- "execution_count": 32,
+ "execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
@@ -532,7 +548,7 @@
},
{
"cell_type": "code",
- "execution_count": 34,
+ "execution_count": 36,
"id": "a0d903b9-018e-4861-9314-cafed59055fd",
"metadata": {},
"outputs": [
@@ -571,7 +587,7 @@
},
{
"cell_type": "code",
- "execution_count": 36,
+ "execution_count": 38,
"id": "72d48abb-7a82-452f-b91d-838b3836a90f",
"metadata": {},
"outputs": [],
@@ -591,17 +607,17 @@
},
{
"cell_type": "code",
- "execution_count": 37,
+ "execution_count": 39,
"id": "6175362b-d8b4-45d1-b70c-d8575a0fe188",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "Puzzle 4.1: .020 seconds, answer 2401 ok"
+ "Puzzle 4.1: .021 seconds, answer 2401 ok"
]
},
- "execution_count": 37,
+ "execution_count": 39,
"metadata": {},
"output_type": "execute_result"
}
@@ -629,7 +645,7 @@
},
{
"cell_type": "code",
- "execution_count": 39,
+ "execution_count": 41,
"id": "3d8a051f-cf7b-4e8c-b0fb-78c3f089989d",
"metadata": {},
"outputs": [],
@@ -647,17 +663,17 @@
},
{
"cell_type": "code",
- "execution_count": 40,
+ "execution_count": 42,
"id": "64cde1d9-f58c-4633-b5da-87908a02f76d",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "Puzzle 4.2: .016 seconds, answer 1822 ok"
+ "Puzzle 4.2: .015 seconds, answer 1822 ok"
]
},
- "execution_count": 40,
+ "execution_count": 42,
"metadata": {},
"output_type": "execute_result"
}
@@ -683,7 +699,7 @@
},
{
"cell_type": "code",
- "execution_count": 42,
+ "execution_count": 44,
"id": "b77a5a1f-a43b-4ce8-a60c-94d69a595505",
"metadata": {},
"outputs": [
@@ -746,7 +762,7 @@
},
{
"cell_type": "code",
- "execution_count": 44,
+ "execution_count": 46,
"id": "4c85a23e-686a-4129-a14c-ff6f6a88b9ac",
"metadata": {},
"outputs": [],
@@ -767,7 +783,7 @@
},
{
"cell_type": "code",
- "execution_count": 46,
+ "execution_count": 48,
"id": "78898d37-46ff-4367-9d89-b2a107a90aa1",
"metadata": {},
"outputs": [],
@@ -785,7 +801,7 @@
},
{
"cell_type": "code",
- "execution_count": 47,
+ "execution_count": 49,
"id": "b1c87359-1d2d-4a90-8305-9d152ce5d547",
"metadata": {},
"outputs": [
@@ -795,7 +811,7 @@
"Puzzle 5.1: .001 seconds, answer 5762 ok"
]
},
- "execution_count": 47,
+ "execution_count": 49,
"metadata": {},
"output_type": "execute_result"
}
@@ -818,7 +834,7 @@
},
{
"cell_type": "code",
- "execution_count": 49,
+ "execution_count": 51,
"id": "d8718c3e-0b3b-49ce-8cca-abd82aa788d7",
"metadata": {},
"outputs": [
@@ -828,7 +844,7 @@
"23"
]
},
- "execution_count": 49,
+ "execution_count": 51,
"metadata": {},
"output_type": "execute_result"
}
@@ -850,7 +866,7 @@
},
{
"cell_type": "code",
- "execution_count": 51,
+ "execution_count": 53,
"id": "7222dc1c-067f-4bb5-84e1-3c2fc72fd53a",
"metadata": {},
"outputs": [],
@@ -867,7 +883,7 @@
},
{
"cell_type": "code",
- "execution_count": 52,
+ "execution_count": 54,
"id": "494cda6e-6b07-4054-9b03-45f61bd4f973",
"metadata": {},
"outputs": [
@@ -877,7 +893,7 @@
"Puzzle 5.2: .001 seconds, answer 4130 ok"
]
},
- "execution_count": 52,
+ "execution_count": 54,
"metadata": {},
"output_type": "execute_result"
}
@@ -907,7 +923,7 @@
},
{
"cell_type": "code",
- "execution_count": 55,
+ "execution_count": 57,
"id": "6ec71cf8-c43d-457e-8e14-0e9eb99b956a",
"metadata": {},
"outputs": [
@@ -950,7 +966,7 @@
},
{
"cell_type": "code",
- "execution_count": 57,
+ "execution_count": 59,
"id": "95f0b409-a6d6-47bc-8ce5-1c2df80f2b18",
"metadata": {},
"outputs": [],
@@ -969,17 +985,17 @@
},
{
"cell_type": "code",
- "execution_count": 58,
+ "execution_count": 60,
"id": "f4be3d1f-7f24-4d55-8221-df0026178e1e",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "Puzzle 6.1: .001 seconds, answer 5329 ok"
+ "Puzzle 6.1: .002 seconds, answer 5329 ok"
]
},
- "execution_count": 58,
+ "execution_count": 60,
"metadata": {},
"output_type": "execute_result"
}
@@ -1010,7 +1026,7 @@
},
{
"cell_type": "code",
- "execution_count": 60,
+ "execution_count": 62,
"id": "1718fecb-aa3e-4162-9948-1c06d4ec5e8a",
"metadata": {},
"outputs": [],
@@ -1022,7 +1038,7 @@
" if grid[ahead] == '#':\n",
" facing = make_turn(facing, 'R')\n",
" if (guard_pos, facing) in path:\n",
- " return True\n",
+ " return True # Found a loop\n",
" path.add((guard_pos, facing))\n",
" else:\n",
" guard_pos = ahead\n",
@@ -1040,17 +1056,17 @@
},
{
"cell_type": "code",
- "execution_count": 61,
+ "execution_count": 63,
"id": "36196264-eb33-4fc0-95d5-06c985105ebf",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "Puzzle 6.2: 1.998 seconds, answer 2162 ok"
+ "Puzzle 6.2: 1.943 seconds, answer 2162 ok"
]
},
- "execution_count": 61,
+ "execution_count": 63,
"metadata": {},
"output_type": "execute_result"
}
@@ -1082,7 +1098,7 @@
},
{
"cell_type": "code",
- "execution_count": 64,
+ "execution_count": 66,
"id": "c1c6cee8-122c-43c9-8c7d-ed8980ea2b76",
"metadata": {},
"outputs": [
@@ -1143,7 +1159,7 @@
},
{
"cell_type": "code",
- "execution_count": 67,
+ "execution_count": 69,
"id": "6fa3907c-0e1a-4d4a-9fc3-f809b9325674",
"metadata": {},
"outputs": [
@@ -1153,7 +1169,7 @@
"13"
]
},
- "execution_count": 67,
+ "execution_count": 69,
"metadata": {},
"output_type": "execute_result"
}
@@ -1174,7 +1190,7 @@
},
{
"cell_type": "code",
- "execution_count": 69,
+ "execution_count": 71,
"id": "5dfe0edf-cf29-4623-bb2c-6180f832f4d7",
"metadata": {},
"outputs": [],
@@ -1192,7 +1208,7 @@
},
{
"cell_type": "code",
- "execution_count": 70,
+ "execution_count": 72,
"id": "3085596d-f5ec-4ba8-b05a-cf70cf276a0c",
"metadata": {},
"outputs": [
@@ -1202,7 +1218,7 @@
"Puzzle 7.1: .014 seconds, answer 1985268524462 ok"
]
},
- "execution_count": 70,
+ "execution_count": 72,
"metadata": {},
"output_type": "execute_result"
}
@@ -1224,7 +1240,7 @@
},
{
"cell_type": "code",
- "execution_count": 72,
+ "execution_count": 74,
"id": "393a50cf-f136-446a-a97e-c501669ce89f",
"metadata": {},
"outputs": [],
@@ -1234,17 +1250,17 @@
},
{
"cell_type": "code",
- "execution_count": 73,
+ "execution_count": 75,
"id": "f8e75ea3-e8ba-4b33-8efe-8bf74357e35d",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "Puzzle 7.2: .803 seconds, answer 150077710195188 ok"
+ "Puzzle 7.2: .799 seconds, answer 150077710195188 ok"
]
},
- "execution_count": 73,
+ "execution_count": 75,
"metadata": {},
"output_type": "execute_result"
}
@@ -1264,7 +1280,7 @@
},
{
"cell_type": "code",
- "execution_count": 75,
+ "execution_count": 77,
"id": "6fe6adad-a3a6-49b8-b49e-6098b27e3a44",
"metadata": {},
"outputs": [],
@@ -1285,17 +1301,17 @@
},
{
"cell_type": "code",
- "execution_count": 76,
+ "execution_count": 78,
"id": "ffb673f1-af9d-4d15-8f8d-92e29489dd78",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "Puzzle 7.2: .606 seconds, answer 150077710195188 ok"
+ "Puzzle 7.2: .592 seconds, answer 150077710195188 ok"
]
},
- "execution_count": 76,
+ "execution_count": 78,
"metadata": {},
"output_type": "execute_result"
}
@@ -1305,24 +1321,6 @@
" sum(numbers[0] for numbers in equations if can_be_calibrated(numbers, operators3)))"
]
},
- {
- "cell_type": "markdown",
- "id": "ecb4bdf5-89ef-4625-8d7b-acbaeb86a18a",
- "metadata": {},
- "source": [
- "Now that we're done with the first week, I'm going to clean up by deleting some of the big data structures that are hanging around."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 78,
- "id": "ed4d4095-d417-4328-9c22-42c22606c482",
- "metadata": {},
- "outputs": [],
- "source": [
- "reports = xmas_grid = manual = rules = updates = lab_grid = equations = None"
- ]
- },
{
"cell_type": "markdown",
"id": "2e5693b7-dab8-4f89-a000-c69ee75a11c9",
@@ -1458,7 +1456,7 @@
{
"data": {
"text/plain": [
- "Puzzle 8.1: .002 seconds, answer 220 ok"
+ "Puzzle 8.1: .003 seconds, answer 220 ok"
]
},
"execution_count": 86,
@@ -1605,7 +1603,7 @@
{
"data": {
"text/plain": [
- "Puzzle 9.1: .020 seconds, answer 6332189866718 ok"
+ "Puzzle 9.1: .019 seconds, answer 6332189866718 ok"
]
},
"execution_count": 93,
@@ -1685,7 +1683,7 @@
{
"data": {
"text/plain": [
- "Puzzle 9.2: 2.428 seconds, answer 6353648390778 ok"
+ "Puzzle 9.2: 2.384 seconds, answer 6353648390778 ok"
]
},
"execution_count": 96,
@@ -1996,7 +1994,7 @@
{
"data": {
"text/plain": [
- "Puzzle 11.1: .066 seconds, answer 194482 ok"
+ "Puzzle 11.1: .067 seconds, answer 194482 ok"
]
},
"execution_count": 113,
@@ -2079,7 +2077,7 @@
{
"data": {
"text/plain": [
- "Puzzle 11.2: .061 seconds, answer 232454623677743 ok"
+ "Puzzle 11.2: .060 seconds, answer 232454623677743 ok"
]
},
"execution_count": 118,
@@ -2288,7 +2286,7 @@
{
"data": {
"text/plain": [
- "Puzzle 12.1: .030 seconds, answer 1402544 ok"
+ "Puzzle 12.1: .050 seconds, answer 1402544 ok"
]
},
"execution_count": 129,
@@ -2310,7 +2308,7 @@
{
"data": {
"text/plain": [
- "Puzzle 12.2: .061 seconds, answer 862486 ok"
+ "Puzzle 12.2: .042 seconds, answer 862486 ok"
]
},
"execution_count": 130,
@@ -2988,42 +2986,42 @@
"\n",
"\n",
"
\n",
- "
\n",
+ "
\n",
"
\n",
- "
\n",
+ " oninput=\"animdc0d5558c9a0485aa3c468981a103eb2.set_frame(parseInt(this.value));\">\n",
"
\n",
- " \n",
+ " \n",
" \n",
- " \n",
+ " \n",
" \n",
- " \n",
+ " \n",
" \n",
- " \n",
+ " \n",
" \n",
- " \n",
+ " \n",
" \n",
- " \n",
+ " \n",
" \n",
- " \n",
+ " \n",
" \n",
- " \n",
+ " \n",
" \n",
- " \n",
+ " \n",
" \n",
"
\n",
- "
\n",
"
\n",
"
\n",
@@ -3033,9 +3031,9 @@
" /* Instantiate the Animation class. */\n",
" /* The IDs given should match those used in the template above. */\n",
" (function() {\n",
- " var img_id = \"_anim_img6bb1e1ef68eb46a0ba61a1ed392b533e\";\n",
- " var slider_id = \"_anim_slider6bb1e1ef68eb46a0ba61a1ed392b533e\";\n",
- " var loop_select_id = \"_anim_loop_select6bb1e1ef68eb46a0ba61a1ed392b533e\";\n",
+ " var img_id = \"_anim_imgdc0d5558c9a0485aa3c468981a103eb2\";\n",
+ " var slider_id = \"_anim_sliderdc0d5558c9a0485aa3c468981a103eb2\";\n",
+ " var loop_select_id = \"_anim_loop_selectdc0d5558c9a0485aa3c468981a103eb2\";\n",
" var frames = new Array(3);\n",
" \n",
" frames[0] = \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90\\\n",
@@ -4772,14 +4770,14 @@
" /* set a timeout to make sure all the above elements are created before\n",
" the object is initialized. */\n",
" setTimeout(function() {\n",
- " anim6bb1e1ef68eb46a0ba61a1ed392b533e = new Animation(frames, img_id, slider_id, 200.0,\n",
+ " animdc0d5558c9a0485aa3c468981a103eb2 = new Animation(frames, img_id, slider_id, 200.0,\n",
" loop_select_id);\n",
" }, 0);\n",
" })()\n",
"\n"
],
"text/plain": [
- ""
+ ""
]
},
"execution_count": 156,
@@ -5012,42 +5010,42 @@
"\n",
"\n",
"\n",
- "
\n",
+ "
\n",
"
\n",
- "
\n",
+ " oninput=\"animea6b17f8e6f745568d5445b9aa800110.set_frame(parseInt(this.value));\">\n",
"
\n",
- " \n",
+ " \n",
" \n",
- " \n",
+ " \n",
" \n",
- " \n",
+ " \n",
" \n",
- " \n",
+ " \n",
" \n",
- " \n",
+ " \n",
" \n",
- " \n",
+ " \n",
" \n",
- " \n",
+ " \n",
" \n",
- " \n",
+ " \n",
" \n",
- " \n",
+ " \n",
" \n",
"
\n",
- "
\n",
"
\n",
"
\n",
@@ -5057,9 +5055,9 @@
" /* Instantiate the Animation class. */\n",
" /* The IDs given should match those used in the template above. */\n",
" (function() {\n",
- " var img_id = \"_anim_imgc44333b0e24f41239f8df1807c200349\";\n",
- " var slider_id = \"_anim_sliderc44333b0e24f41239f8df1807c200349\";\n",
- " var loop_select_id = \"_anim_loop_selectc44333b0e24f41239f8df1807c200349\";\n",
+ " var img_id = \"_anim_imgea6b17f8e6f745568d5445b9aa800110\";\n",
+ " var slider_id = \"_anim_sliderea6b17f8e6f745568d5445b9aa800110\";\n",
+ " var loop_select_id = \"_anim_loop_selectea6b17f8e6f745568d5445b9aa800110\";\n",
" var frames = new Array(1);\n",
" \n",
" frames[0] = \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90\\\n",
@@ -5448,14 +5446,14 @@
" /* set a timeout to make sure all the above elements are created before\n",
" the object is initialized. */\n",
" setTimeout(function() {\n",
- " animc44333b0e24f41239f8df1807c200349 = new Animation(frames, img_id, slider_id, 200.0,\n",
+ " animea6b17f8e6f745568d5445b9aa800110 = new Animation(frames, img_id, slider_id, 200.0,\n",
" loop_select_id);\n",
" }, 0);\n",
" })()\n",
"\n"
],
"text/plain": [
- ""
+ ""
]
},
"execution_count": 159,
@@ -5489,7 +5487,7 @@
{
"data": {
"text/plain": [
- "Puzzle 14.2: 1.874 seconds, answer 6876 ok"
+ "Puzzle 14.2: 1.828 seconds, answer 6876 ok"
]
},
"execution_count": 161,
@@ -5943,7 +5941,7 @@
{
"data": {
"text/plain": [
- "Puzzle 16.2: .863 seconds, answer 554 ok"
+ "Puzzle 16.2: .848 seconds, answer 554 ok"
]
},
"execution_count": 181,
@@ -5956,24 +5954,6 @@
" len(reindeer_best_positions(maze)))"
]
},
- {
- "cell_type": "markdown",
- "id": "479dc79f-44d9-4140-b79d-ebd9132fcfbd",
- "metadata": {},
- "source": [
- "Time to do another cleanup:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 183,
- "id": "0300f56c-ed13-4d63-a6d1-8c8bcba558ba",
- "metadata": {},
- "outputs": [],
- "source": [
- "disk_map = topo = farm = claws = robots = warehouse_woes = warehouse = arrows = maze = None"
- ]
- },
{
"cell_type": "markdown",
"id": "91607c18-56c3-4432-8da8-cfe570887bc0",
@@ -5986,7 +5966,7 @@
},
{
"cell_type": "code",
- "execution_count": 185,
+ "execution_count": 183,
"id": "50fd3cb8-0a6f-4edd-b5cb-f7b1e6f9d987",
"metadata": {},
"outputs": [
@@ -6030,7 +6010,7 @@
},
{
"cell_type": "code",
- "execution_count": 186,
+ "execution_count": 184,
"id": "c23b8a44-e352-4a30-abe5-3c939ffc743c",
"metadata": {},
"outputs": [
@@ -6040,7 +6020,7 @@
"Computer(A=52042868, B=0, C=0, prog=[2, 4, 1, 7, 7, 5, 0, 3, 4, 4, 1, 7, 5, 5, 3, 0])"
]
},
- "execution_count": 186,
+ "execution_count": 184,
"metadata": {},
"output_type": "execute_result"
}
@@ -6061,7 +6041,7 @@
},
{
"cell_type": "code",
- "execution_count": 188,
+ "execution_count": 186,
"id": "d98f88cc-c435-43fc-bcb5-52e6dd70fdb1",
"metadata": {},
"outputs": [],
@@ -6096,7 +6076,7 @@
},
{
"cell_type": "code",
- "execution_count": 190,
+ "execution_count": 188,
"id": "860f24e5-92ad-4361-8920-102ebc573598",
"metadata": {},
"outputs": [
@@ -6106,7 +6086,7 @@
"Puzzle 17.1: .000 seconds, answer 2,1,0,1,7,2,5,0,3 ok"
]
},
- "execution_count": 190,
+ "execution_count": 188,
"metadata": {},
"output_type": "execute_result"
}
@@ -6150,7 +6130,7 @@
},
{
"cell_type": "code",
- "execution_count": 192,
+ "execution_count": 190,
"id": "bb745303-dd20-486f-bbdd-7ae77f995c2c",
"metadata": {},
"outputs": [],
@@ -6162,7 +6142,7 @@
},
{
"cell_type": "code",
- "execution_count": 193,
+ "execution_count": 191,
"id": "54ac9b9c-70d9-4356-91c5-40fb285634b4",
"metadata": {},
"outputs": [
@@ -6172,7 +6152,7 @@
"[2, 4, 1, 7, 7, 5, 0, 3, 4, 4, 1, 7, 5, 5, 3, 0]"
]
},
- "execution_count": 193,
+ "execution_count": 191,
"metadata": {},
"output_type": "execute_result"
}
@@ -6183,7 +6163,7 @@
},
{
"cell_type": "code",
- "execution_count": 194,
+ "execution_count": 192,
"id": "36d89d9a-c8fc-41be-820b-cb13e40793c0",
"metadata": {},
"outputs": [
@@ -6193,7 +6173,7 @@
"[0]"
]
},
- "execution_count": 194,
+ "execution_count": 192,
"metadata": {},
"output_type": "execute_result"
}
@@ -6204,7 +6184,7 @@
},
{
"cell_type": "code",
- "execution_count": 195,
+ "execution_count": 193,
"id": "892fef38-5f9b-4370-a242-f7a10df5487b",
"metadata": {},
"outputs": [
@@ -6214,7 +6194,7 @@
"[3, 0]"
]
},
- "execution_count": 195,
+ "execution_count": 193,
"metadata": {},
"output_type": "execute_result"
}
@@ -6225,7 +6205,7 @@
},
{
"cell_type": "code",
- "execution_count": 196,
+ "execution_count": 194,
"id": "b3d11d5e-30c2-419f-bc11-3f26fbdddfbb",
"metadata": {},
"outputs": [
@@ -6235,7 +6215,7 @@
"[5, 3, 0]"
]
},
- "execution_count": 196,
+ "execution_count": 194,
"metadata": {},
"output_type": "execute_result"
}
@@ -6246,7 +6226,7 @@
},
{
"cell_type": "code",
- "execution_count": 197,
+ "execution_count": 195,
"id": "9ffcefa7-714f-416f-b6c7-8a9ad6d65380",
"metadata": {},
"outputs": [
@@ -6256,7 +6236,7 @@
"[5, 5, 3, 0]"
]
},
- "execution_count": 197,
+ "execution_count": 195,
"metadata": {},
"output_type": "execute_result"
}
@@ -6284,7 +6264,7 @@
},
{
"cell_type": "code",
- "execution_count": 199,
+ "execution_count": 197,
"id": "a49c6de9-4e6b-47e5-bcf0-2972a95c1af3",
"metadata": {},
"outputs": [
@@ -6294,7 +6274,7 @@
"Puzzle 17.2: .004 seconds, answer 267265166222235 ok"
]
},
- "execution_count": 199,
+ "execution_count": 197,
"metadata": {},
"output_type": "execute_result"
}
@@ -6325,7 +6305,7 @@
},
{
"cell_type": "code",
- "execution_count": 201,
+ "execution_count": 199,
"id": "d14e1966-2feb-4553-9a0a-12595ef4f7d7",
"metadata": {},
"outputs": [
@@ -6380,7 +6360,7 @@
},
{
"cell_type": "code",
- "execution_count": 203,
+ "execution_count": 201,
"id": "83af4751-38c9-4830-a2fa-78515b59bc97",
"metadata": {},
"outputs": [],
@@ -6395,7 +6375,7 @@
},
{
"cell_type": "code",
- "execution_count": 204,
+ "execution_count": 202,
"id": "29da25e2-f3c2-43e3-8769-1d4fcecb807b",
"metadata": {},
"outputs": [
@@ -6405,7 +6385,7 @@
"Puzzle 18.1: .014 seconds, answer 344 ok"
]
},
- "execution_count": 204,
+ "execution_count": 202,
"metadata": {},
"output_type": "execute_result"
}
@@ -6429,7 +6409,7 @@
},
{
"cell_type": "code",
- "execution_count": 206,
+ "execution_count": 204,
"id": "4c0a8dcb-c3af-45e7-9273-8776e8c3ea1d",
"metadata": {},
"outputs": [],
@@ -6450,17 +6430,17 @@
},
{
"cell_type": "code",
- "execution_count": 207,
+ "execution_count": 205,
"id": "22371144-5d51-440a-918f-a63de73b13ad",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "Puzzle 18.2: .033 seconds, answer 46,18 ok"
+ "Puzzle 18.2: .032 seconds, answer 46,18 ok"
]
},
- "execution_count": 207,
+ "execution_count": 205,
"metadata": {},
"output_type": "execute_result"
}
@@ -6502,7 +6482,7 @@
},
{
"cell_type": "code",
- "execution_count": 210,
+ "execution_count": 208,
"id": "689df92b-92d7-44e6-8b4e-d67bf3f153df",
"metadata": {},
"outputs": [
@@ -6546,7 +6526,7 @@
},
{
"cell_type": "code",
- "execution_count": 212,
+ "execution_count": 210,
"id": "e0b96545-5f60-4c8e-9a0f-c77608c19128",
"metadata": {},
"outputs": [],
@@ -6560,7 +6540,7 @@
},
{
"cell_type": "code",
- "execution_count": 213,
+ "execution_count": 211,
"id": "3c3fba1b-d3e5-494e-aad0-42ca0566ae1f",
"metadata": {},
"outputs": [
@@ -6570,7 +6550,7 @@
"Puzzle 19.1: .040 seconds, answer 242 ok"
]
},
- "execution_count": 213,
+ "execution_count": 211,
"metadata": {},
"output_type": "execute_result"
}
@@ -6592,7 +6572,7 @@
},
{
"cell_type": "code",
- "execution_count": 215,
+ "execution_count": 213,
"id": "77d4fae1-d506-4733-9bb2-467619012f97",
"metadata": {},
"outputs": [],
@@ -6607,17 +6587,17 @@
},
{
"cell_type": "code",
- "execution_count": 216,
+ "execution_count": 214,
"id": "14116eca-0b0f-484a-a169-9726e4ac7fbf",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "Puzzle 19.2: .189 seconds, answer 595975512785325 ok"
+ "Puzzle 19.2: .186 seconds, answer 595975512785325 ok"
]
},
- "execution_count": 216,
+ "execution_count": 214,
"metadata": {},
"output_type": "execute_result"
}
@@ -6637,7 +6617,7 @@
},
{
"cell_type": "code",
- "execution_count": 218,
+ "execution_count": 216,
"id": "f992b197-be14-47dc-8678-10cc63a1afd7",
"metadata": {},
"outputs": [],
@@ -6656,7 +6636,7 @@
},
{
"cell_type": "code",
- "execution_count": 220,
+ "execution_count": 218,
"id": "2437ae06-27e4-4840-ad51-65454ef0bf60",
"metadata": {},
"outputs": [],
@@ -6669,7 +6649,7 @@
},
{
"cell_type": "code",
- "execution_count": 221,
+ "execution_count": 219,
"id": "88e45604-ce45-478e-a1b8-66ead1d0e72e",
"metadata": {},
"outputs": [
@@ -6679,7 +6659,7 @@
"Puzzle 19.1: .004 seconds, answer 242 ok"
]
},
- "execution_count": 221,
+ "execution_count": 219,
"metadata": {},
"output_type": "execute_result"
}
@@ -6701,7 +6681,7 @@
},
{
"cell_type": "code",
- "execution_count": 223,
+ "execution_count": 221,
"id": "156dcbf7-79ec-41a7-a9f2-397a827b9856",
"metadata": {},
"outputs": [
@@ -6744,7 +6724,7 @@
},
{
"cell_type": "code",
- "execution_count": 225,
+ "execution_count": 223,
"id": "4c4ef05c-b548-49f9-b092-847e9752e745",
"metadata": {},
"outputs": [],
@@ -6775,17 +6755,17 @@
},
{
"cell_type": "code",
- "execution_count": 226,
+ "execution_count": 224,
"id": "1bbd8b72-c503-4384-aaea-a5bed45a4491",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "Puzzle 20.1: .028 seconds, answer 1343 ok"
+ "Puzzle 20.1: .029 seconds, answer 1343 ok"
]
},
- "execution_count": 226,
+ "execution_count": 224,
"metadata": {},
"output_type": "execute_result"
}
@@ -6812,17 +6792,17 @@
},
{
"cell_type": "code",
- "execution_count": 228,
+ "execution_count": 226,
"id": "d370e24c-9b82-4415-82a5-7afe2be17654",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "Puzzle 20.2: .773 seconds, answer 982891 ok"
+ "Puzzle 20.2: .761 seconds, answer 982891 ok"
]
},
- "execution_count": 228,
+ "execution_count": 226,
"metadata": {},
"output_type": "execute_result"
}
@@ -6858,7 +6838,7 @@
},
{
"cell_type": "code",
- "execution_count": 230,
+ "execution_count": 228,
"id": "332e9c72-db9a-4b90-a649-45f7bf955e84",
"metadata": {},
"outputs": [
@@ -6868,7 +6848,7 @@
"Puzzle 20.1: .023 seconds, answer 1343 ok"
]
},
- "execution_count": 230,
+ "execution_count": 228,
"metadata": {},
"output_type": "execute_result"
}
@@ -6890,7 +6870,7 @@
},
{
"cell_type": "code",
- "execution_count": 232,
+ "execution_count": 230,
"id": "9d0eea9f-9d8f-4410-97ec-13d8b136925b",
"metadata": {},
"outputs": [
@@ -6964,7 +6944,7 @@
},
{
"cell_type": "code",
- "execution_count": 234,
+ "execution_count": 232,
"id": "779c6b4c-ceb0-49ac-96f2-4700835c70ea",
"metadata": {},
"outputs": [],
@@ -6990,7 +6970,7 @@
},
{
"cell_type": "code",
- "execution_count": 236,
+ "execution_count": 234,
"id": "c915ada2-9dfe-42fe-bd08-855ff5d0e837",
"metadata": {},
"outputs": [],
@@ -7019,7 +6999,7 @@
},
{
"cell_type": "code",
- "execution_count": 238,
+ "execution_count": 236,
"id": "391f6120-6373-43f2-b697-585c90e45e54",
"metadata": {},
"outputs": [],
@@ -7039,7 +7019,7 @@
},
{
"cell_type": "code",
- "execution_count": 240,
+ "execution_count": 238,
"id": "1e2e8c59-744f-4f36-9251-c8ea5fd60aed",
"metadata": {},
"outputs": [],
@@ -7059,7 +7039,7 @@
},
{
"cell_type": "code",
- "execution_count": 242,
+ "execution_count": 240,
"id": "980572de-2589-4ada-a2a1-6c17cc627353",
"metadata": {},
"outputs": [],
@@ -7096,7 +7076,7 @@
},
{
"cell_type": "code",
- "execution_count": 244,
+ "execution_count": 242,
"id": "393a8c6b-6a1c-4495-aad5-92f48711fbf1",
"metadata": {},
"outputs": [
@@ -7106,7 +7086,7 @@
"Puzzle 21.1: .000 seconds, answer 205160 ok"
]
},
- "execution_count": 244,
+ "execution_count": 242,
"metadata": {},
"output_type": "execute_result"
}
@@ -7126,7 +7106,7 @@
},
{
"cell_type": "code",
- "execution_count": 246,
+ "execution_count": 244,
"id": "4d8c8659-52d3-4349-8465-7003e880502f",
"metadata": {},
"outputs": [],
@@ -7143,7 +7123,7 @@
"id": "08d46094-0ebf-4c84-8ec4-b563630b2458",
"metadata": {},
"source": [
- "I was encountering other **bugs** (off-by-one errors, maybe?), so I wrote some code that explicitly built a cache of path lengths. Once I did that I understood the puzzle better and was able to easily write the code above with the cache handled by the decorator, which is a little cleaner."
+ "I was encountering other **bugs** (off-by-one errors, maybe?), so I wrote some code that explicitly built a cache of path lengths. Once I did that I understood the puzzle better and was able to easily write the code above with the cache handled by the decorator, which I think is neater."
]
},
{
@@ -7158,7 +7138,7 @@
},
{
"cell_type": "code",
- "execution_count": 249,
+ "execution_count": 247,
"id": "563c5959-692d-4368-8c0b-469fa0142678",
"metadata": {},
"outputs": [
@@ -7168,7 +7148,7 @@
"Puzzle 21.2: .004 seconds, answer 252473394928452 ok"
]
},
- "execution_count": 249,
+ "execution_count": 247,
"metadata": {},
"output_type": "execute_result"
}
@@ -7188,7 +7168,7 @@
},
{
"cell_type": "code",
- "execution_count": 251,
+ "execution_count": 249,
"id": "f2d29a66-5420-4fc1-8586-1570ed5ac0a8",
"metadata": {},
"outputs": [
@@ -7198,7 +7178,7 @@
"439646398242"
]
},
- "execution_count": 251,
+ "execution_count": 249,
"metadata": {},
"output_type": "execute_result"
}
@@ -7227,7 +7207,7 @@
},
{
"cell_type": "code",
- "execution_count": 254,
+ "execution_count": 252,
"id": "2c1e7612-4ec5-4ce1-b591-5c3a14f8ea61",
"metadata": {},
"outputs": [
@@ -7278,7 +7258,7 @@
},
{
"cell_type": "code",
- "execution_count": 256,
+ "execution_count": 254,
"id": "3807adbc-261a-4108-88ba-6e2b061526b5",
"metadata": {},
"outputs": [],
@@ -7294,17 +7274,17 @@
},
{
"cell_type": "code",
- "execution_count": 257,
+ "execution_count": 255,
"id": "fce754cd-f6da-4e7d-b406-3314c9c28ca8",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "Puzzle 22.1: .325 seconds, answer 14273043166 ok"
+ "Puzzle 22.1: .318 seconds, answer 14273043166 ok"
]
},
- "execution_count": 257,
+ "execution_count": 255,
"metadata": {},
"output_type": "execute_result"
}
@@ -7333,26 +7313,24 @@
"\n",
"Our task is to get the most possible bananas under these constraints. \n",
"\n",
- "Can we brute-force it? Each delta is between -9 and +9, so the number of possible 4-tuples of deltas is 194 or about 100,000; a small number. However, if for each possible 4-tuple of deltas I looked at all 2000 steps of all 1685 monkeys, then 194 ✖️ 2000 ✖️ 1685 is more than 400 billion, which is a medium-large number. So instead I'll do this:\n",
+ "Can we brute-force it? Each delta is between -9 and +9, so the number of possible 4-tuples of deltas is fairly small, less than 105 (5 digits give you all the 4-deltas, but some are duplicates). However, if for each possible 4-tuple of deltas I looked at all 2000 steps of all 1685 monkeys, then 105 ✖️ 2000 ✖️ 1685 is more than 300 billion, which is a medium-large number. So instead I'll do define `total_bananas` to do this:\n",
"\n",
+ " Maintain a dict of {4-tuple: total bananas gained}, initially empty\n",
" For each monkey:\n",
- " For each 4-tuple of price deltas in the monkey's price timeline:\n",
- " If this is the first time this 4-tuple appeared in this monkey's timeline:\n",
- " then increment the total number of bananas for this 4-tuple by the current price\n",
- " Finally, take the maximum of the numbers of bananas, across all the recorded 4-tuples\n",
+ " For each unique 4-tuple of price deltas in the monkey's price timeline:\n",
+ " increment the total number of bananas for this 4-tuple by the current price\n",
+ "\n",
+ "I'll also define `price_timeline` to give the timeline for one monkey, making sure to only include the first time each 4-tuple appears. Finally, take the maximum of the numbers of bananas, across all the recorded 4-tuples.\n",
"\n",
"Some details:\n",
"- A `defaultdict(int)` is a great data structure for the 4-tuple to bananas mapping (a `Counter` is also good).\n",
- "- A `deque` with `maxlen=4` is a good data structure for keeping the evolving 4-tuple; just append to the deque and it drops old deltas.\n",
- "- I now call `nth_secret(secret, 1)`, so I wish I had made a separate `next_secret` function in Part 1; it would probably speed things up by a percent or two.\n",
- "- `price_timeline` returns a dict of `{delta-4-tuple: price}` for all the first appearances of a 4-tuple in a given monkey's timeline.\n",
- "- `total_bananas` returns a dict of `{delta-4-tuple: total_price}`, computing the total across all monkeys.\n",
- "- Then we just take the `max` of the `values` of the result of `total_bananas`."
+ "- A `deque` with `maxlen=4` is a good data structure for keeping the evolving 4-tuple; just append to the deque and it automatically drops old deltas.\n",
+ "- In `price_timeline` I call `nth_secret(secret, 1)`, so I wish I had made a separate `next_secret` function in Part 1; it would probably speed things up by a percent or two."
]
},
{
"cell_type": "code",
- "execution_count": 259,
+ "execution_count": 257,
"id": "cbbb4793-b13d-4a95-ba03-673b3ebaa229",
"metadata": {},
"outputs": [],
@@ -7385,17 +7363,17 @@
},
{
"cell_type": "code",
- "execution_count": 260,
+ "execution_count": 258,
"id": "34eaf7fe-fe9b-4858-b1e8-e4c3713ea093",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "Puzzle 22.2: 1.285 seconds, answer 1667 ok"
+ "Puzzle 22.2: 1.267 seconds, answer 1667 ok"
]
},
- "execution_count": 260,
+ "execution_count": 258,
"metadata": {},
"output_type": "execute_result"
}
@@ -7410,12 +7388,12 @@
"id": "bfc067a9-e6de-4390-bf78-3da283d68465",
"metadata": {},
"source": [
- "I'm surprised the answer is so low; less than one banana per monkey. And yet it is the correct answer. Let's investigate. First, what is the best 4-tuple of deltas?"
+ "I'm surprised the answer is so low; less than one banana per monkey. I would have guessed more like 4 per monkey. And yet it is the correct answer. Let's investigate. First, what is the best 4-tuple of deltas?"
]
},
{
"cell_type": "code",
- "execution_count": 262,
+ "execution_count": 260,
"id": "a2da8c78-d240-4c52-a83a-f3599f4f69a4",
"metadata": {},
"outputs": [
@@ -7425,7 +7403,7 @@
"(-3, 2, -1, 2)"
]
},
- "execution_count": 262,
+ "execution_count": 260,
"metadata": {},
"output_type": "execute_result"
}
@@ -7446,7 +7424,7 @@
},
{
"cell_type": "code",
- "execution_count": 264,
+ "execution_count": 262,
"id": "9de3f365-c546-494a-a18c-2ae58d88792b",
"metadata": {},
"outputs": [
@@ -7454,14 +7432,16 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "271 monkeys (16%), price 6.2 mean: {0: 0, 1: 0, 2: 0, 3: 43, 4: 34, 5: 33, 6: 32, 7: 37, 8: 42, 9: 50}\n"
+ "271 monkeys (16%) bought something for total price 1667, mean 6.2,\n",
+ "histogram: {0: 0, 1: 0, 2: 0, 3: 43, 4: 34, 5: 33, 6: 32, 7: 37, 8: 42, 9: 50}\n"
]
}
],
"source": [
"prices = [p for secret in secrets for d, p in price_timeline(secret).items() if d == best]\n",
"histo = {p: prices.count(p) for p in range(10)}\n",
- "print(f'{len(prices)} monkeys ({len(prices)/len(secrets):.0%}), price {mean(prices):3.1f} mean: {histo}')"
+ "print(f'{len(prices)} monkeys ({len(prices)/len(secrets):.0%}) bought something '\n",
+ " f'for total price {sum(prices)}, mean {mean(prices):3.1f},\\nhistogram: {histo}')"
]
},
{
@@ -7469,14 +7449,14 @@
"id": "7fac136e-b676-49c9-91f1-a209b9ef53fa",
"metadata": {},
"source": [
- "We do pretty well on prices, getting a lot of 8 and 9 prices, and nothing less than 3, but only 16% of monkeys every get this sequence of price deltas.\n",
+ "We do pretty well on prices, getting a lot of 8 and 9 prices, and nothing less than 3, but only 271 monkeys (16%) every get this sequence of price deltas.\n",
"\n",
"Do any 4-tuples show up in more timelines?"
]
},
{
"cell_type": "code",
- "execution_count": 266,
+ "execution_count": 264,
"id": "4fc191f9-62d8-47ef-a571-8c0541e25f4d",
"metadata": {},
"outputs": [
@@ -7495,13 +7475,13 @@
" ((1, -1, 0, 0), 292)]"
]
},
- "execution_count": 266,
+ "execution_count": 264,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "Counter(append(map(price_timeline, secrets))).most_common(10)"
+ "Counter(flatten(map(price_timeline, secrets))).most_common(10)"
]
},
{
@@ -7514,7 +7494,7 @@
},
{
"cell_type": "code",
- "execution_count": 268,
+ "execution_count": 266,
"id": "bbd329a0-309c-4c81-a780-6bd97a95f652",
"metadata": {},
"outputs": [
@@ -7524,7 +7504,7 @@
"1341"
]
},
- "execution_count": 268,
+ "execution_count": 266,
"metadata": {},
"output_type": "execute_result"
}
@@ -7533,14 +7513,109 @@
"bananas[(0, -1, 1, -1)]"
]
},
+ {
+ "cell_type": "markdown",
+ "id": "58c39447-f458-4254-bb4c-144effd3f23c",
+ "metadata": {},
+ "source": [
+ "I waas also curious about exactly how many *n*-tuples of deltas there are:"
+ ]
+ },
{
"cell_type": "code",
- "execution_count": 269,
- "id": "4a6a5116-2e01-46af-adf2-96ebd0a53e5f",
+ "execution_count": 268,
+ "id": "a2945c44-00f7-4c88-9b6e-747d9563034e",
"metadata": {},
"outputs": [],
"source": [
- "del bananas # clean up"
+ "def all_deltas(digits=range(10), n=4) -> Counter[Tuple[int, ...]]:\n",
+ " \"\"\"What `n`-tuples of deltas are possible for all sequences of `n`+1 `digits`,\n",
+ " and how many ways can each of them occur?\"\"\"\n",
+ " sequences = cross_product(digits, repeat=n+1)\n",
+ " return Counter(tuple(seq[i + 1] - seq[i] for i in range(n))\n",
+ " for seq in sequences)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4e8e0ea9-b617-43fc-83dc-767511ce63a6",
+ "metadata": {},
+ "source": [
+ "First a small example, with only two digits:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 270,
+ "id": "936bfa40-726a-4ddd-8033-8a50fa09b9ea",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Counter({(0, 0, 0): 2,\n",
+ " (0, 0, 1): 1,\n",
+ " (0, 1, -1): 1,\n",
+ " (0, 1, 0): 1,\n",
+ " (1, -1, 0): 1,\n",
+ " (1, -1, 1): 1,\n",
+ " (1, 0, -1): 1,\n",
+ " (1, 0, 0): 1,\n",
+ " (-1, 0, 0): 1,\n",
+ " (-1, 0, 1): 1,\n",
+ " (-1, 1, -1): 1,\n",
+ " (-1, 1, 0): 1,\n",
+ " (0, -1, 0): 1,\n",
+ " (0, -1, 1): 1,\n",
+ " (0, 0, -1): 1})"
+ ]
+ },
+ "execution_count": 270,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "all_deltas(digits=(0, 1), n=3)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "bf3f03a4-c9ea-4429-82a4-3f54b7846ce0",
+ "metadata": {},
+ "source": [
+ "With 2 digits there are 24 sequences of length 4 that make 24 - 1 unique delta 3-tuples, because the sequence (0, 0, 0, 0) and (1, 1, 1, 1) both yield the deltas (0, 0, 0). \n",
+ "\n",
+ "Now we try with 10 digits, for tuples of length 1 to 4:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 272,
+ "id": "2bb368b8-d5e7-431c-bd2c-19aa41983b8d",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{1: 19, 2: 271, 3: 3439, 4: 40951}"
+ ]
+ },
+ "execution_count": 272,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "{n: len(all_deltas(digits=range(10), n=n)) for n in range(1, 5)}"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "47add4c5-499a-4c6f-a148-74093a72e3c7",
+ "metadata": {},
+ "source": [
+ "This sequence of integers, 19, 271, 3439, 40951, [**appears**](https://oeis.org/search?q=+1%2C+19%2C+271%2C+3439%2C+40951&language=english&go=Search) in the Online Encyclopedia of Integer Sequences (OEIS), but it is not described as having anything to do with deltas, but rather as 10*n* - 9*n* ."
]
},
{
@@ -7555,7 +7630,7 @@
},
{
"cell_type": "code",
- "execution_count": 271,
+ "execution_count": 275,
"id": "85f5b145-8c5e-448c-8b45-ad5750252ff2",
"metadata": {},
"outputs": [
@@ -7601,17 +7676,17 @@
"source": [
"### Part 1: Find all the sets of three inter-connected computers. How many contain at least one computer with a name that starts with t?\n",
"\n",
- "We're asked to find three inter-connected computers, e.g., three computers A, B, C, such that A-B, B-C, and C-A are all in the list of connections (but connections are bidirectional, so either A-B or B-A could be in the input). A set where every node is connected to every other is called a **clique**. I'll represent the network **graph** as a dict of the form `{A: {B, C}}` to denote that node `A` is connected to `B` and `C`. The function `bidrected_graph` forms a graph from an iterable of (A, B) connections. Then `triples_starting_with` finds all cliques of size 3, where at least one of them starts with the given letter. The answer for Part 1 is then the number of triples that start with `t`."
+ "We're asked to find three inter-connected computers, e.g., three computers A, B, C, such that A-B, B-C, and C-A are all in the list of connections (but connections are bidirectional, so either A-B or B-A could be in the input). A set where every node is connected to every other is called a **clique**. I'll represent the network **graph** as a dict of the form `{A: {B, C}}` to denote that node `A` is connected to `B` and `C`. The function `bidrected_graph` forms a graph from an iterable of (A, B) connections. Then `triples_starting_with` finds all cliques of size 3, where at least one of them starts with the given letter. The procedure could find duplicates (e.g. both (A, B, C) and (C, B, A), so I represent each triple as a frozenset and eliminate duplicates by returning the set of them. The answer for Part 1 is then the number of triples that start with `t`."
]
},
{
"cell_type": "code",
- "execution_count": 273,
+ "execution_count": 277,
"id": "289d2325-1e58-41f5-b4b2-b90ae26e7887",
"metadata": {},
"outputs": [],
"source": [
- "Clique = set\n",
+ "Clique = set # A clique is a set of nodes\n",
"\n",
"def bidirected_graph(connections) -> dict:\n",
" \"\"\"A graph where, e.g., {A: {B, C}} means A is connected to B and C.\"\"\"\n",
@@ -7631,7 +7706,7 @@
},
{
"cell_type": "code",
- "execution_count": 274,
+ "execution_count": 278,
"id": "6425577d-4ca9-45de-9698-cd9b026f7ce6",
"metadata": {},
"outputs": [
@@ -7641,7 +7716,7 @@
"Puzzle 23.1: .001 seconds, answer 1170 ok"
]
},
- "execution_count": 274,
+ "execution_count": 278,
"metadata": {},
"output_type": "execute_result"
}
@@ -7663,7 +7738,7 @@
},
{
"cell_type": "code",
- "execution_count": 276,
+ "execution_count": 280,
"id": "88811073-22b2-4378-afa5-9d38462c63b5",
"metadata": {},
"outputs": [],
@@ -7685,17 +7760,17 @@
},
{
"cell_type": "code",
- "execution_count": 277,
+ "execution_count": 281,
"id": "0b5f08ac-18e2-4933-9737-cdbc842c5809",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "Puzzle 23.2: .003 seconds, answer bo,dd,eq,ik,lo,lu,ph,ro,rr,rw,uo,wx,yg ok"
+ "Puzzle 23.2: .004 seconds, answer bo,dd,eq,ik,lo,lu,ph,ro,rr,rw,uo,wx,yg ok"
]
},
- "execution_count": 277,
+ "execution_count": 281,
"metadata": {},
"output_type": "execute_result"
}
@@ -7735,7 +7810,7 @@
},
{
"cell_type": "code",
- "execution_count": 280,
+ "execution_count": 284,
"id": "47421581-71df-4c72-a62e-c40d0596fdbb",
"metadata": {},
"outputs": [
@@ -7786,7 +7861,7 @@
},
{
"cell_type": "code",
- "execution_count": 282,
+ "execution_count": 286,
"id": "43b29260-d912-4cfc-91ce-d303ec1c86df",
"metadata": {},
"outputs": [],
@@ -7812,7 +7887,7 @@
},
{
"cell_type": "code",
- "execution_count": 284,
+ "execution_count": 288,
"id": "a9a4780f-6033-452f-b49c-74b97c9e2440",
"metadata": {},
"outputs": [],
@@ -7834,7 +7909,7 @@
},
{
"cell_type": "code",
- "execution_count": 285,
+ "execution_count": 289,
"id": "72437439-dddf-4202-9944-36e796800304",
"metadata": {},
"outputs": [
@@ -7844,7 +7919,7 @@
"Puzzle 24.1: .001 seconds, answer 36035961805936 ok"
]
},
- "execution_count": 285,
+ "execution_count": 289,
"metadata": {},
"output_type": "execute_result"
}
@@ -7877,7 +7952,7 @@
"\n",
"I have four ideas of how to proceed, none of them completely compelling:\n",
"1) Plot the circuit diagram and see if anythng looks funny.\n",
- " - Making a nice plot would be hard; I'm worried that wires in a circuit diagram cross each other; that seems hard to do cleanly.\n",
+ " - Making a nice plot would be hard; I'm worried that wires in a circuit diagram cross each other; that could get messy.\n",
"2) Examine the structure of the device and look for something that breaks the pattern.\n",
" - This might help me, as a detective, uncover the answer, but if I was given another input device I'd have to start all over.\n",
"3) Choose `x` and `y` numbers as input, run the simulation, and compare the resulting `z` values to the correct answer.\n",
@@ -7900,7 +7975,7 @@
},
{
"cell_type": "code",
- "execution_count": 289,
+ "execution_count": 293,
"id": "9021ad30-f505-4164-9feb-5af740632182",
"metadata": {},
"outputs": [
@@ -7955,15 +8030,15 @@
" 'z00': ('x00', 'XOR', 'y00')}"
]
},
- "execution_count": 289,
+ "execution_count": 293,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "D = Device(connections)\n",
- "zs = wires(D, 'z')\n",
- "{z: D[z] for z in zs}"
+ "device = Device(connections)\n",
+ "zs = wires(device, 'z')\n",
+ "{z: device[z] for z in zs}"
]
},
{
@@ -7986,7 +8061,7 @@
},
{
"cell_type": "code",
- "execution_count": 291,
+ "execution_count": 295,
"id": "3b41a166-d33b-402b-971b-1dc1d33135ec",
"metadata": {},
"outputs": [
@@ -7996,13 +8071,13 @@
"Counter({'AND': 89, 'XOR': 89, 'OR': 44})"
]
},
- "execution_count": 291,
+ "execution_count": 295,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "Counter(val[1] for val in Device(connections).values() if val not in (0, 1))"
+ "Counter(val[1] for val in device.values() if val not in (0, 1))"
]
},
{
@@ -8017,7 +8092,7 @@
},
{
"cell_type": "code",
- "execution_count": 293,
+ "execution_count": 297,
"id": "ec8d86d4-8caf-40f2-b516-c7da4acbda19",
"metadata": {},
"outputs": [],
@@ -8053,7 +8128,7 @@
},
{
"cell_type": "code",
- "execution_count": 295,
+ "execution_count": 299,
"id": "7ed8f8e6-c3e1-4c22-b812-e1a201afec3d",
"metadata": {},
"outputs": [],
@@ -8091,7 +8166,7 @@
},
{
"cell_type": "code",
- "execution_count": 296,
+ "execution_count": 300,
"id": "e9b87c38-f67c-4948-9af6-251021747e9d",
"metadata": {},
"outputs": [
@@ -8101,7 +8176,7 @@
"Puzzle 24.2: .000 seconds, answer jqf,mdd,skh,wpd,wts,z11,z19,z37 ok"
]
},
- "execution_count": 296,
+ "execution_count": 300,
"metadata": {},
"output_type": "execute_result"
}
@@ -8125,7 +8200,7 @@
},
{
"cell_type": "code",
- "execution_count": 298,
+ "execution_count": 302,
"id": "f5971853-7139-4f17-bdc5-6c51e12a928d",
"metadata": {},
"outputs": [
@@ -8193,7 +8268,7 @@
},
{
"cell_type": "code",
- "execution_count": 300,
+ "execution_count": 304,
"id": "5302ac58-91fc-475a-83d9-cea91457df3b",
"metadata": {},
"outputs": [],
@@ -8215,17 +8290,17 @@
},
{
"cell_type": "code",
- "execution_count": 301,
+ "execution_count": 305,
"id": "89c28b74-ed31-4bb5-b463-7177952a95ae",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "Puzzle 25.1: .021 seconds, answer 3196 ok"
+ "Puzzle 25.1: .022 seconds, answer 3196 ok"
]
},
- "execution_count": 301,
+ "execution_count": 305,
"metadata": {},
"output_type": "execute_result"
}
@@ -8254,14 +8329,14 @@
"source": [
"# Summary\n",
"\n",
- "Here are all the puzzle answers and timings. I got all the puzzles right! And I did it before midnight (my time) on December 25th, a rarity for me. \n",
+ "Here are all the puzzle answers and timings. I got all the puzzles correct! And I did it before midnight (my time) on December 25th, a rarity for me. \n",
"\n",
"The median run time is about 5 milliseconds, with 4 puzzles taking over a second. I didn't count the time that `parse` takes, but that is less than a millisecond per day."
]
},
{
"cell_type": "code",
- "execution_count": 304,
+ "execution_count": 308,
"id": "34813fc9-a000-4cd8-88ae-692851b3242c",
"metadata": {},
"outputs": [
@@ -8275,53 +8350,53 @@
"Puzzle 2.2: .002 seconds, answer 328 ok\n",
"Puzzle 3.1: .001 seconds, answer 156388521 ok\n",
"Puzzle 3.2: .000 seconds, answer 75920122 ok\n",
- "Puzzle 4.1: .020 seconds, answer 2401 ok\n",
- "Puzzle 4.2: .016 seconds, answer 1822 ok\n",
+ "Puzzle 4.1: .021 seconds, answer 2401 ok\n",
+ "Puzzle 4.2: .015 seconds, answer 1822 ok\n",
"Puzzle 5.1: .001 seconds, answer 5762 ok\n",
"Puzzle 5.2: .001 seconds, answer 4130 ok\n",
- "Puzzle 6.1: .001 seconds, answer 5329 ok\n",
- "Puzzle 6.2: 1.998 seconds, answer 2162 ok\n",
+ "Puzzle 6.1: .002 seconds, answer 5329 ok\n",
+ "Puzzle 6.2: 1.943 seconds, answer 2162 ok\n",
"Puzzle 7.1: .014 seconds, answer 1985268524462 ok\n",
- "Puzzle 7.2: .606 seconds, answer 150077710195188 ok\n",
- "Puzzle 8.1: .002 seconds, answer 220 ok\n",
+ "Puzzle 7.2: .592 seconds, answer 150077710195188 ok\n",
+ "Puzzle 8.1: .003 seconds, answer 220 ok\n",
"Puzzle 8.2: .003 seconds, answer 813 ok\n",
- "Puzzle 9.1: .020 seconds, answer 6332189866718 ok\n",
- "Puzzle 9.2: 2.428 seconds, answer 6353648390778 ok\n",
+ "Puzzle 9.1: .019 seconds, answer 6332189866718 ok\n",
+ "Puzzle 9.2: 2.384 seconds, answer 6353648390778 ok\n",
"Puzzle 10.1: .005 seconds, answer 744 ok\n",
"Puzzle 10.2: .006 seconds, answer 1651 ok\n",
"Puzzle 11.1: .001 seconds, answer 194482 ok\n",
- "Puzzle 11.2: .061 seconds, answer 232454623677743 ok\n",
- "Puzzle 12.1: .030 seconds, answer 1402544 ok\n",
- "Puzzle 12.2: .061 seconds, answer 862486 ok\n",
+ "Puzzle 11.2: .060 seconds, answer 232454623677743 ok\n",
+ "Puzzle 12.1: .050 seconds, answer 1402544 ok\n",
+ "Puzzle 12.2: .042 seconds, answer 862486 ok\n",
"Puzzle 13.1: .000 seconds, answer 29598 ok\n",
"Puzzle 13.2: .000 seconds, answer 93217456941970 ok\n",
"Puzzle 14.1: .000 seconds, answer 216027840 ok\n",
- "Puzzle 14.2: 1.874 seconds, answer 6876 ok\n",
+ "Puzzle 14.2: 1.828 seconds, answer 6876 ok\n",
"Puzzle 15.1: .029 seconds, answer 1563092 ok\n",
"Puzzle 15.2: .042 seconds, answer 1582688 ok\n",
"Puzzle 16.1: .146 seconds, answer 103512 ok\n",
- "Puzzle 16.2: .863 seconds, answer 554 ok\n",
+ "Puzzle 16.2: .848 seconds, answer 554 ok\n",
"Puzzle 17.1: .000 seconds, answer 2,1,0,1,7,2,5,0,3 ok\n",
"Puzzle 17.2: .004 seconds, answer 267265166222235 ok\n",
"Puzzle 18.1: .014 seconds, answer 344 ok\n",
- "Puzzle 18.2: .033 seconds, answer 46,18 ok\n",
+ "Puzzle 18.2: .032 seconds, answer 46,18 ok\n",
"Puzzle 19.1: .004 seconds, answer 242 ok\n",
- "Puzzle 19.2: .189 seconds, answer 595975512785325 ok\n",
+ "Puzzle 19.2: .186 seconds, answer 595975512785325 ok\n",
"Puzzle 20.1: .023 seconds, answer 1343 ok\n",
- "Puzzle 20.2: .773 seconds, answer 982891 ok\n",
+ "Puzzle 20.2: .761 seconds, answer 982891 ok\n",
"Puzzle 21.1: .000 seconds, answer 205160 ok\n",
"Puzzle 21.2: .004 seconds, answer 252473394928452 ok\n",
- "Puzzle 22.1: .325 seconds, answer 14273043166 ok\n",
- "Puzzle 22.2: 1.285 seconds, answer 1667 ok\n",
+ "Puzzle 22.1: .318 seconds, answer 14273043166 ok\n",
+ "Puzzle 22.2: 1.267 seconds, answer 1667 ok\n",
"Puzzle 23.1: .001 seconds, answer 1170 ok\n",
- "Puzzle 23.2: .003 seconds, answer bo,dd,eq,ik,lo,lu,ph,ro,rr,rw,uo,wx,yg ok\n",
+ "Puzzle 23.2: .004 seconds, answer bo,dd,eq,ik,lo,lu,ph,ro,rr,rw,uo,wx,yg ok\n",
"Puzzle 24.1: .001 seconds, answer 36035961805936 ok\n",
"Puzzle 24.2: .000 seconds, answer jqf,mdd,skh,wpd,wts,z11,z19,z37 ok\n",
- "Puzzle 25.1: .021 seconds, answer 3196 ok\n",
+ "Puzzle 25.1: .022 seconds, answer 3196 ok\n",
"\n",
"Correct: 49/49\n",
"\n",
- "Time in seconds: 0.005 median, 0.223 mean, 10.914 total.\n"
+ "Time in seconds: 0.005 median, 0.218 mean, 10.699 total.\n"
]
}
],