From c2e5a4c9b0477bbea193ba4458268d07f2f37acb Mon Sep 17 00:00:00 2001 From: Darren Lester Date: Wed, 20 Dec 2023 09:41:52 +0000 Subject: [PATCH] 2023d20 pt 1 done --- .env | Bin 535 -> 535 bytes .../Dazbo's_Advent_of_Code_2023.ipynb | 801 ++++++++++++++++-- src/AoC_2023/d20/input/input.txt | Bin 0 -> 872 bytes 3 files changed, 748 insertions(+), 53 deletions(-) create mode 100644 src/AoC_2023/d20/input/input.txt diff --git a/.env b/.env index f05e9f790d1da8d47cb97ab325b68377b86f8f75..7bbec20237187f88376d08883eec246a3e37beb7 100644 GIT binary patch literal 535 zcmV+y0_gn!M@dveQdv+`09WwN3M!#VXirGEDiPL4T1Qi1TLO0iL&IySEkkO6r{DCw z$bdp<1(*blpOr~bh?MNJ;6j8k)90{v-z
wnEsZoh)$124~tB#=Q1zqD_kWhW6O*+?^FXL2flOk}GN$#&$?F$@c>w~A5ajo-x
zV=Pt^w5Q~)6MJUSTJEmNk60DDN^)T{nyiWn^tP>US`nCvdQ0ouzQD)n~0O3Q-3L)2bn%GkXT{a!76_X
zJ(H6?=7rp>p9gikjXj_XN|~_AUyKIGNaAA1CRn&v&8dx3fR}$y8g4*O3$(R%7El)X@zq^Ik!5&KOQ)2|Sdn44pt!@p42(e@HmM;~1ijidz}pTXYK8IFgtsz+~WuyT*O@*JUeh
zKYRVdS{ywSpbP=^9q-t}uvV*^x{ZOsM55QZTf|8R*wN=
z2#O{g&L}PoFe`Oj5SgFKbCT}Ck+H_ZRD|w0s$Z&2(SG%K_4MmX*e>>_qF{(XWC9j7
zgb9cA^vIQ!t1UrW4Max*e+K4woRq#@d?@|+ZBGghz=NeSYA)>@{BEj5>#r7#_zvou
z`A&wmg=ocT+U^a(qdLu2Z!-8<7B1(MqG~-zOu3M4xB1}T2p}hq2}~-*Md`;{Pvy~0
zz*1_3s2-dc%&UH#F}1d;QT`C4Z2j#0cKbeyS0OTLc&}fiyQ)`Pq<1TpN2k{#Ds$@z
zh0FU2!4%~5UwmTt8RQq*4@hd2b3)P}-fRXQh^wvAB!Ci~);DHaKq&ao{&-n}#8EQ1
zB@QeVOye!@pa5dtk{W+vZRSG%g66<*JJp;_@W4%Hw*K&Y{-_BrL~B6u|DmePnE!;(
zW`e8PdJKw+S6D$5l;^Li_iT|i<2m1>rd)Qr|Cd_zrG{kIOU>4)y!4X><+H;Q$)dCq
Z++SbB!qo{hXqM;z=2.0.0 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyterlab-lsp) (2.2.0)\n",
+      "Requirement already satisfied: jupyterlab<5.0.0a0,>=4.0.6 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyterlab-lsp) (4.0.8)\n",
+      "Requirement already satisfied: comm>=0.1.1 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from ipykernel) (0.1.2)\n",
+      "Requirement already satisfied: debugpy>=1.6.5 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from ipykernel) (1.6.7)\n",
+      "Requirement already satisfied: ipython>=7.23.1 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from ipykernel) (8.15.0)\n",
+      "Requirement already satisfied: jupyter-client>=6.1.12 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from ipykernel) (8.6.0)\n",
+      "Requirement already satisfied: jupyter-core!=5.0.*,>=4.12 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from ipykernel) (5.5.0)\n",
+      "Requirement already satisfied: matplotlib-inline>=0.1 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from ipykernel) (0.1.6)\n",
+      "Requirement already satisfied: nest-asyncio in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from ipykernel) (1.5.6)\n",
+      "Requirement already satisfied: packaging in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from ipykernel) (23.1)\n",
+      "Requirement already satisfied: psutil in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from ipykernel) (5.9.0)\n",
+      "Requirement already satisfied: pyzmq>=20 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from ipykernel) (25.1.0)\n",
+      "Requirement already satisfied: tornado>=6.1 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from ipykernel) (6.3.3)\n",
+      "Requirement already satisfied: traitlets>=5.4.0 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from ipykernel) (5.7.1)\n",
+      "Requirement already satisfied: matplotlib in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from mediapy) (3.8.0)\n",
+      "Requirement already satisfied: numpy in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from mediapy) (1.26.2)\n",
+      "Requirement already satisfied: Pillow in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from mediapy) (10.0.1)\n",
+      "Requirement already satisfied: backcall in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from ipython>=7.23.1->ipykernel) (0.2.0)\n",
+      "Requirement already satisfied: decorator in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from ipython>=7.23.1->ipykernel) (5.1.1)\n",
+      "Requirement already satisfied: jedi>=0.16 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from ipython>=7.23.1->ipykernel) (0.18.1)\n",
+      "Requirement already satisfied: pickleshare in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from ipython>=7.23.1->ipykernel) (0.7.5)\n",
+      "Requirement already satisfied: prompt-toolkit!=3.0.37,<3.1.0,>=3.0.30 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from ipython>=7.23.1->ipykernel) (3.0.36)\n",
+      "Requirement already satisfied: pygments>=2.4.0 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from ipython>=7.23.1->ipykernel) (2.15.1)\n",
+      "Requirement already satisfied: stack-data in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from ipython>=7.23.1->ipykernel) (0.2.0)\n",
+      "Requirement already satisfied: python-dateutil>=2.8.2 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyter-client>=6.1.12->ipykernel) (2.8.2)\n",
+      "Requirement already satisfied: platformdirs>=2.5 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyter-core!=5.0.*,>=4.12->ipykernel) (3.10.0)\n",
+      "Requirement already satisfied: pywin32>=300 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyter-core!=5.0.*,>=4.12->ipykernel) (305.1)\n",
+      "Requirement already satisfied: jupyter-server>=1.1.2 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyter-lsp>=2.0.0->jupyterlab-lsp) (2.10.0)\n",
+      "Requirement already satisfied: async-lru>=1.0.0 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyterlab<5.0.0a0,>=4.0.6->jupyterlab-lsp) (2.0.4)\n",
+      "Requirement already satisfied: jinja2>=3.0.3 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyterlab<5.0.0a0,>=4.0.6->jupyterlab-lsp) (3.1.2)\n",
+      "Requirement already satisfied: jupyterlab-server<3,>=2.19.0 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyterlab<5.0.0a0,>=4.0.6->jupyterlab-lsp) (2.25.1)\n",
+      "Requirement already satisfied: notebook-shim>=0.2 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyterlab<5.0.0a0,>=4.0.6->jupyterlab-lsp) (0.2.3)\n",
+      "Requirement already satisfied: contourpy>=1.0.1 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from matplotlib->mediapy) (1.2.0)\n",
+      "Requirement already satisfied: cycler>=0.10 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from matplotlib->mediapy) (0.11.0)\n",
+      "Requirement already satisfied: fonttools>=4.22.0 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from matplotlib->mediapy) (4.25.0)\n",
+      "Requirement already satisfied: kiwisolver>=1.0.1 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from matplotlib->mediapy) (1.4.4)\n",
+      "Requirement already satisfied: pyparsing>=2.3.1 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from matplotlib->mediapy) (3.0.9)\n",
+      "Requirement already satisfied: parso<0.9.0,>=0.8.0 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jedi>=0.16->ipython>=7.23.1->ipykernel) (0.8.3)\n",
+      "Requirement already satisfied: MarkupSafe>=2.0 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jinja2>=3.0.3->jupyterlab<5.0.0a0,>=4.0.6->jupyterlab-lsp) (2.1.1)\n",
+      "Requirement already satisfied: anyio>=3.1.0 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (3.5.0)\n",
+      "Requirement already satisfied: argon2-cffi in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (21.3.0)\n",
+      "Requirement already satisfied: jupyter-events>=0.6.0 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (0.8.0)\n",
+      "Requirement already satisfied: jupyter-server-terminals in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (0.4.4)\n",
+      "Requirement already satisfied: nbconvert>=6.4.4 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (7.10.0)\n",
+      "Requirement already satisfied: nbformat>=5.3.0 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (5.9.2)\n",
+      "Requirement already satisfied: overrides in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (7.4.0)\n",
+      "Requirement already satisfied: prometheus-client in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (0.14.1)\n",
+      "Requirement already satisfied: pywinpty in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (2.0.10)\n",
+      "Requirement already satisfied: send2trash>=1.8.2 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (1.8.2)\n",
+      "Requirement already satisfied: terminado>=0.8.3 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (0.17.1)\n",
+      "Requirement already satisfied: websocket-client in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (0.58.0)\n",
+      "Requirement already satisfied: babel>=2.10 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyterlab-server<3,>=2.19.0->jupyterlab<5.0.0a0,>=4.0.6->jupyterlab-lsp) (2.11.0)\n",
+      "Requirement already satisfied: json5>=0.9.0 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyterlab-server<3,>=2.19.0->jupyterlab<5.0.0a0,>=4.0.6->jupyterlab-lsp) (0.9.6)\n",
+      "Requirement already satisfied: jsonschema>=4.18.0 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyterlab-server<3,>=2.19.0->jupyterlab<5.0.0a0,>=4.0.6->jupyterlab-lsp) (4.19.2)\n",
+      "Requirement already satisfied: requests>=2.31 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyterlab-server<3,>=2.19.0->jupyterlab<5.0.0a0,>=4.0.6->jupyterlab-lsp) (2.31.0)\n",
+      "Requirement already satisfied: wcwidth in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from prompt-toolkit!=3.0.37,<3.1.0,>=3.0.30->ipython>=7.23.1->ipykernel) (0.2.5)\n",
+      "Requirement already satisfied: six>=1.5 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from python-dateutil>=2.8.2->jupyter-client>=6.1.12->ipykernel) (1.16.0)\n",
+      "Requirement already satisfied: executing in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from stack-data->ipython>=7.23.1->ipykernel) (0.8.3)\n",
+      "Requirement already satisfied: asttokens in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from stack-data->ipython>=7.23.1->ipykernel) (2.0.5)\n",
+      "Requirement already satisfied: pure-eval in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from stack-data->ipython>=7.23.1->ipykernel) (0.2.2)\n",
+      "Requirement already satisfied: idna>=2.8 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from anyio>=3.1.0->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (3.4)\n",
+      "Requirement already satisfied: sniffio>=1.1 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from anyio>=3.1.0->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (1.2.0)\n",
+      "Requirement already satisfied: pytz>=2015.7 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from babel>=2.10->jupyterlab-server<3,>=2.19.0->jupyterlab<5.0.0a0,>=4.0.6->jupyterlab-lsp) (2023.3.post1)\n",
+      "Requirement already satisfied: attrs>=22.2.0 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.19.0->jupyterlab<5.0.0a0,>=4.0.6->jupyterlab-lsp) (23.1.0)\n",
+      "Requirement already satisfied: jsonschema-specifications>=2023.03.6 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.19.0->jupyterlab<5.0.0a0,>=4.0.6->jupyterlab-lsp) (2023.7.1)\n",
+      "Requirement already satisfied: referencing>=0.28.4 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.19.0->jupyterlab<5.0.0a0,>=4.0.6->jupyterlab-lsp) (0.30.2)\n",
+      "Requirement already satisfied: rpds-py>=0.7.1 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jsonschema>=4.18.0->jupyterlab-server<3,>=2.19.0->jupyterlab<5.0.0a0,>=4.0.6->jupyterlab-lsp) (0.10.6)\n",
+      "Requirement already satisfied: python-json-logger>=2.0.4 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyter-events>=0.6.0->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (2.0.7)\n",
+      "Requirement already satisfied: pyyaml>=5.3 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyter-events>=0.6.0->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (6.0.1)\n",
+      "Requirement already satisfied: rfc3339-validator in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyter-events>=0.6.0->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (0.1.4)\n",
+      "Requirement already satisfied: rfc3986-validator>=0.1.1 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jupyter-events>=0.6.0->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (0.1.1)\n",
+      "Requirement already satisfied: beautifulsoup4 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from nbconvert>=6.4.4->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (4.12.2)\n",
+      "Requirement already satisfied: bleach!=5.0.0 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from nbconvert>=6.4.4->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (4.1.0)\n",
+      "Requirement already satisfied: defusedxml in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from nbconvert>=6.4.4->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (0.7.1)\n",
+      "Requirement already satisfied: jupyterlab-pygments in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from nbconvert>=6.4.4->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (0.1.2)\n",
+      "Requirement already satisfied: mistune<4,>=2.0.3 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from nbconvert>=6.4.4->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (2.0.4)\n",
+      "Requirement already satisfied: nbclient>=0.5.0 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from nbconvert>=6.4.4->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (0.8.0)\n",
+      "Requirement already satisfied: pandocfilters>=1.4.1 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from nbconvert>=6.4.4->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (1.5.0)\n",
+      "Requirement already satisfied: tinycss2 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from nbconvert>=6.4.4->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (1.2.1)\n",
+      "Requirement already satisfied: fastjsonschema in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from nbformat>=5.3.0->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (2.16.2)\n",
+      "Requirement already satisfied: charset-normalizer<4,>=2 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from requests>=2.31->jupyterlab-server<3,>=2.19.0->jupyterlab<5.0.0a0,>=4.0.6->jupyterlab-lsp) (2.0.4)\n",
+      "Requirement already satisfied: urllib3<3,>=1.21.1 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from requests>=2.31->jupyterlab-server<3,>=2.19.0->jupyterlab<5.0.0a0,>=4.0.6->jupyterlab-lsp) (1.26.18)\n",
+      "Requirement already satisfied: certifi>=2017.4.17 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from requests>=2.31->jupyterlab-server<3,>=2.19.0->jupyterlab<5.0.0a0,>=4.0.6->jupyterlab-lsp) (2023.11.17)\n",
+      "Requirement already satisfied: argon2-cffi-bindings in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from argon2-cffi->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (21.2.0)\n",
+      "Requirement already satisfied: webencodings in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from bleach!=5.0.0->nbconvert>=6.4.4->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (0.5.1)\n",
+      "Requirement already satisfied: fqdn in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.6.0->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (1.5.1)\n",
+      "Requirement already satisfied: isoduration in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.6.0->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (20.11.0)\n",
+      "Requirement already satisfied: jsonpointer>1.13 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.6.0->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (2.4)\n",
+      "Requirement already satisfied: uri-template in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.6.0->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (1.3.0)\n",
+      "Requirement already satisfied: webcolors>=1.11 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.6.0->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (1.13)\n",
+      "Requirement already satisfied: cffi>=1.0.1 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from argon2-cffi-bindings->argon2-cffi->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (1.16.0)\n",
+      "Requirement already satisfied: soupsieve>1.2 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from beautifulsoup4->nbconvert>=6.4.4->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (2.5)\n",
+      "Requirement already satisfied: pycparser in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from cffi>=1.0.1->argon2-cffi-bindings->argon2-cffi->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (2.21)\n",
+      "Requirement already satisfied: arrow>=0.15.0 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from isoduration->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.6.0->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (1.3.0)\n",
+      "Requirement already satisfied: types-python-dateutil>=2.8.10 in c:\\users\\darren_lester\\appdata\\local\\anaconda3\\envs\\aoc-ana-env\\lib\\site-packages (from arrow>=0.15.0->isoduration->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.6.0->jupyter-server>=1.1.2->jupyter-lsp>=2.0.0->jupyterlab-lsp) (2.8.19.14)\n",
+      "Note: you may need to restart the kernel to use updated packages.\n"
+     ]
+    }
+   ],
    "source": [
     "%pip install jupyterlab-lsp colorama python-dotenv ipykernel ffmpeg mediapy"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 48,
    "metadata": {
     "id": "p5Ki_HvOJUWk",
     "tags": []
@@ -74,6 +183,7 @@
     "from itertools import permutations, combinations, count, cycle\n",
     "from collections import Counter, deque, defaultdict\n",
     "from io import BytesIO\n",
+    "import abc\n",
     "import heapq\n",
     "import copy\n",
     "import operator\n",
@@ -119,7 +229,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 11,
    "metadata": {
     "id": "SwzjfUFCKhXe",
     "tags": []
@@ -255,9 +365,36 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
+   "execution_count": 12,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "\u001b[32m23:34:58.058:__main__ - INF: Installing FFmpeg on Windows...\u001b[39m\n",
+      "\u001b[32m23:35:00.224:__main__ - INF: Note that the ffmpeg command may not be immediately available after first installing ffmpeg.\n",
+      "It may be necessary to relaunch the notebook environment.\u001b[39m\n"
+     ]
+    },
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "ffmpeg version 6.1-full_build-www.gyan.dev Copyright (c) 2000-2023 the FFmpeg developers\n",
+      "built with gcc 12.2.0 (Rev10, Built by MSYS2 project)\n",
+      "configuration: --enable-gpl --enable-version3 --enable-static --pkg-config=pkgconf --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-bzlib --enable-lzma --enable-libsnappy --enable-zlib --enable-librist --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-libbluray --enable-libcaca --enable-sdl2 --enable-libaribb24 --enable-libaribcaption --enable-libdav1d --enable-libdavs2 --enable-libuavs3d --enable-libzvbi --enable-librav1e --enable-libsvtav1 --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs2 --enable-libxvid --enable-libaom --enable-libjxl --enable-libopenjpeg --enable-libvpx --enable-mediafoundation --enable-libass --enable-frei0r --enable-libfreetype --enable-libfribidi --enable-libharfbuzz --enable-liblensfun --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-ffnvcodec --enable-nvdec --enable-nvenc --enable-dxva2 --enable-d3d11va --enable-libvpl --enable-libshaderc --enable-vulkan --enable-libplacebo --enable-opencl --enable-libcdio --enable-libgme --enable-libmodplug --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libshine --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libcodec2 --enable-libilbc --enable-libgsm --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-ladspa --enable-libbs2b --enable-libflite --enable-libmysofa --enable-librubberband --enable-libsoxr --enable-chromaprint\n",
+      "libavutil      58. 29.100 / 58. 29.100\n",
+      "libavcodec     60. 31.102 / 60. 31.102\n",
+      "libavformat    60. 16.100 / 60. 16.100\n",
+      "libavdevice    60.  3.100 / 60.  3.100\n",
+      "libavfilter     9. 12.100 /  9. 12.100\n",
+      "libswscale      7.  5.100 /  7.  5.100\n",
+      "libswresample   4. 12.100 /  4. 12.100\n",
+      "libpostproc    57.  3.100 / 57.  3.100\n"
+     ]
+    }
+   ],
    "source": [
     "def install_ffmpeg():\n",
     "    os_name = platform.system()\n",
@@ -305,9 +442,21 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 43,
    "metadata": {},
-   "outputs": [],
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "\u001b[34m06:08:54.305:aoc2023 - DBG: Trying .env at C:\\Users\\Darren_Lester\\localdev\\My-IP\\Advent-of-Code\\src\\AoC_2023\\.env\u001b[39m\n",
+      "\u001b[34m06:08:54.306:aoc2023 - DBG: Trying .env at C:\\Users\\Darren_Lester\\localdev\\My-IP\\Advent-of-Code\\src\\.env\u001b[39m\n",
+      "\u001b[34m06:08:54.307:aoc2023 - DBG: Trying .env at C:\\Users\\Darren_Lester\\localdev\\My-IP\\Advent-of-Code\\.env\u001b[39m\n",
+      "\u001b[32m06:08:54.309:aoc2023 - INF: Using .env at C:\\Users\\Darren_Lester\\localdev\\My-IP\\Advent-of-Code\\.env\u001b[39m\n",
+      "\u001b[32m06:08:54.309:aoc2023 - INF: Session cookie retrieved: 53616c...a18261\u001b[39m\n"
+     ]
+    }
+   ],
    "source": [
     "def get_envs_from_file() -> bool:\n",
     "    \"\"\" Look for .env files, read variables from it, and store as environment variables \"\"\"\n",
@@ -359,7 +508,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 14,
    "metadata": {
     "id": "VK27bcGiK0_M",
     "tags": []
@@ -408,7 +557,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 15,
    "metadata": {
     "id": "lwP0r3BAaxjt",
     "tags": []
@@ -477,7 +626,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 16,
    "metadata": {
     "id": "Y6nbd6WMryWi",
     "tags": []
@@ -505,7 +654,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 17,
    "metadata": {
     "id": "A8sU4Ez_bBKl",
     "tags": []
@@ -759,7 +908,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 18,
    "metadata": {
     "id": "DT5FSYliC9wp",
     "tags": []
@@ -861,7 +1010,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 19,
    "metadata": {
     "id": "sbdA-geUNqAF",
     "tags": []
@@ -6183,9 +6332,22 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 24,
    "metadata": {},
-   "outputs": [],
+   "outputs": [
+    {
+     "data": {
+      "text/markdown": [
+       "#### See [Day 18](https://adventofcode.com/2023/day/18)."
+      ],
+      "text/plain": [
+       ""
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
    "source": [
     "DAY = \"18\" # replace with actual number (without leading digit)\n",
     "day_link = f\"#### See [Day {DAY}](https://adventofcode.com/{YEAR}/day/{DAY}).\"\n",
@@ -6194,9 +6356,29 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
+   "execution_count": 25,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "\u001b[34m23:49:03.318:aoc2023 - DBG: input.txt already exists\u001b[39m\n",
+      "\u001b[32m23:49:03.321:aoc2023 - INF: Input data:\n",
+      "  1: L 7 (#2ac8e2)\n",
+      "  2: D 5 (#14b771)\n",
+      "  3: L 14 (#302602)\n",
+      "  4: U 5 (#14b773)\n",
+      "  5: L 4 (#55b782)\n",
+      "...\n",
+      "690: U 4 (#043ac3)\n",
+      "691: L 8 (#49ca22)\n",
+      "692: U 7 (#057783)\n",
+      "693: L 6 (#57e6a2)\n",
+      "694: U 12 (#2d7e63)\u001b[39m\n"
+     ]
+    }
+   ],
    "source": [
     "d_name = \"d\" + str(DAY).zfill(2) # e.g. d01\n",
     "script_name = \"aoc\" + str(YEAR) + d_name # e.g. aoc2017d01\n",
@@ -6292,7 +6474,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 26,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -6412,7 +6594,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 27,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -6430,9 +6612,122 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
+   "execution_count": 28,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "\u001b[34m23:49:12.086:aoc2023 - DBG: Processing 10 interior candidates.\u001b[39m\n",
+      "\u001b[34m23:49:12.088:aoc2023 - DBG: Updated all_interior with 24 points.\u001b[39m\n",
+      "\u001b[34m23:49:12.088:aoc2023 - DBG: Updated exterior with 3 points.\u001b[39m\n",
+      "\u001b[34m23:49:12.089:aoc2023 - DBG: Updated exterior with 2 points.\u001b[39m\n",
+      "\u001b[34m23:49:12.090:aoc2023 - DBG: Updated exterior with 1 points.\u001b[39m\n"
+     ]
+    },
+    {
+     "data": {
+      "image/png": "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o9KGujrp0Uf7afnyEXr00X6qq/O6InNFo1Io5NPmzekKhXyKRr2uyFxk5RxZOUdWzpGVO8bkZXns8ccftzIyMqyEhATr4osvtjZv3uz470YiEUuSFYlEuq2e22+3LL/fsqTmL7/fHkesdessKxCIzSoQsMcRi6ycIyvnyMo5snKnp/Nys//2tFFZs2aNFR8fb61YscJ6++23rVmzZlkDBgywPvjgA0d/v7sbldtvj/1POfaLZqXZunWW5fO1zsjns7948zcjK+fIyjmyco6s3OmNvNzsv32WZVkeHczRpZdeqosvvljLli1rGsvKytKVV16phQsXdvj3q6urlZKSokgk0uVfSlhXJyUm6riHtvx+6d//lvr379JTnfCiUWnYMCkcbnu9zyelp0s7d9qZ9WVk5RxZOUdWzpGVO07yCgSk3bu7lpeb/bdnvz25rq5Or7/+uu68886Y8by8PL388stt/p3a2lrV1tY2LVdXV0uyf7tjfX19l+pZurSfotHjpx6NSoMGdelp+gTLkqqqpJQUrysxH1k5R1bOkZVzZOWOZUmVldKmTQ3Kyen8cQ43+2zPGpWPP/5Y0WhUgwcPjhkfPHiwPvroozb/zsKFCzV//vxW488//7wSExO7VM+LL46QlNmlxwAAoC8oLd2uQ4faOeziwOHDhx1v61mj0sjn88UsW5bVaqzR3LlzNWfOnKbl6upqBYNB5eXldfnUz/vv91NJScfbLVgQ1f/8z5EuPdeJbssWn6ZM6fils3Fjg7KzPTuzaASyco6snCMr58jKHad5FRSMVE7OhZ1+nsYzIk54do1KXV2dEhMT9cc//lHf+MY3msZnzZql7du3KxQKdfgYXlyjcvgw16hEo1JGhn0Os61XT3edwzwZkJVzZOUcWTlHVu70Vl5u9t+efY5K//79dckll6isrCxmvKysTGPGjPGgHqnFwZo2zZlDkyLZL84lS+zvjz341bi8eDFveoms3CAr58jKObJyx8i8un6TUec13p7861//2nr77bet2bNnWwMGDLD27Nnj6O/31Oeo9OvH56g40dZ99sEgt/q1haycIyvnyMo5snJn3TrLSk/vubxOmNuTJemJJ57Qgw8+qH379mn48OF65JFHNH78eEd/tztP/bR04EDz3T0LFkR1221+jqS0Ixq1r/4uLd2ugoKRmjAhjp9M2kFWzpGV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/Q6QlXNk5RxZOUdWzpGVOz2VV+N+28lv8TmhG5WamhpJUjAY9LgSAADgVk1NjVJSUo67zQn9SwmPHDmiDz/8UElJSfId+/uou6i6ulrBYFCVlZXd/gsPTzZk5RxZOUdWzpGVc2TlTk/lZVmWampqlJaWpn79jn8Vygl9RKVfv34KBAI9+hzJycm8mB0iK+fIyjmyco6snCMrd3oir46OpDTiYloAAGAsGhUAAGAsGpV2JCQk6Gc/+5kSEhK8LsV4ZOUcWTlHVs6RlXNk5Y4JeZ3QF9MCAICTG0dUAACAsWhUAACAsWhUAACAsWhUAACAsWhU2vDEE09o6NChOuWUU3TJJZfopZde8rokI23evFlTpkxRWlqafD6fNmzY4HVJxlq4cKG+/OUvKykpSampqbryyiv1zjvveF2WkZYtW6YLLrig6QOmLrvsMpWWlnpd1glh4cKF8vl8mj17ttelGGfevHny+XwxX2eddZbXZRkrHA7rO9/5js444wwlJiZq5MiRev311z2phUblGE8//bRmz56tu+66S2+88YbGjRungoIC7d271+vSjHPo0CFdeOGFeuyxx7wuxXihUEgzZszQ1q1bVVZWpoaGBuXl5enQoUNel2acQCCgX/ziF3rttdf02muv6Stf+Yq+/vWva+fOnV6XZrRt27Zp+fLluuCCC7wuxVjnn3++9u3b1/S1Y8cOr0sy0oEDBzR27FjFx8ertLRUb7/9th5++GGddtppntTD7cnHuPTSS3XxxRdr2bJlTWNZWVm68sortXDhQg8rM5vP59P69et15ZVXel3KCeHf//63UlNTFQqFNH78eK/LMd6gQYP00EMP6Xvf+57XpRjp008/1cUXX6wnnnhC9913n0aOHKnFixd7XZZR5s2bpw0bNmj79u1el2K8O++8U3/729+MOZvAEZUW6urq9PrrrysvLy9mPC8vTy+//LJHVeFkFIlEJNk7YLQvGo1qzZo1OnTokC677DKvyzHWjBkzdPnll2vSpElel2K09957T2lpaRo6dKi+/e1vq6KiwuuSjPTMM89o1KhRuvrqq5WamqqLLrpIK1as8KweGpUWPv74Y0WjUQ0ePDhmfPDgwfroo488qgonG8uyNGfOHGVnZ2v48OFel2OkHTt2aODAgUpISNDNN9+s9evXa9iwYV6XZaQ1a9bo73//O0d8O3DppZfqqaee0l/+8hetWLFCH330kcaMGaNPPvnE69KMU1FRoWXLlum8887TX/7yF91888269dZb9dRTT3lSzwn925N7is/ni1m2LKvVGNBZP/jBD/TWW29py5YtXpdirC9+8Yvavn27Dh48qHXr1un6669XKBSiWTlGZWWlZs2apeeff16nnHKK1+UYraCgoOn7ESNG6LLLLtPnP/95Pfnkk5ozZ46HlZnnyJEjGjVqlBYsWCBJuuiii7Rz504tW7ZM1113Xa/XwxGVFs4880z5/f5WR0/279/f6igL0BkzZ87UM888o02bNikQCHhdjrH69++vc889V6NGjdLChQt14YUXasmSJV6XZZzXX39d+/fv1yWXXKK4uDjFxcUpFArp0UcfVVxcnKLRqNclGmvAgAEaMWKE3nvvPa9LMc6QIUNa/VCQlZXl2U0lNCot9O/fX5dcconKyspixsvKyjRmzBiPqsLJwLIs/eAHP1BxcbFefPFFDR061OuSTiiWZam2ttbrMowzceJE7dixQ9u3b2/6GjVqlKZNm6bt27fL7/d7XaKxamtrtWvXLg0ZMsTrUowzduzYVh+f8O677+qcc87xpB5O/Rxjzpw5mj59ukaNGqXLLrtMy5cv1969e3XzzTd7XZpxPv30U73//vtNy7t379b27ds1aNAgnX322R5WZp4ZM2Zo9erV+tOf/qSkpKSmo3YpKSk69dRTPa7OLD/5yU9UUFCgYDCompoarVmzRuXl5Xruuee8Ls04SUlJra5zGjBggM444wyufzrGj370I02ZMkVnn3229u/fr/vuu0/V1dW6/vrrvS7NOD/84Q81ZswYLViwQN/85jf16quvavny5Vq+fLk3BVlo5fHHH7fOOeccq3///tbFF19shUIhr0sy0qZNmyxJrb6uv/56r0szTls5SbJ+85vfeF2acW644Yam99/nPvc5a+LEidbzzz/vdVknjJycHGvWrFlel2Gcb33rW9aQIUOs+Ph4Ky0tzSoqKrJ27tzpdVnG2rhxozV8+HArISHB+tKXvmQtX77cs1r4HBUAAGAsrlEBAADGolEBAADGolEBAADGolEBAADGolEBAADGolEBAADGolEBAADGolEBcMIrLy+Xz+fTwYMHvS4FQDejUQHQbaLRqMaMGaOrrroqZjwSiSgYDOqnP/1pjzzvmDFjtG/fPqWkpPTI4wPwDp9MC6Bbvffeexo5cqSWL1+uadOmSZKuu+46vfnmm9q2bZv69+/vcYUATiQcUQHQrc477zwtXLhQM2fO1Icffqg//elPWrNmjZ588sl2m5Q77rhDX/jCF5SYmKjMzEzdfffdqq+vl2T/5uRJkyYpPz9fjT9XHTx4UGeffbbuuusuSa1P/XzwwQeaMmWKTj/9dA0YMEDnn3++SkpKev4fD6Db8duTAXS7mTNnav369bruuuu0Y8cO3XPPPRo5cmS72yclJem3v/2t0tLStGPHDt14441KSkrSj3/8Y/l8Pj355JMaMWKEHn30Uc2aNUs333yzBg8erHnz5rX5eDNmzFBdXZ02b96sAQMG6O2339bAgQN75h8LoEdx6gdAj/jHP/6hrKwsjRgxQn//+98VF+f856KHHnpITz/9tF577bWmsT/+8Y+aPn265syZoyVLluiNN97QF77wBUn2EZUJEybowIEDOu2003TBBRfoqquu0s9+9rNu/3cB6F2c+gHQI1auXKnExETt3r1bVVVVkqSbb75ZAwcObPpqtHbtWmVnZ+uss87SwIEDdffdd2vv3r0xj3f11VerqKhICxcu1MMPP9zUpLTl1ltv1X333aexY8fqZz/7md56662e+UcC6HE0KgC63SuvvKJHHnlEf/rTn3TZZZfpe9/7nizL0r333qvt27c3fUnS1q1b9e1vf1sFBQX685//rDfeeEN33XWX6urqYh7z8OHDev311+X3+/Xee+8d9/m///3vq6KiQtOnT9eOHTs0atQoLV26tKf+uQB6EI0KgG712Wef6frrr9dNN92kSZMm6Ve/+pW2bdumX/7yl0pNTdW5557b9CVJf/vb33TOOeforrvu0qhRo3Teeefpgw8+aPW4t912m/r166fS0lI9+uijevHFF49bRzAY1M0336zi4mLddtttWrFiRY/8ewH0LBoVAN3qzjvv1JEjR/TAAw9Iks4++2w9/PDDuv3227Vnz55W25977rnau3ev1qxZo3/+85969NFHtX79+phtnn32Wa1cuVK///3vNXnyZN155526/vrrdeDAgTZrmD17tv7yl79o9+7d+vvf/64XX3xRWVlZ3f5vBdDzuJgWQLcJhUKaOHGiysvLlZ2dHbPuq1/9qhoaGvTXv/5VPp8vZt2Pf/xjrVy5UrW1tbr88ss1evRozZs3TwcPHtS///1vjRgxQrNmzdLcuXMlSQ0NDRo7dqwyMjL09NNPt7qYdubMmSotLVVVVZWSk5OVn5+vRx55RGeccUavZQGge9CoAAAAY3HqBwAAGItGBQAAGItGBQAAGItGBQAAGItGBQAAGItGBQAAGItGBQAAGItGBQAAGItGBQAAGItGBQAAGItGBQAAGItGBQAAGOv/A6dhTmoga6ECAAAAAElFTkSuQmCC",
+      "text/plain": [
+       "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[32m23:49:12.420:aoc2023 - INF: Tests passed!\u001b[39m\n", + "\u001b[34m23:49:12.519:aoc2023 - DBG: Processing 692 interior candidates.\u001b[39m\n", + "\u001b[34m23:49:12.527:aoc2023 - DBG: Updated exterior with 3191 points.\u001b[39m\n", + "\u001b[34m23:49:12.760:aoc2023 - DBG: Updated all_interior with 101645 points.\u001b[39m\n", + "\u001b[34m23:49:12.769:aoc2023 - DBG: Updated exterior with 2153 points.\u001b[39m\n", + "\u001b[34m23:49:12.785:aoc2023 - DBG: Updated exterior with 4665 points.\u001b[39m\n", + "\u001b[34m23:49:12.785:aoc2023 - DBG: Updated exterior with 47 points.\u001b[39m\n", + "\u001b[34m23:49:12.802:aoc2023 - DBG: Updated exterior with 6778 points.\u001b[39m\n", + "\u001b[34m23:49:12.810:aoc2023 - DBG: Updated exterior with 2824 points.\u001b[39m\n", + "\u001b[34m23:49:12.819:aoc2023 - DBG: Updated exterior with 1481 points.\u001b[39m\n", + "\u001b[34m23:49:12.827:aoc2023 - DBG: Updated exterior with 2103 points.\u001b[39m\n", + "\u001b[34m23:49:12.835:aoc2023 - DBG: Updated exterior with 2397 points.\u001b[39m\n", + "\u001b[34m23:49:12.843:aoc2023 - DBG: Updated exterior with 2047 points.\u001b[39m\n", + "\u001b[34m23:49:12.843:aoc2023 - DBG: Updated exterior with 105 points.\u001b[39m\n", + "\u001b[34m23:49:12.851:aoc2023 - DBG: Updated exterior with 1604 points.\u001b[39m\n", + "\u001b[34m23:49:12.852:aoc2023 - DBG: Updated exterior with 1009 points.\u001b[39m\n", + "\u001b[34m23:49:12.869:aoc2023 - DBG: Updated exterior with 4278 points.\u001b[39m\n", + "\u001b[34m23:49:12.869:aoc2023 - DBG: Updated exterior with 242 points.\u001b[39m\n", + "\u001b[34m23:49:12.881:aoc2023 - DBG: Updated exterior with 1431 points.\u001b[39m\n", + "\u001b[34m23:49:12.889:aoc2023 - DBG: Updated exterior with 1947 points.\u001b[39m\n", + "\u001b[34m23:49:12.907:aoc2023 - DBG: Updated exterior with 4837 points.\u001b[39m\n", + "\u001b[34m23:49:12.916:aoc2023 - DBG: Updated exterior with 1844 points.\u001b[39m\n", + "\u001b[34m23:49:12.921:aoc2023 - DBG: Updated exterior with 1021 points.\u001b[39m\n", + "\u001b[34m23:49:12.936:aoc2023 - DBG: Updated exterior with 3662 points.\u001b[39m\n", + "\u001b[34m23:49:12.941:aoc2023 - DBG: Updated exterior with 966 points.\u001b[39m\n", + "\u001b[34m23:49:12.961:aoc2023 - DBG: Updated exterior with 3090 points.\u001b[39m\n", + "\u001b[34m23:49:12.963:aoc2023 - DBG: Updated exterior with 92 points.\u001b[39m\n", + "\u001b[34m23:49:12.967:aoc2023 - DBG: Updated exterior with 569 points.\u001b[39m\n", + "\u001b[34m23:49:12.970:aoc2023 - DBG: Updated exterior with 322 points.\u001b[39m\n", + "\u001b[34m23:49:12.978:aoc2023 - DBG: Updated exterior with 1882 points.\u001b[39m\n", + "\u001b[34m23:49:12.979:aoc2023 - DBG: Updated exterior with 84 points.\u001b[39m\n", + "\u001b[34m23:49:12.981:aoc2023 - DBG: Updated exterior with 237 points.\u001b[39m\n", + "\u001b[34m23:49:12.985:aoc2023 - DBG: Updated exterior with 702 points.\u001b[39m\n", + "\u001b[34m23:49:12.986:aoc2023 - DBG: Updated exterior with 36 points.\u001b[39m\n", + "\u001b[34m23:49:12.992:aoc2023 - DBG: Updated exterior with 1427 points.\u001b[39m\n", + "\u001b[34m23:49:12.993:aoc2023 - DBG: Updated exterior with 108 points.\u001b[39m\n", + "\u001b[34m23:49:13.006:aoc2023 - DBG: Updated exterior with 2865 points.\u001b[39m\n", + "\u001b[34m23:49:13.007:aoc2023 - DBG: Updated exterior with 88 points.\u001b[39m\n", + "\u001b[34m23:49:13.009:aoc2023 - DBG: Updated exterior with 71 points.\u001b[39m\n", + "\u001b[34m23:49:13.021:aoc2023 - DBG: Updated exterior with 2849 points.\u001b[39m\n", + "\u001b[34m23:49:13.030:aoc2023 - DBG: Updated exterior with 1672 points.\u001b[39m\n", + "\u001b[34m23:49:13.032:aoc2023 - DBG: Updated exterior with 67 points.\u001b[39m\n", + "\u001b[34m23:49:13.033:aoc2023 - DBG: Updated exterior with 10 points.\u001b[39m\n", + "\u001b[34m23:49:13.034:aoc2023 - DBG: Updated exterior with 15 points.\u001b[39m\n", + "\u001b[34m23:49:13.036:aoc2023 - DBG: Updated exterior with 117 points.\u001b[39m\n", + "\u001b[34m23:49:13.037:aoc2023 - DBG: Updated exterior with 15 points.\u001b[39m\n", + "\u001b[34m23:49:13.038:aoc2023 - DBG: Updated exterior with 52 points.\u001b[39m\n", + "\u001b[34m23:49:13.045:aoc2023 - DBG: Updated exterior with 1768 points.\u001b[39m\n", + "\u001b[34m23:49:13.049:aoc2023 - DBG: Updated exterior with 307 points.\u001b[39m\n", + "\u001b[34m23:49:13.050:aoc2023 - DBG: Updated exterior with 207 points.\u001b[39m\n", + "\u001b[34m23:49:13.052:aoc2023 - DBG: Updated exterior with 56 points.\u001b[39m\n", + "\u001b[34m23:49:13.053:aoc2023 - DBG: Updated exterior with 84 points.\u001b[39m\n", + "\u001b[34m23:49:13.058:aoc2023 - DBG: Updated exterior with 990 points.\u001b[39m\n", + "\u001b[34m23:49:13.059:aoc2023 - DBG: Updated exterior with 39 points.\u001b[39m\n", + "\u001b[34m23:49:13.060:aoc2023 - DBG: Updated exterior with 14 points.\u001b[39m\n", + "\u001b[34m23:49:13.062:aoc2023 - DBG: Updated exterior with 241 points.\u001b[39m\n", + "\u001b[34m23:49:13.064:aoc2023 - DBG: Updated exterior with 7 points.\u001b[39m\n", + "\u001b[34m23:49:13.065:aoc2023 - DBG: Updated exterior with 19 points.\u001b[39m\n", + "\u001b[34m23:49:13.066:aoc2023 - DBG: Updated exterior with 87 points.\u001b[39m\n", + "\u001b[34m23:49:13.079:aoc2023 - DBG: Updated exterior with 2526 points.\u001b[39m\n" + ] + }, + { + "data": { + "image/png": "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QgghapHgSAghhBCiFgmOhBBCCCFqkeBICCGEEKIWCY502rt3L7feeivdu3cnNDSU3/zmNzz00ENUVFTU2W7//v1cc801hIeHExMTw5133tlgm927dzNw4EBCQ0Pp1KkTDz/8cIv1XnzdY489Rr9+/QgLC6N9+/aNbiPXTrvnnnuO7t2706ZNGy699FK2bdvm6SZ53NatW7nmmmtISEjAYrHw9ttv1/m5oijMnTuXhIQEQkNDSUpK4ttvv62zTXl5OVOnTiUmJobw8HD++te/cvDgQTe+Cs9YsGABl112GW3btqVjx45ce+21/Pjjj3W2kevXuOeff54//OEPNYkJ+/bty/vvv1/zc7lu2i1YsACLxcLdd99d85zbr58idHn//feV8ePHKx988IHyyy+/KBs2bFA6duyoTJ8+vWabqqoqpWfPnkpycrLy5ZdfKllZWUpCQoIyZcqUmm0KCwuVuLg45cYbb1R2796tZGRkKG3btlUWL17siZflNg8++KDyxBNPKNOmTVMiIyMb/FyunXbr1q1TgoKClBUrVijfffedctdddynh4eHKvn37PN00j3rvvfeU++67T8nIyFAAZf369XV+vnDhQqVt27ZKRkaGsnv3buWGG25QzjnnHKWoqKhmm9tuu03p1KmTkpWVpXz55ZdKcnKyctFFFylVVVVufjXuNWzYMOWVV15RvvnmG2XXrl3KVVddpXTt2lUpLi6u2UauX+Peeecd5d1331V+/PFH5ccff1TmzJmjBAUFKd98842iKHLdtPrss8+UxMRE5Q9/+INy11131Tzv7usnwZEJ0tPTle7du9c8fu+995SAgADl0KFDNc+98cYbSkhIiFJYWKgoiqI899xzSmRkpFJWVlazzYIFC5SEhATFbre7r/Ee8sorrzQaHMm10+5Pf/qTctttt9V57ne/+51y7733eqhF3qd+cGS325X4+Hhl4cKFNc+VlZUpkZGRygsvvKAoiqKcOnVKCQoKUtatW1ezzaFDh5SAgADlv//9r9va7g2OHz+uAMqWLVsURZHrp1eHDh2Ul156Sa6bRqdPn1bOP/98JSsrSxk4cGBNcOSJ6yfDaiYoLCwkKiqq5vH27dvp2bNnncJ2w4YNo7y8nC+++KJmm4EDB9ZJYjVs2DAOHz7M3r173dZ2byPXTpuKigq++OILhg4dWuf5oUOH8vHHH3uoVd5vz549HD16tM51CwkJYeDAgTXX7YsvvqCysrLONgkJCfTs2bPVXdvCwkKAms83uX7a2Gw21q1bR0lJCX379pXrptEdd9zBVVdd1aDWqSeunwRHTvrll19YunQpt912W81zR48eJS4urs52HTp0IDg4mKNHjza5jeOxY5vWSK6dNnl5edhstkavQ2u5BkY4rk1z1+3o0aMEBwfToUOHJrdpDRRFYdq0aVxxxRX07NkTkOvXkt27dxMREUFISAi33XYb69evp0ePHnLdNFi3bh1ffvklCxYsaPAzT1w/CY6qzZ07F4vF0uyfzz//vM4+hw8fZvjw4Vx33XVMmDChzs8sFkuDcyiKUuf5+tso1ROKG9vXmxm5ds1pTdfOWY1dh9Z2DYwwct1a27WdMmUKX3/9NW+88UaDn8n1a9wFF1zArl27+OSTT/jHP/7BuHHj+O6772p+LtetcQcOHOCuu+7itddeo02bNk1u587rF6h7Dz81ZcoUbrzxxma3SUxMrPn34cOHSU5Opm/fvixfvrzOdvHx8Xz66ad1njt58iSVlZU1kW98fHyDaPb48eNAw+jY2+m9ds1pbdfOqJiYGKxWa6PXobVcAyPi4+MB9VvmOeecU/N87esWHx9PRUUFJ0+erPMt9Pjx4/Tr18+9DfaQqVOn8s4777B161Y6d+5c87xcv+YFBwdz3nnnAdC7d2927NjB008/zT333APIdWvKF198wfHjx7n00ktrnrPZbGzdupVly5bVrJh06/XTPUtJKAcPHlTOP/985cYbb2x0FrxjUvHhw4drnlu3bl2DScXt27dXysvLa7ZZuHBhq5lU3NKEbLl2LfvTn/6k/OMf/6jz3IUXXigTsmuhiQnZjz/+eM1z5eXljU7sfPPNN2u2OXz4cKuYGGu325U77rhDSUhIUH766adGfy7XT7uUlBRl3Lhxct1aUFRUpOzevbvOn969eys333yzsnv3bo9cPwmOdDp06JBy3nnnKSkpKcrBgweVI0eO1PxxcCxHHzRokPLll18qmzZtUjp37lxnOfqpU6eUuLg45aabblJ2796tZGZmKu3atfP75ej79u1Tdu7cqcybN0+JiIhQdu7cqezcuVM5ffq0oihy7fRwLOV/+eWXle+++065++67lfDwcGXv3r2ebppHnT59uuZ9BShPPPGEsnPnzpoUBwsXLlQiIyOVzMxMZffu3cpNN93U6JLgzp07K5s2bVK+/PJLJSUlpVUsqf7HP/6hREZGKrm5uXU+286cOVOzjVy/xs2ePVvZunWrsmfPHuXrr79W5syZowQEBCgbN25UFEWum161V6spivuvnwRHOr3yyisK0Oif2vbt26dcddVVSmhoqBIVFaVMmTKlztJzRVGUr7/+Wunfv78SEhKixMfHK3PnzvX7no9x48Y1eu02b95cs41cO+2effZZpVu3bkpwcLDyxz/+sWbJdWu2efPmRt9j48aNUxRF7f146KGHlPj4eCUkJEQZMGCAsnv37jrHKC0tVaZMmaJERUUpoaGhytVXX63s37/fA6/GvZr6bHvllVdqtpHr17hbbrml5v9ibGysMmjQoJrASFHkuulVPzhy9/WzKEorTCsshBBCCNEEWa0mhBBCCFGLBEdCCCGEELVIcCSEEEIIUYsER0IIIYQQtUhwJIQQQghRiwRHQgghhBC1SHAkhBBCCFGLBEdCCGFAbm4uFouFU6dOebopQgiTSXAkhPBpNpuNfv36kZaWVuf5wsJCunTpwv333++S8/br148jR44QGRnpkuMLITxHMmQLIXze//73Py6++GKWL1/O6NGjARg7dixfffUVO3bsIDg42MMtFEL4Euk5EkL4vPPPP58FCxYwdepUDh8+zIYNG1i3bh2rV69uMjC65557+O1vf0tYWBjnnnsuDzzwAJWVlQAoisLgwYMZPnw4ju+Pp06domvXrtx3331Aw2G1ffv2cc0119ChQwfCw8P5/e9/z3vvvef6Fy+EMF2gpxsghBBmmDp1KuvXr2fs2LHs3r2bBx98kIsvvrjJ7du2bcuqVatISEhg9+7dTJw4kbZt2zJr1iwsFgurV6+mV69ePPPMM9x1113cdtttxMXFMXfu3EaPd8cdd1BRUcHWrVsJDw/nu+++IyIiwjUvVgjhUjKsJoTwGz/88AMXXnghvXr14ssvvyQwUPv3v0WLFvHmm2/y+eef1zz373//mzFjxjBt2jSefvppdu7cyW9/+1tA7TlKTk7m5MmTtG/fnj/84Q+kpaXx0EMPmf66hBDuJcNqQgi/sXLlSsLCwtizZw8HDx4E+P927R4kuSiAw/i/WsVFiJY+Bhsa2hwM3SpM2gTBJRwMcrECKQyJIoJoEMGmSNyChCgCQ4KQGqIg+qDG6EvaGmoqCql3euVI0dR9wZfnB2c6h3PvudMD9ygajcpms1XHX+vr6/J6vWppaZHNZtP09LTK5XLNfsFgUIFAQAsLC0qlUtUw+s7o6Kjm5+fl8Xg0MzOji4sLaw4JwHLEEYD/wuHhodLptLa2ttTT06NIJKLPz0/Nzc3p/Py8OiTp6OhIoVBIfr9fhUJBZ2dnSiaTen9/r9nz5eVFJycnampq0tXV1Y/PHx4e1s3NjYaGhnR5eSmXy6WlpSWrjgvAQsQRgLr3+vqqcDiskZER9fX1KZvN6vj4WMvLy2pubpbT6awOSTo4OFB7e7uSyaRcLpc6Ozt1f3//Zd94PK7GxkYVi0VlMhmVSqUf36O1tVXRaFQbGxuKx+NaWVmx5LwArEUcAah7iURCHx8fWlxclCS1tbUplUppYmJCd3d3X9Y7nU6Vy2Wtra3p+vpamUxGm5ubNWu2t7eVy+W0urqq/v5+JRIJhcNhPT09ffsO4+Pj2tnZ0e3trU5PT1UqldTV1fXrZwVgPS5kA6hr+/v76u3t1d7enrxeb82cz+dTpVLR7u6uGhoaauYmJyeVy+X09vamwcFBud1uzc7O6vn5WY+Pj+ru7tbY2JimpqYkSZVKRR6PRx0dHcrn818uZMdiMRWLRT08PMhut2tgYEDpdFoOh+OffQsAv4M4AgAAMPBbDQAAwEAcAQAAGIgjAAAAA3EEAABgII4AAAAMxBEAAICBOAIAADAQRwAAAAbiCAAAwEAcAQAAGIgjAAAAA3EEAABg+AMWz7Aw6iuEXQAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[32m23:49:14.089:aoc2023 - INF: Part 1 soln=106459\u001b[39m\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: total: 1.48 s\n", + "Wall time: 2 s\n" + ] + } + ], "source": [ "%%time\n", "sample_inputs = []\n", @@ -6476,29 +6771,23 @@ "\n", "**My solution:**\n", "\n", - "Even with the sample data, we're told that our lagoon will hold `952408144115` cubic metres of lava. So clearly we have far too many points to go storing them in sets. Our Part 1 solution isn't going to scale!\n", - "\n", - "We need to do something smarter. I'm thinking... 2D coordinate compression, to come up with a bunch of rectangles that ew can add together.\n", - "\n", - "_sigh_\n", + "Even with the sample data, we're told that our lagoon will hold `952408144115` cubic metres of lava. So clearly we have far too many points to go storing them in sets. Our Part 1 solution isn't going to scale! We need to do something smarter.\n", "\n", - "I described how this works back in [AoC 2021 Day 22](https://aoc.just2good.co.uk/2021/22):\n", + "- [Shoelace formulate](https://en.wikipedia.org/wiki/Shoelace_formula) - to calcualte the area of any polygon, given the consecutive coordinates of its vertices.\n", "\n", - "Coordinate compression is a technique where we take a large number of coordinates, and compress them down to fewer coordinates by eliminating all adjacent points where nothing interesting happens. As a really noddy example in one dimension:\n", - "\n", - "![1D coordinate compression](https://aoc.just2good.co.uk/assets/images/coord-compression.png)\n", - "\n", - "Here's a 2D example:\n", + "$$\n", + "A = \\frac{1}{2} \\left| \\sum_{i=1}^{n} x_i (y_{i+1} - y_{i-1}) \\right|\n", + "$$\n", "\n", - "![2D coordination compression](https://aoc.just2good.co.uk/assets/images/2d-reactor-compression.png)\n", + "- [Pick's theorem](https://en.wikipedia.org/wiki/Pick%27s_theorem) - to calculate the number of interior points for an enclosed polygon.\n", "\n", - "It's easy enough to parse the hex strings and convert to direction and length.\n", - "\n" + "$$\n", + "A = i + \\frac{b}{2} - 1" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 39, "metadata": {}, "outputs": [], "source": [ @@ -6516,24 +6805,22 @@ "\n", "def process_turns(plan):\n", " # initialise, from current\n", - " curr_x = 0\n", - " curr_y = 0\n", - " x_vals = [curr_x]\n", - " y_vals = [curr_y]\n", + " current = (0,0)\n", + " path = [current]\n", "\n", " for instr_num, (dirn_char, path_len) in enumerate(plan):\n", " logger.debug(f\"[{instr_num}]: {(dirn_char, path_len)}\")\n", " dirn = VectorDicts.DIRS[dirn_char]\n", - " curr_x += dirn[0]*path_len\n", - " curr_y += dirn[1]*path_len\n", - " x_vals.append(curr_x)\n", - " y_vals.append(curr_y) \n", + " current = (current[0]+dirn[0]*path_len, current[1]+dirn[1]*path_len)\n", + " path.append(current)\n", + "\n", + " logger.debug(path) \n", " " ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 36, "metadata": {}, "outputs": [], "source": [ @@ -6544,9 +6831,43 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[34m23:52:22.614:aoc2023 - DBG: [0]: ('R', 461937)\u001b[39m\n", + "\u001b[34m23:52:22.614:aoc2023 - DBG: [1]: ('D', 56407)\u001b[39m\n", + "\u001b[34m23:52:22.619:aoc2023 - DBG: [2]: ('R', 356671)\u001b[39m\n", + "\u001b[34m23:52:22.619:aoc2023 - DBG: [3]: ('D', 863240)\u001b[39m\n", + "\u001b[34m23:52:22.621:aoc2023 - DBG: [4]: ('R', 367720)\u001b[39m\n", + "\u001b[34m23:52:22.622:aoc2023 - DBG: [5]: ('D', 266681)\u001b[39m\n", + "\u001b[34m23:52:22.623:aoc2023 - DBG: [6]: ('L', 577262)\u001b[39m\n", + "\u001b[34m23:52:22.623:aoc2023 - DBG: [7]: ('U', 829975)\u001b[39m\n", + "\u001b[34m23:52:22.625:aoc2023 - DBG: [8]: ('L', 112010)\u001b[39m\n", + "\u001b[34m23:52:22.626:aoc2023 - DBG: [9]: ('D', 829975)\u001b[39m\n", + "\u001b[34m23:52:22.628:aoc2023 - DBG: [10]: ('L', 491645)\u001b[39m\n", + "\u001b[34m23:52:22.630:aoc2023 - DBG: [11]: ('U', 686074)\u001b[39m\n", + "\u001b[34m23:52:22.631:aoc2023 - DBG: [12]: ('L', 5411)\u001b[39m\n", + "\u001b[34m23:52:22.633:aoc2023 - DBG: [13]: ('U', 500254)\u001b[39m\n", + "\u001b[34m23:52:22.633:aoc2023 - DBG: [(0, 0), (461937, 0), (461937, 56407), (818608, 56407), (818608, 919647), (1186328, 919647), (1186328, 1186328), (609066, 1186328), (609066, 356353), (497056, 356353), (497056, 1186328), (5411, 1186328), (5411, 500254), (0, 500254), (0, 0)]\u001b[39m\n" + ] + }, + { + "ename": "AssertionError", + "evalue": "None != 952408144115", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mAssertionError\u001b[0m Traceback (most recent call last)", + "File \u001b[1;32m:4\u001b[0m\n", + "Cell \u001b[1;32mIn[16], line 8\u001b[0m, in \u001b[0;36mvalidate\u001b[1;34m(test, answer)\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 3\u001b[0m \u001b[38;5;124;03mArgs:\u001b[39;00m\n\u001b[0;32m 4\u001b[0m \u001b[38;5;124;03m test: the answer given by our solution\u001b[39;00m\n\u001b[0;32m 5\u001b[0m \u001b[38;5;124;03m answer: the expected answer, e.g. from instructions\u001b[39;00m\n\u001b[0;32m 6\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 7\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m test \u001b[38;5;241m!=\u001b[39m answer:\n\u001b[1;32m----> 8\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mAssertionError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mtest\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m != \u001b[39m\u001b[38;5;132;01m{\u001b[39;00manswer\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n", + "\u001b[1;31mAssertionError\u001b[0m: None != 952408144115" + ] + } + ], "source": [ "%%time\n", "sample_answers = [952408144115]\n", @@ -6924,7 +7245,331 @@ "metadata": {}, "source": [ "---\n", - "## Day n: title" + "## Day 20: Pulse Propagation" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "#### See [Day 20](https://adventofcode.com/2023/day/20)." + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "DAY = \"20\" # replace with actual number (without leading digit)\n", + "day_link = f\"#### See [Day {DAY}](https://adventofcode.com/{YEAR}/day/{DAY}).\"\n", + "display(Markdown(day_link))" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[32m06:09:16.472:aoc2023 - INF: Session cookie retrieved: 53616c...a18261\u001b[39m\n", + "\u001b[34m06:09:17.289:aoc2023 - DBG: Writing input file input.txt\u001b[39m\n", + "\u001b[32m06:09:17.289:aoc2023 - INF: Input data:\n", + " 1: %vh -> qc, rr\n", + " 2: &pb -> gf, gv, vp, qb, vr, hq, zj\n", + " 3: %zj -> kn, pb\n", + " 4: %mm -> dj\n", + " 5: %gp -> cp\n", + "...\n", + "54: %zs -> dq\n", + "55: %gv -> vr\n", + "56: &cq -> ns\n", + "57: %cp -> rr, jt\n", + "58: %xn -> pb, gf\u001b[39m\n" + ] + } + ], + "source": [ + "d_name = \"d\" + str(DAY).zfill(2) # e.g. d01\n", + "script_name = \"aoc\" + str(YEAR) + d_name # e.g. aoc2017d01\n", + "locations = get_locations(d_name)\n", + "\n", + "# SETUP LOGGING\n", + "logger.setLevel(logging.DEBUG)\n", + "# td.setup_file_logging(logger, locations.output_dir)\n", + "\n", + "# Retrieve input and store in local file\n", + "try:\n", + " write_puzzle_input_file(YEAR, DAY, locations)\n", + " with open(locations.input_file, mode=\"rt\") as f:\n", + " input_data = f.read().splitlines()\n", + "\n", + " logger.info(\"Input data:\\n%s\", top_and_tail(input_data))\n", + "except ValueError as e:\n", + " logger.error(e)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Day 20 Part 1\n", + "\n", + "Modules communicate using pulses. \n", + "\n", + "- There are two types of pulses: `high` and `low`. \n", + "- For any given module, each pulse is sent to a list of destination modules. \n", + "- _Flip-flop_ modules (prefix `%`) are either on or off. \n", + " - They are initially off. \n", + " - If it receives a `low` pulse it flips. When it flips on, it sends a `high` pulse. When it flips off, it sends a `low` pulse.\n", + " - If it receives a `high`, it does nothing.\n", + "- _Conjunction_ modules (prefix `&`) remember the type of pulse received from each of its inputs. They initially default to remembering `low` pulse. When it receives a pulse, it updates its memory state, and then:\n", + " - If all inputs remembered are `high`, it sends a `low`.\n", + " - Otherwise it sends a `high`.\n", + "- There is one _broadcast_ module. When it receives a pulse, it sends the same pulse to all of its destinations.\n", + "- There is a _button_ module. When pressed, it sends `low` to _broadcast_.\n", + "- Modules are processed in the order they are sent. (So, breadth first, rather than depth first.)\n", + "\n", + "Sample configuration:\n", + "\n", + "```text\n", + "broadcaster -> a, b, c\n", + "%a -> b\n", + "%b -> c\n", + "%c -> inv\n", + "&inv -> a\n", + "```\n", + "\n", + "**Consult your module configuration; determine the number of low pulses and high pulses that would be sent after pushing the button 1000 times, waiting for all pulses to be fully handled after each push of the button. What do you get if you multiply the total number of low pulses sent by the total number of high pulses sent?**\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 174, + "metadata": {}, + "outputs": [], + "source": [ + "@dataclass\n", + "class Module(abc.ABC):\n", + " id: str\n", + " inputs: list[Module] = field(default_factory=list)\n", + " outputs: list[Module] = field(default_factory=list)\n", + " low_sent: int = 0\n", + " high_sent: int = 0\n", + "\n", + " def add_input(self, module: Module):\n", + " self.inputs.append(module)\n", + "\n", + " def add_output(self, module: Module):\n", + " self.outputs.append(module)\n", + "\n", + " def _send_pulse(self, pulse: int):\n", + " # logger.debug(f\"{self.id} -> {pulse} -> {[mod.id for mod in self.outputs]}\")\n", + " for mod in self.outputs:\n", + " if pulse == 0:\n", + " self.low_sent += 1\n", + " else:\n", + " self.high_sent += 1\n", + " mod.pulse_received(self, pulse)\n", + "\n", + " @abc.abstractmethod\n", + " def send_pulse(self):\n", + " pass\n", + "\n", + " @abc.abstractmethod\n", + " def pulse_received(self, in_module: Module, pulse: int):\n", + " pass\n", + "\n", + " def __str__(self) -> str:\n", + " input_ids = [input_module.id for input_module in self.inputs]\n", + " output_ids = [output_module.id for output_module in self.outputs]\n", + " return f\"Module(id={self.id}, inputs={input_ids}, outputs={output_ids})\"\n", + "\n", + "class FlipFlop(Module):\n", + " state:bool = False # initially off\n", + "\n", + " def send_pulse(self):\n", + " pulse = 1 if self.state else 0\n", + " self._send_pulse(pulse)\n", + "\n", + " def pulse_received(self, in_module: Module, pulse: int):\n", + " if pulse == 0:\n", + " self.state = not self.state\n", + " self.send_pulse()\n", + " \n", + " def __str__(self):\n", + " return f\"{super().__str__()}, state={self.state}\"\n", + "\n", + "class Conjunction(Module):\n", + " state: dict[str, int] = {}\n", + "\n", + " def add_input(self, module: Module):\n", + " super().add_input(module)\n", + " self.state[module.id] = 0\n", + "\n", + " def pulse_received(self, in_module: Module, pulse: int):\n", + " self.state[in_module.id] = pulse\n", + " self.send_pulse()\n", + "\n", + " def send_pulse(self):\n", + " input_mod_ids = [input_mod.id for input_mod in self.inputs]\n", + " pulse = 0 if all(self.state[id] for id in input_mod_ids) else 1\n", + " self._send_pulse(pulse)\n", + "\n", + " def __str__(self):\n", + " return f\"{super().__str__()}, state={self.state}\"\n", + "\n", + "class Broadcaster(Module):\n", + " received:int\n", + "\n", + " def pulse_received(self, in_module: Module, pulse: int):\n", + " self.received = pulse\n", + " self.send_pulse()\n", + " \n", + " def send_pulse(self):\n", + " self._send_pulse(self.received)\n", + "\n", + "class Button(Module):\n", + " def send_pulse(self):\n", + " self._send_pulse(0) # always sends 0 to broadcast\n", + "\n", + " def pulse_received(self, in_module: Module, pulse: int):\n", + " pass\n", + "\n", + " def push(self):\n", + " self.send_pulse()\n", + " \n", + "class Output(Module):\n", + " def send_pulse(self):\n", + " pass\n", + "\n", + " def pulse_received(self, in_module: Module, pulse: int):\n", + " pass" + ] + }, + { + "cell_type": "code", + "execution_count": 181, + "metadata": {}, + "outputs": [], + "source": [ + "def solve_part1(data):\n", + " modules:dict[str, Module] = {}\n", + "\n", + " # create the modules\n", + " for line in data:\n", + " mod_part, outputs_part = line.split(\" -> \")\n", + " if mod_part[0] == \"%\":\n", + " modules[mod_part[1:]] = FlipFlop(mod_part[1:])\n", + " elif mod_part[0] == \"&\":\n", + " modules[mod_part[1:]] = Conjunction(mod_part[1:])\n", + " else:\n", + " assert mod_part == \"broadcaster\", \"This must be a broadcaster module\"\n", + " modules[mod_part] = Broadcaster(mod_part)\n", + "\n", + " # now register inputs and outputs\n", + " for line in data:\n", + " mod_part, outputs_part = line.split(\" -> \")\n", + " if mod_part == \"broadcaster\":\n", + " module = modules[mod_part]\n", + " else:\n", + " module = modules[mod_part[1:]]\n", + "\n", + " output_names = [name.strip() for name in outputs_part.split(\",\")]\n", + "\n", + " # check for outputs that aren't inputs\n", + " for output_name in output_names:\n", + " if output_name not in modules:\n", + " modules[output_name] = Output(output_name)\n", + "\n", + " module.add_output(modules[output_name])\n", + " modules[output_name].add_input(module)\n", + "\n", + " button = Button(\"button\")\n", + " modules[button.id] = button\n", + " button.add_output(modules[\"broadcaster\"])\n", + " for _ in range(1000):\n", + " button.push()\n", + "\n", + " low_sent = sum(module.low_sent for module in modules.values())\n", + " high_sent = sum(module.high_sent for module in modules.values())\n", + " logger.debug(f\"{low_sent=}, {high_sent=}\")\n", + " prod = low_sent*high_sent\n", + " logger.debug(f\"{prod=}\")\n", + " return prod\n" + ] + }, + { + "cell_type": "code", + "execution_count": 182, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[34m09:40:28.754:aoc2023 - DBG: low_sent=8000, high_sent=4000\u001b[39m\n", + "\u001b[34m09:40:28.754:aoc2023 - DBG: prod=32000000\u001b[39m\n", + "\u001b[34m09:40:28.754:aoc2023 - DBG: low_sent=4250, high_sent=2750\u001b[39m\n", + "\u001b[34m09:40:28.754:aoc2023 - DBG: prod=11687500\u001b[39m\n", + "\u001b[32m09:40:28.754:aoc2023 - INF: Tests passed!\u001b[39m\n", + "\u001b[34m09:40:28.810:aoc2023 - DBG: low_sent=17913, high_sent=50172\u001b[39m\n", + "\u001b[34m09:40:28.812:aoc2023 - DBG: prod=898731036\u001b[39m\n", + "\u001b[32m09:40:28.812:aoc2023 - INF: Part 1 soln=898731036\u001b[39m\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: total: 62.5 ms\n", + "Wall time: 61.6 ms\n" + ] + } + ], + "source": [ + "%%time\n", + "sample_inputs = []\n", + "sample_inputs.append(\"\"\"broadcaster -> a, b, c\n", + "%a -> b\n", + "%b -> c\n", + "%c -> inv\n", + "&inv -> a\"\"\")\n", + "\n", + "sample_inputs.append(\"\"\"broadcaster -> a\n", + "%a -> inv, con\n", + "&inv -> b\n", + "%b -> con\n", + "&con -> output\"\"\")\n", + "\n", + "sample_answers = [32000000, 11687500]\n", + "\n", + "for curr_input, curr_ans in zip(sample_inputs, sample_answers):\n", + " validate(solve_part1(curr_input.splitlines()), curr_ans) # test with sample data\n", + "\n", + "logger.info(\"Tests passed!\")\n", + "\n", + "soln = solve_part1(input_data)\n", + "logger.info(f\"Part 1 soln={soln}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Day 20 Part 2\n", + "\n", + "Overview..." ] }, { @@ -6932,6 +7577,56 @@ "execution_count": null, "metadata": {}, "outputs": [], + "source": [ + "def solve_part2(data):\n", + " pass" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%time\n", + "sample_inputs = [\"abcdef\"]\n", + "sample_answers = [\"uvwxyz\"]\n", + "\n", + "for curr_input, curr_ans in zip(sample_inputs, sample_answers):\n", + " validate(solve_part2(curr_input), curr_ans) # test with sample data\n", + "\n", + "logger.info(\"Tests passed!\")\n", + "\n", + "soln = solve_part2(input_data)\n", + "logger.info(f\"Part 2 soln={soln}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "## Day n: title" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "#### See [Day n](https://adventofcode.com/2023/day/n)." + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "DAY = \"n\" # replace with actual number (without leading digit)\n", "day_link = f\"#### See [Day {DAY}](https://adventofcode.com/{YEAR}/day/{DAY}).\"\n", diff --git a/src/AoC_2023/d20/input/input.txt b/src/AoC_2023/d20/input/input.txt new file mode 100644 index 0000000000000000000000000000000000000000..d737af3c302ebab0f4459d43e96b879b46d85ced GIT binary patch literal 872 zcmV-u1DE^&M@dveQdv+`0BkCXfWW8xmLg-lA-P+YbN#IkC&EuG@3G>ynla5YQ;maz z{G&A`ABBeY=zQ|}S;nF&BX$mZ;~d?-uo2;22ULQfSl2ML`69ybfxdRH12{`8UCGcr zDv4H?bA7A*(yC5(I-UDiG+F=)Cs%G;eywWX^rxNe$rb2Td7sACK3^(L;xJGm>9j@QO2J8YoCHs5zvEynQhs(?x!5E}=zaM?;qtZsm4nZfV6Au(eSLxz-vJm^7as2 zAbbQKZDY<}up9_t6tl7e`(lq}wM8~_3+>r9;4&O1T!InteVRhy=cC8~YJBe{1?N=M zLl{A8c|AL-rC7TET7N_#mb9kN-an zPWe^cKVNJC6P!uRxxwuXC&w{nOHr66UaITeNOPA;^AoH&MZ#>$vMtwi@%9>oW8Uv+ z3>D=hG%JX2x}?;Ezp?h4V|`Zj>a)+SZC79~rZ6y{lSFZ@{(54|#K1{adzV!=kONxD zkxQ0Q)5dn0GbHeRsv8;kjLIv&+IX}JFv0s>@weGo?q8x5`bBApz4uH~OUC^GyVlrj y^pmDTgR>n=%4Wz(=~aJ#k2@}MF$Y8Ki@^+j339T+rvqNab4}}fNJoe;_V{#3C%0q( literal 0 HcmV?d00001