Add files via upload

This commit is contained in:
Peter Norvig 2024-12-28 14:16:19 -08:00 committed by GitHub
parent ab0d5e1845
commit 9a4949ee01
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -670,7 +670,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"Puzzle 4.2: .015 seconds, answer 1822 ok" "Puzzle 4.2: .016 seconds, answer 1822 ok"
] ]
}, },
"execution_count": 42, "execution_count": 42,
@ -1063,7 +1063,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"Puzzle 6.2: 1.943 seconds, answer 2162 ok" "Puzzle 6.2: 1.977 seconds, answer 2162 ok"
] ]
}, },
"execution_count": 63, "execution_count": 63,
@ -1308,7 +1308,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"Puzzle 7.2: .592 seconds, answer 150077710195188 ok" "Puzzle 7.2: .600 seconds, answer 150077710195188 ok"
] ]
}, },
"execution_count": 78, "execution_count": 78,
@ -1603,7 +1603,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"Puzzle 9.1: .019 seconds, answer 6332189866718 ok" "Puzzle 9.1: .020 seconds, answer 6332189866718 ok"
] ]
}, },
"execution_count": 93, "execution_count": 93,
@ -1629,21 +1629,22 @@
"\n", "\n",
"To find all the slices that indicate files, it is easier to run through the disk map than the disk layout. The function `file_slices` quickly finds all such slices.\n", "To find all the slices that indicate files, it is easier to run through the disk map than the disk layout. The function `file_slices` quickly finds all such slices.\n",
"\n", "\n",
"Finding a free space for a file is more difficult, because we need to find one that is big enough. I'll run through the whole layout from left-to-right each time. This will make it *O*(*n*<sup>2</sup>) rather than *O*(*n*), but hopefully it won't be too slow. (If I wanted to speed it up I could have an array of starting positions for each desired size of free space.)" "Finding a free space for a file is more difficult, because we need to find one that is big enough. At first I coded a solution that ran through the whole layout from left-to-right each time. That made it *O*(*n*<sup>2</sup>). So I added a table: `starts[length]` tells me where to start looking for an empty space of size `length`. That speeds things up."
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 95, "execution_count": 95,
"id": "fcf4d832-3d7d-4987-aa57-e6e0f1df16bf", "id": "8d34e96a-8ea9-4f92-b0aa-839b216ea14b",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"def compress_layout2(disk_map: Ints) -> list:\n", "def compress_layout2(disk_map: Ints) -> list:\n",
" \"\"\"Mutate layout by moving files one at a time from the end to the leftmost free space.\"\"\"\n", " \"\"\"Mutate layout by moving files one at a time from the end to the leftmost free space.\"\"\"\n",
" layout = disk_layout(disk_map)\n", " layout = disk_layout(disk_map)\n",
" starts = defaultdict(int)\n",
" for file in file_slices(disk_map):\n", " for file in file_slices(disk_map):\n",
" if free := find_freespace(layout, file):\n", " if free := find_freespace(layout, file, starts):\n",
" layout[file], layout[free] = layout[free], layout[file]\n", " layout[file], layout[free] = layout[free], layout[file]\n",
" return layout\n", " return layout\n",
"\n", "\n",
@ -1658,11 +1659,12 @@
" slices.reverse()\n", " slices.reverse()\n",
" return slices\n", " return slices\n",
"\n", "\n",
"def find_freespace(layout, file_slice) -> Optional[slice]:\n", "def find_freespace(layout, file_slice, starts) -> Optional[slice]:\n",
" \"\"\"Find a slice position big enough to fit the given file slice, or return None if there is no position.\"\"\"\n", " \"\"\"Find a slice position big enough to fit the given file slice, or return None if there is no position.\"\"\"\n",
" length = file_slice.stop - file_slice.start\n", " length = file_slice.stop - file_slice.start\n",
" run = 0\n", " run = 0\n",
" for i in range(layout.index(empty), len(layout)):\n", " for i in range(layout.index(empty, starts[length]), len(layout)):\n",
" starts[length] = i\n",
" if i >= file_slice.start:\n", " if i >= file_slice.start:\n",
" return None # We only want to move a file left, not right\n", " return None # We only want to move a file left, not right\n",
" elif layout[i] is empty:\n", " elif layout[i] is empty:\n",
@ -1683,7 +1685,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"Puzzle 9.2: 2.384 seconds, answer 6353648390778 ok" "Puzzle 9.2: .021 seconds, answer 6353648390778 ok"
] ]
}, },
"execution_count": 96, "execution_count": 96,
@ -1792,7 +1794,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"Puzzle 10.1: .005 seconds, answer 744 ok" "Puzzle 10.1: .004 seconds, answer 744 ok"
] ]
}, },
"execution_count": 102, "execution_count": 102,
@ -1994,7 +1996,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"Puzzle 11.1: .067 seconds, answer 194482 ok" "Puzzle 11.1: .068 seconds, answer 194482 ok"
] ]
}, },
"execution_count": 113, "execution_count": 113,
@ -2055,7 +2057,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"Puzzle 11.1: .001 seconds, answer 194482 ok" "Puzzle 11.1: .002 seconds, answer 194482 ok"
] ]
}, },
"execution_count": 117, "execution_count": 117,
@ -2077,7 +2079,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"Puzzle 11.2: .060 seconds, answer 232454623677743 ok" "Puzzle 11.2: .058 seconds, answer 232454623677743 ok"
] ]
}, },
"execution_count": 118, "execution_count": 118,
@ -2213,7 +2215,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"Puzzle 12.1: .033 seconds, answer 1402544 ok" "Puzzle 12.1: .032 seconds, answer 1402544 ok"
] ]
}, },
"execution_count": 126, "execution_count": 126,
@ -2286,7 +2288,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"Puzzle 12.1: .050 seconds, answer 1402544 ok" "Puzzle 12.1: .052 seconds, answer 1402544 ok"
] ]
}, },
"execution_count": 129, "execution_count": 129,
@ -2308,7 +2310,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"Puzzle 12.2: .042 seconds, answer 862486 ok" "Puzzle 12.2: .043 seconds, answer 862486 ok"
] ]
}, },
"execution_count": 130, "execution_count": 130,
@ -2986,42 +2988,42 @@
"</style>\n", "</style>\n",
"\n", "\n",
"<div class=\"animation\">\n", "<div class=\"animation\">\n",
" <img id=\"_anim_imgdc0d5558c9a0485aa3c468981a103eb2\">\n", " <img id=\"_anim_imge5889f6e232a4cbba19719532f4cbcc2\">\n",
" <div class=\"anim-controls\">\n", " <div class=\"anim-controls\">\n",
" <input id=\"_anim_sliderdc0d5558c9a0485aa3c468981a103eb2\" type=\"range\" class=\"anim-slider\"\n", " <input id=\"_anim_slidere5889f6e232a4cbba19719532f4cbcc2\" type=\"range\" class=\"anim-slider\"\n",
" name=\"points\" min=\"0\" max=\"1\" step=\"1\" value=\"0\"\n", " name=\"points\" min=\"0\" max=\"1\" step=\"1\" value=\"0\"\n",
" oninput=\"animdc0d5558c9a0485aa3c468981a103eb2.set_frame(parseInt(this.value));\">\n", " oninput=\"anime5889f6e232a4cbba19719532f4cbcc2.set_frame(parseInt(this.value));\">\n",
" <div class=\"anim-buttons\">\n", " <div class=\"anim-buttons\">\n",
" <button title=\"Decrease speed\" aria-label=\"Decrease speed\" onclick=\"animdc0d5558c9a0485aa3c468981a103eb2.slower()\">\n", " <button title=\"Decrease speed\" aria-label=\"Decrease speed\" onclick=\"anime5889f6e232a4cbba19719532f4cbcc2.slower()\">\n",
" <i class=\"fa fa-minus\"></i></button>\n", " <i class=\"fa fa-minus\"></i></button>\n",
" <button title=\"First frame\" aria-label=\"First frame\" onclick=\"animdc0d5558c9a0485aa3c468981a103eb2.first_frame()\">\n", " <button title=\"First frame\" aria-label=\"First frame\" onclick=\"anime5889f6e232a4cbba19719532f4cbcc2.first_frame()\">\n",
" <i class=\"fa fa-fast-backward\"></i></button>\n", " <i class=\"fa fa-fast-backward\"></i></button>\n",
" <button title=\"Previous frame\" aria-label=\"Previous frame\" onclick=\"animdc0d5558c9a0485aa3c468981a103eb2.previous_frame()\">\n", " <button title=\"Previous frame\" aria-label=\"Previous frame\" onclick=\"anime5889f6e232a4cbba19719532f4cbcc2.previous_frame()\">\n",
" <i class=\"fa fa-step-backward\"></i></button>\n", " <i class=\"fa fa-step-backward\"></i></button>\n",
" <button title=\"Play backwards\" aria-label=\"Play backwards\" onclick=\"animdc0d5558c9a0485aa3c468981a103eb2.reverse_animation()\">\n", " <button title=\"Play backwards\" aria-label=\"Play backwards\" onclick=\"anime5889f6e232a4cbba19719532f4cbcc2.reverse_animation()\">\n",
" <i class=\"fa fa-play fa-flip-horizontal\"></i></button>\n", " <i class=\"fa fa-play fa-flip-horizontal\"></i></button>\n",
" <button title=\"Pause\" aria-label=\"Pause\" onclick=\"animdc0d5558c9a0485aa3c468981a103eb2.pause_animation()\">\n", " <button title=\"Pause\" aria-label=\"Pause\" onclick=\"anime5889f6e232a4cbba19719532f4cbcc2.pause_animation()\">\n",
" <i class=\"fa fa-pause\"></i></button>\n", " <i class=\"fa fa-pause\"></i></button>\n",
" <button title=\"Play\" aria-label=\"Play\" onclick=\"animdc0d5558c9a0485aa3c468981a103eb2.play_animation()\">\n", " <button title=\"Play\" aria-label=\"Play\" onclick=\"anime5889f6e232a4cbba19719532f4cbcc2.play_animation()\">\n",
" <i class=\"fa fa-play\"></i></button>\n", " <i class=\"fa fa-play\"></i></button>\n",
" <button title=\"Next frame\" aria-label=\"Next frame\" onclick=\"animdc0d5558c9a0485aa3c468981a103eb2.next_frame()\">\n", " <button title=\"Next frame\" aria-label=\"Next frame\" onclick=\"anime5889f6e232a4cbba19719532f4cbcc2.next_frame()\">\n",
" <i class=\"fa fa-step-forward\"></i></button>\n", " <i class=\"fa fa-step-forward\"></i></button>\n",
" <button title=\"Last frame\" aria-label=\"Last frame\" onclick=\"animdc0d5558c9a0485aa3c468981a103eb2.last_frame()\">\n", " <button title=\"Last frame\" aria-label=\"Last frame\" onclick=\"anime5889f6e232a4cbba19719532f4cbcc2.last_frame()\">\n",
" <i class=\"fa fa-fast-forward\"></i></button>\n", " <i class=\"fa fa-fast-forward\"></i></button>\n",
" <button title=\"Increase speed\" aria-label=\"Increase speed\" onclick=\"animdc0d5558c9a0485aa3c468981a103eb2.faster()\">\n", " <button title=\"Increase speed\" aria-label=\"Increase speed\" onclick=\"anime5889f6e232a4cbba19719532f4cbcc2.faster()\">\n",
" <i class=\"fa fa-plus\"></i></button>\n", " <i class=\"fa fa-plus\"></i></button>\n",
" </div>\n", " </div>\n",
" <form title=\"Repetition mode\" aria-label=\"Repetition mode\" action=\"#n\" name=\"_anim_loop_selectdc0d5558c9a0485aa3c468981a103eb2\"\n", " <form title=\"Repetition mode\" aria-label=\"Repetition mode\" action=\"#n\" name=\"_anim_loop_selecte5889f6e232a4cbba19719532f4cbcc2\"\n",
" class=\"anim-state\">\n", " class=\"anim-state\">\n",
" <input type=\"radio\" name=\"state\" value=\"once\" id=\"_anim_radio1_dc0d5558c9a0485aa3c468981a103eb2\"\n", " <input type=\"radio\" name=\"state\" value=\"once\" id=\"_anim_radio1_e5889f6e232a4cbba19719532f4cbcc2\"\n",
" >\n", " >\n",
" <label for=\"_anim_radio1_dc0d5558c9a0485aa3c468981a103eb2\">Once</label>\n", " <label for=\"_anim_radio1_e5889f6e232a4cbba19719532f4cbcc2\">Once</label>\n",
" <input type=\"radio\" name=\"state\" value=\"loop\" id=\"_anim_radio2_dc0d5558c9a0485aa3c468981a103eb2\"\n", " <input type=\"radio\" name=\"state\" value=\"loop\" id=\"_anim_radio2_e5889f6e232a4cbba19719532f4cbcc2\"\n",
" checked>\n", " checked>\n",
" <label for=\"_anim_radio2_dc0d5558c9a0485aa3c468981a103eb2\">Loop</label>\n", " <label for=\"_anim_radio2_e5889f6e232a4cbba19719532f4cbcc2\">Loop</label>\n",
" <input type=\"radio\" name=\"state\" value=\"reflect\" id=\"_anim_radio3_dc0d5558c9a0485aa3c468981a103eb2\"\n", " <input type=\"radio\" name=\"state\" value=\"reflect\" id=\"_anim_radio3_e5889f6e232a4cbba19719532f4cbcc2\"\n",
" >\n", " >\n",
" <label for=\"_anim_radio3_dc0d5558c9a0485aa3c468981a103eb2\">Reflect</label>\n", " <label for=\"_anim_radio3_e5889f6e232a4cbba19719532f4cbcc2\">Reflect</label>\n",
" </form>\n", " </form>\n",
" </div>\n", " </div>\n",
"</div>\n", "</div>\n",
@ -3031,9 +3033,9 @@
" /* Instantiate the Animation class. */\n", " /* Instantiate the Animation class. */\n",
" /* The IDs given should match those used in the template above. */\n", " /* The IDs given should match those used in the template above. */\n",
" (function() {\n", " (function() {\n",
" var img_id = \"_anim_imgdc0d5558c9a0485aa3c468981a103eb2\";\n", " var img_id = \"_anim_imge5889f6e232a4cbba19719532f4cbcc2\";\n",
" var slider_id = \"_anim_sliderdc0d5558c9a0485aa3c468981a103eb2\";\n", " var slider_id = \"_anim_slidere5889f6e232a4cbba19719532f4cbcc2\";\n",
" var loop_select_id = \"_anim_loop_selectdc0d5558c9a0485aa3c468981a103eb2\";\n", " var loop_select_id = \"_anim_loop_selecte5889f6e232a4cbba19719532f4cbcc2\";\n",
" var frames = new Array(3);\n", " var frames = new Array(3);\n",
" \n", " \n",
" frames[0] = \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90\\\n", " frames[0] = \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90\\\n",
@ -4770,14 +4772,14 @@
" /* set a timeout to make sure all the above elements are created before\n", " /* set a timeout to make sure all the above elements are created before\n",
" the object is initialized. */\n", " the object is initialized. */\n",
" setTimeout(function() {\n", " setTimeout(function() {\n",
" animdc0d5558c9a0485aa3c468981a103eb2 = new Animation(frames, img_id, slider_id, 200.0,\n", " anime5889f6e232a4cbba19719532f4cbcc2 = new Animation(frames, img_id, slider_id, 200.0,\n",
" loop_select_id);\n", " loop_select_id);\n",
" }, 0);\n", " }, 0);\n",
" })()\n", " })()\n",
"</script>\n" "</script>\n"
], ],
"text/plain": [ "text/plain": [
"<matplotlib.animation.FuncAnimation at 0x31c3b3f20>" "<matplotlib.animation.FuncAnimation at 0x31ce7ac00>"
] ]
}, },
"execution_count": 156, "execution_count": 156,
@ -5010,42 +5012,42 @@
"</style>\n", "</style>\n",
"\n", "\n",
"<div class=\"animation\">\n", "<div class=\"animation\">\n",
" <img id=\"_anim_imgea6b17f8e6f745568d5445b9aa800110\">\n", " <img id=\"_anim_img7295292aa9074d0193a9f80b1d46cca1\">\n",
" <div class=\"anim-controls\">\n", " <div class=\"anim-controls\">\n",
" <input id=\"_anim_sliderea6b17f8e6f745568d5445b9aa800110\" type=\"range\" class=\"anim-slider\"\n", " <input id=\"_anim_slider7295292aa9074d0193a9f80b1d46cca1\" type=\"range\" class=\"anim-slider\"\n",
" name=\"points\" min=\"0\" max=\"1\" step=\"1\" value=\"0\"\n", " name=\"points\" min=\"0\" max=\"1\" step=\"1\" value=\"0\"\n",
" oninput=\"animea6b17f8e6f745568d5445b9aa800110.set_frame(parseInt(this.value));\">\n", " oninput=\"anim7295292aa9074d0193a9f80b1d46cca1.set_frame(parseInt(this.value));\">\n",
" <div class=\"anim-buttons\">\n", " <div class=\"anim-buttons\">\n",
" <button title=\"Decrease speed\" aria-label=\"Decrease speed\" onclick=\"animea6b17f8e6f745568d5445b9aa800110.slower()\">\n", " <button title=\"Decrease speed\" aria-label=\"Decrease speed\" onclick=\"anim7295292aa9074d0193a9f80b1d46cca1.slower()\">\n",
" <i class=\"fa fa-minus\"></i></button>\n", " <i class=\"fa fa-minus\"></i></button>\n",
" <button title=\"First frame\" aria-label=\"First frame\" onclick=\"animea6b17f8e6f745568d5445b9aa800110.first_frame()\">\n", " <button title=\"First frame\" aria-label=\"First frame\" onclick=\"anim7295292aa9074d0193a9f80b1d46cca1.first_frame()\">\n",
" <i class=\"fa fa-fast-backward\"></i></button>\n", " <i class=\"fa fa-fast-backward\"></i></button>\n",
" <button title=\"Previous frame\" aria-label=\"Previous frame\" onclick=\"animea6b17f8e6f745568d5445b9aa800110.previous_frame()\">\n", " <button title=\"Previous frame\" aria-label=\"Previous frame\" onclick=\"anim7295292aa9074d0193a9f80b1d46cca1.previous_frame()\">\n",
" <i class=\"fa fa-step-backward\"></i></button>\n", " <i class=\"fa fa-step-backward\"></i></button>\n",
" <button title=\"Play backwards\" aria-label=\"Play backwards\" onclick=\"animea6b17f8e6f745568d5445b9aa800110.reverse_animation()\">\n", " <button title=\"Play backwards\" aria-label=\"Play backwards\" onclick=\"anim7295292aa9074d0193a9f80b1d46cca1.reverse_animation()\">\n",
" <i class=\"fa fa-play fa-flip-horizontal\"></i></button>\n", " <i class=\"fa fa-play fa-flip-horizontal\"></i></button>\n",
" <button title=\"Pause\" aria-label=\"Pause\" onclick=\"animea6b17f8e6f745568d5445b9aa800110.pause_animation()\">\n", " <button title=\"Pause\" aria-label=\"Pause\" onclick=\"anim7295292aa9074d0193a9f80b1d46cca1.pause_animation()\">\n",
" <i class=\"fa fa-pause\"></i></button>\n", " <i class=\"fa fa-pause\"></i></button>\n",
" <button title=\"Play\" aria-label=\"Play\" onclick=\"animea6b17f8e6f745568d5445b9aa800110.play_animation()\">\n", " <button title=\"Play\" aria-label=\"Play\" onclick=\"anim7295292aa9074d0193a9f80b1d46cca1.play_animation()\">\n",
" <i class=\"fa fa-play\"></i></button>\n", " <i class=\"fa fa-play\"></i></button>\n",
" <button title=\"Next frame\" aria-label=\"Next frame\" onclick=\"animea6b17f8e6f745568d5445b9aa800110.next_frame()\">\n", " <button title=\"Next frame\" aria-label=\"Next frame\" onclick=\"anim7295292aa9074d0193a9f80b1d46cca1.next_frame()\">\n",
" <i class=\"fa fa-step-forward\"></i></button>\n", " <i class=\"fa fa-step-forward\"></i></button>\n",
" <button title=\"Last frame\" aria-label=\"Last frame\" onclick=\"animea6b17f8e6f745568d5445b9aa800110.last_frame()\">\n", " <button title=\"Last frame\" aria-label=\"Last frame\" onclick=\"anim7295292aa9074d0193a9f80b1d46cca1.last_frame()\">\n",
" <i class=\"fa fa-fast-forward\"></i></button>\n", " <i class=\"fa fa-fast-forward\"></i></button>\n",
" <button title=\"Increase speed\" aria-label=\"Increase speed\" onclick=\"animea6b17f8e6f745568d5445b9aa800110.faster()\">\n", " <button title=\"Increase speed\" aria-label=\"Increase speed\" onclick=\"anim7295292aa9074d0193a9f80b1d46cca1.faster()\">\n",
" <i class=\"fa fa-plus\"></i></button>\n", " <i class=\"fa fa-plus\"></i></button>\n",
" </div>\n", " </div>\n",
" <form title=\"Repetition mode\" aria-label=\"Repetition mode\" action=\"#n\" name=\"_anim_loop_selectea6b17f8e6f745568d5445b9aa800110\"\n", " <form title=\"Repetition mode\" aria-label=\"Repetition mode\" action=\"#n\" name=\"_anim_loop_select7295292aa9074d0193a9f80b1d46cca1\"\n",
" class=\"anim-state\">\n", " class=\"anim-state\">\n",
" <input type=\"radio\" name=\"state\" value=\"once\" id=\"_anim_radio1_ea6b17f8e6f745568d5445b9aa800110\"\n", " <input type=\"radio\" name=\"state\" value=\"once\" id=\"_anim_radio1_7295292aa9074d0193a9f80b1d46cca1\"\n",
" >\n", " >\n",
" <label for=\"_anim_radio1_ea6b17f8e6f745568d5445b9aa800110\">Once</label>\n", " <label for=\"_anim_radio1_7295292aa9074d0193a9f80b1d46cca1\">Once</label>\n",
" <input type=\"radio\" name=\"state\" value=\"loop\" id=\"_anim_radio2_ea6b17f8e6f745568d5445b9aa800110\"\n", " <input type=\"radio\" name=\"state\" value=\"loop\" id=\"_anim_radio2_7295292aa9074d0193a9f80b1d46cca1\"\n",
" checked>\n", " checked>\n",
" <label for=\"_anim_radio2_ea6b17f8e6f745568d5445b9aa800110\">Loop</label>\n", " <label for=\"_anim_radio2_7295292aa9074d0193a9f80b1d46cca1\">Loop</label>\n",
" <input type=\"radio\" name=\"state\" value=\"reflect\" id=\"_anim_radio3_ea6b17f8e6f745568d5445b9aa800110\"\n", " <input type=\"radio\" name=\"state\" value=\"reflect\" id=\"_anim_radio3_7295292aa9074d0193a9f80b1d46cca1\"\n",
" >\n", " >\n",
" <label for=\"_anim_radio3_ea6b17f8e6f745568d5445b9aa800110\">Reflect</label>\n", " <label for=\"_anim_radio3_7295292aa9074d0193a9f80b1d46cca1\">Reflect</label>\n",
" </form>\n", " </form>\n",
" </div>\n", " </div>\n",
"</div>\n", "</div>\n",
@ -5055,9 +5057,9 @@
" /* Instantiate the Animation class. */\n", " /* Instantiate the Animation class. */\n",
" /* The IDs given should match those used in the template above. */\n", " /* The IDs given should match those used in the template above. */\n",
" (function() {\n", " (function() {\n",
" var img_id = \"_anim_imgea6b17f8e6f745568d5445b9aa800110\";\n", " var img_id = \"_anim_img7295292aa9074d0193a9f80b1d46cca1\";\n",
" var slider_id = \"_anim_sliderea6b17f8e6f745568d5445b9aa800110\";\n", " var slider_id = \"_anim_slider7295292aa9074d0193a9f80b1d46cca1\";\n",
" var loop_select_id = \"_anim_loop_selectea6b17f8e6f745568d5445b9aa800110\";\n", " var loop_select_id = \"_anim_loop_select7295292aa9074d0193a9f80b1d46cca1\";\n",
" var frames = new Array(1);\n", " var frames = new Array(1);\n",
" \n", " \n",
" frames[0] = \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90\\\n", " frames[0] = \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90\\\n",
@ -5446,14 +5448,14 @@
" /* set a timeout to make sure all the above elements are created before\n", " /* set a timeout to make sure all the above elements are created before\n",
" the object is initialized. */\n", " the object is initialized. */\n",
" setTimeout(function() {\n", " setTimeout(function() {\n",
" animea6b17f8e6f745568d5445b9aa800110 = new Animation(frames, img_id, slider_id, 200.0,\n", " anim7295292aa9074d0193a9f80b1d46cca1 = new Animation(frames, img_id, slider_id, 200.0,\n",
" loop_select_id);\n", " loop_select_id);\n",
" }, 0);\n", " }, 0);\n",
" })()\n", " })()\n",
"</script>\n" "</script>\n"
], ],
"text/plain": [ "text/plain": [
"<matplotlib.animation.FuncAnimation at 0x31c28bef0>" "<matplotlib.animation.FuncAnimation at 0x31cdecd70>"
] ]
}, },
"execution_count": 159, "execution_count": 159,
@ -5487,7 +5489,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"Puzzle 14.2: 1.828 seconds, answer 6876 ok" "Puzzle 14.2: 1.866 seconds, answer 6876 ok"
] ]
}, },
"execution_count": 161, "execution_count": 161,
@ -5609,7 +5611,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"Puzzle 15.1: .026 seconds, answer 1563092 ok" "Puzzle 15.1: .027 seconds, answer 1563092 ok"
] ]
}, },
"execution_count": 166, "execution_count": 166,
@ -5877,7 +5879,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"Puzzle 16.1: .146 seconds, answer 103512 ok" "Puzzle 16.1: .147 seconds, answer 103512 ok"
] ]
}, },
"execution_count": 178, "execution_count": 178,
@ -5941,7 +5943,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"Puzzle 16.2: .848 seconds, answer 554 ok" "Puzzle 16.2: .860 seconds, answer 554 ok"
] ]
}, },
"execution_count": 181, "execution_count": 181,
@ -6547,7 +6549,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"Puzzle 19.1: .040 seconds, answer 242 ok" "Puzzle 19.1: .039 seconds, answer 242 ok"
] ]
}, },
"execution_count": 211, "execution_count": 211,
@ -6594,7 +6596,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"Puzzle 19.2: .186 seconds, answer 595975512785325 ok" "Puzzle 19.2: .185 seconds, answer 595975512785325 ok"
] ]
}, },
"execution_count": 214, "execution_count": 214,
@ -6762,7 +6764,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"Puzzle 20.1: .029 seconds, answer 1343 ok" "Puzzle 20.1: .028 seconds, answer 1343 ok"
] ]
}, },
"execution_count": 224, "execution_count": 224,
@ -6799,7 +6801,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"Puzzle 20.2: .761 seconds, answer 982891 ok" "Puzzle 20.2: .768 seconds, answer 982891 ok"
] ]
}, },
"execution_count": 226, "execution_count": 226,
@ -7281,7 +7283,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"Puzzle 22.1: .318 seconds, answer 14273043166 ok" "Puzzle 22.1: .331 seconds, answer 14273043166 ok"
] ]
}, },
"execution_count": 255, "execution_count": 255,
@ -7325,7 +7327,7 @@
"Some details:\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 `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 automatically drops old deltas.\n", "- 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." "- In `price_timeline` I could call `nth_secret(secret, 1)`, but I decided to make a separate `next_secret` function. I probably should have done that for Part 1."
] ]
}, },
{ {
@ -7347,18 +7349,25 @@
" return bananas\n", " return bananas\n",
" \n", " \n",
"def price_timeline(secret, n=2000) -> Dict[Deltas, int]:\n", "def price_timeline(secret, n=2000) -> Dict[Deltas, int]:\n",
" \"\"\"Each {delta-4-tuple: price} in the timeline of this secret number for `n` steps.\"\"\"\n", " \"\"\"Each {delta-4-tuple: price} in the timeline of this secret number, for `n` steps.\"\"\"\n",
" timeline = {} # {delta-4-tuple: price} pairs\n", " timeline = {} # {delta-4-tuple: price} pairs\n",
" deltas = deque(maxlen=4) # The 4 most recent price deltas \n", " deltas = deque(maxlen=4) # The 4 most recent price deltas \n",
" price = secret % 10 # Initial price\n", " price = secret % 10 # Initial price\n",
" for _ in range(n):\n", " for _ in range(n):\n",
" secret = nth_secret(secret, 1)\n", " secret = next_secret(secret)\n",
" price, previous_price = secret % 10, price\n", " price, previous_price = secret % 10, price\n",
" deltas.append(price - previous_price)\n", " deltas.append(price - previous_price)\n",
" D = tuple(deltas)\n", " D = tuple(deltas)\n",
" if len(D) == 4 and D not in timeline:\n", " if len(D) == 4 and D not in timeline:\n",
" timeline[D] = price\n", " timeline[D] = price\n",
" return timeline" " return timeline\n",
"\n",
"def next_secret(secret: int) -> int:\n",
" \"\"\"Compute the next secret number after this secret number.\"\"\"\n",
" secret ^= (secret * 64) % 16777216\n",
" secret ^= (secret // 32) % 16777216\n",
" secret ^= (secret * 2048) % 16777216\n",
" return secret"
] ]
}, },
{ {
@ -7370,7 +7379,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"Puzzle 22.2: 1.267 seconds, answer 1667 ok" "Puzzle 22.2: 1.157 seconds, answer 1667 ok"
] ]
}, },
"execution_count": 258, "execution_count": 258,
@ -7767,7 +7776,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"Puzzle 23.2: .004 seconds, answer bo,dd,eq,ik,lo,lu,ph,ro,rr,rw,uo,wx,yg ok" "Puzzle 23.2: .003 seconds, answer bo,dd,eq,ik,lo,lu,ph,ro,rr,rw,uo,wx,yg ok"
] ]
}, },
"execution_count": 281, "execution_count": 281,
@ -8331,7 +8340,7 @@
"\n", "\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", "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", "\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." "The median run time is about 5 milliseconds, with 3 puzzles taking over a second. I didn't count the time that `parse` takes, but that is less than a millisecond per day."
] ]
}, },
{ {
@ -8351,58 +8360,66 @@
"Puzzle 3.1: .001 seconds, answer 156388521 ok\n", "Puzzle 3.1: .001 seconds, answer 156388521 ok\n",
"Puzzle 3.2: .000 seconds, answer 75920122 ok\n", "Puzzle 3.2: .000 seconds, answer 75920122 ok\n",
"Puzzle 4.1: .021 seconds, answer 2401 ok\n", "Puzzle 4.1: .021 seconds, answer 2401 ok\n",
"Puzzle 4.2: .015 seconds, answer 1822 ok\n", "Puzzle 4.2: .016 seconds, answer 1822 ok\n",
"Puzzle 5.1: .001 seconds, answer 5762 ok\n", "Puzzle 5.1: .001 seconds, answer 5762 ok\n",
"Puzzle 5.2: .001 seconds, answer 4130 ok\n", "Puzzle 5.2: .001 seconds, answer 4130 ok\n",
"Puzzle 6.1: .002 seconds, answer 5329 ok\n", "Puzzle 6.1: .002 seconds, answer 5329 ok\n",
"Puzzle 6.2: 1.943 seconds, answer 2162 ok\n", "Puzzle 6.2: 1.977 seconds, answer 2162 ok\n",
"Puzzle 7.1: .014 seconds, answer 1985268524462 ok\n", "Puzzle 7.1: .014 seconds, answer 1985268524462 ok\n",
"Puzzle 7.2: .592 seconds, answer 150077710195188 ok\n", "Puzzle 7.2: .600 seconds, answer 150077710195188 ok\n",
"Puzzle 8.1: .003 seconds, answer 220 ok\n", "Puzzle 8.1: .003 seconds, answer 220 ok\n",
"Puzzle 8.2: .003 seconds, answer 813 ok\n", "Puzzle 8.2: .003 seconds, answer 813 ok\n",
"Puzzle 9.1: .019 seconds, answer 6332189866718 ok\n", "Puzzle 9.1: .020 seconds, answer 6332189866718 ok\n",
"Puzzle 9.2: 2.384 seconds, answer 6353648390778 ok\n", "Puzzle 9.2: .021 seconds, answer 6353648390778 ok\n",
"Puzzle 10.1: .005 seconds, answer 744 ok\n", "Puzzle 10.1: .004 seconds, answer 744 ok\n",
"Puzzle 10.2: .006 seconds, answer 1651 ok\n", "Puzzle 10.2: .006 seconds, answer 1651 ok\n",
"Puzzle 11.1: .001 seconds, answer 194482 ok\n", "Puzzle 11.1: .002 seconds, answer 194482 ok\n",
"Puzzle 11.2: .060 seconds, answer 232454623677743 ok\n", "Puzzle 11.2: .058 seconds, answer 232454623677743 ok\n",
"Puzzle 12.1: .050 seconds, answer 1402544 ok\n", "Puzzle 12.1: .052 seconds, answer 1402544 ok\n",
"Puzzle 12.2: .042 seconds, answer 862486 ok\n", "Puzzle 12.2: .043 seconds, answer 862486 ok\n",
"Puzzle 13.1: .000 seconds, answer 29598 ok\n", "Puzzle 13.1: .000 seconds, answer 29598 ok\n",
"Puzzle 13.2: .000 seconds, answer 93217456941970 ok\n", "Puzzle 13.2: .000 seconds, answer 93217456941970 ok\n",
"Puzzle 14.1: .000 seconds, answer 216027840 ok\n", "Puzzle 14.1: .000 seconds, answer 216027840 ok\n",
"Puzzle 14.2: 1.828 seconds, answer 6876 ok\n", "Puzzle 14.2: 1.866 seconds, answer 6876 ok\n",
"Puzzle 15.1: .029 seconds, answer 1563092 ok\n", "Puzzle 15.1: .029 seconds, answer 1563092 ok\n",
"Puzzle 15.2: .042 seconds, answer 1582688 ok\n", "Puzzle 15.2: .042 seconds, answer 1582688 ok\n",
"Puzzle 16.1: .146 seconds, answer 103512 ok\n", "Puzzle 16.1: .147 seconds, answer 103512 ok\n",
"Puzzle 16.2: .848 seconds, answer 554 ok\n", "Puzzle 16.2: .860 seconds, answer 554 ok\n",
"Puzzle 17.1: .000 seconds, answer 2,1,0,1,7,2,5,0,3 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 17.2: .004 seconds, answer 267265166222235 ok\n",
"Puzzle 18.1: .014 seconds, answer 344 ok\n", "Puzzle 18.1: .014 seconds, answer 344 ok\n",
"Puzzle 18.2: .032 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.1: .004 seconds, answer 242 ok\n",
"Puzzle 19.2: .186 seconds, answer 595975512785325 ok\n", "Puzzle 19.2: .185 seconds, answer 595975512785325 ok\n",
"Puzzle 20.1: .023 seconds, answer 1343 ok\n", "Puzzle 20.1: .023 seconds, answer 1343 ok\n",
"Puzzle 20.2: .761 seconds, answer 982891 ok\n", "Puzzle 20.2: .768 seconds, answer 982891 ok\n",
"Puzzle 21.1: .000 seconds, answer 205160 ok\n", "Puzzle 21.1: .000 seconds, answer 205160 ok\n",
"Puzzle 21.2: .004 seconds, answer 252473394928452 ok\n", "Puzzle 21.2: .004 seconds, answer 252473394928452 ok\n",
"Puzzle 22.1: .318 seconds, answer 14273043166 ok\n", "Puzzle 22.1: .331 seconds, answer 14273043166 ok\n",
"Puzzle 22.2: 1.267 seconds, answer 1667 ok\n", "Puzzle 22.2: 1.157 seconds, answer 1667 ok\n",
"Puzzle 23.1: .001 seconds, answer 1170 ok\n", "Puzzle 23.1: .001 seconds, answer 1170 ok\n",
"Puzzle 23.2: .004 seconds, answer bo,dd,eq,ik,lo,lu,ph,ro,rr,rw,uo,wx,yg ok\n", "Puzzle 23.2: .003 seconds, answer bo,dd,eq,ik,lo,lu,ph,ro,rr,rw,uo,wx,yg ok\n",
"Puzzle 24.1: .001 seconds, answer 36035961805936 ok\n", "Puzzle 24.1: .001 seconds, answer 36035961805936 ok\n",
"Puzzle 24.2: .000 seconds, answer jqf,mdd,skh,wpd,wts,z11,z19,z37 ok\n", "Puzzle 24.2: .000 seconds, answer jqf,mdd,skh,wpd,wts,z11,z19,z37 ok\n",
"Puzzle 25.1: .022 seconds, answer 3196 ok\n", "Puzzle 25.1: .022 seconds, answer 3196 ok\n",
"\n", "\n",
"Correct: 49/49\n", "Correct: 49/49\n",
"\n", "\n",
"Time in seconds: 0.005 median, 0.218 mean, 10.699 total.\n" "Time in seconds: 0.004 median, 0.170 mean, 8.342 total.\n"
] ]
} }
], ],
"source": [ "source": [
"summary(answers)" "summary(answers)"
] ]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4f23c694-7302-4d45-8bef-751b9a7356f2",
"metadata": {},
"outputs": [],
"source": []
} }
], ],
"metadata": { "metadata": {