From c020a7a52d658b80092dde3d3f5fca2f8d918452 Mon Sep 17 00:00:00 2001 From: Dazbo Date: Thu, 5 Dec 2024 16:54:44 +0000 Subject: [PATCH] Starting d5 --- .../Dazbo's_Advent_of_Code_2024.ipynb | 295 +++++++++++++++++- src/AoC_2024/d05/input/input.txt | Bin 0 -> 16068 bytes 2 files changed, 293 insertions(+), 2 deletions(-) create mode 100644 src/AoC_2024/d05/input/input.txt diff --git a/src/AoC_2024/Dazbo's_Advent_of_Code_2024.ipynb b/src/AoC_2024/Dazbo's_Advent_of_Code_2024.ipynb index 3dc92d5..5907b15 100644 --- a/src/AoC_2024/Dazbo's_Advent_of_Code_2024.ipynb +++ b/src/AoC_2024/Dazbo's_Advent_of_Code_2024.ipynb @@ -1502,6 +1502,297 @@ "logger.info(f\"Part 2 soln={soln}\")" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "## Day 5: Print Queue" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "DAY = \"5\" # 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": null, + "metadata": {}, + "outputs": [], + "source": [ + "d_name = \"d\" + str(DAY).zfill(2) # e.g. d01\n", + "script_name = \"aoc\" + str(YEAR) + d_name # e.g. aoc2024d01\n", + "locations = dc.get_locations(d_name)\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\", dc.top_and_tail(input_data))\n", + "except ValueError as e:\n", + " logger.error(e)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Day 5 Part 1\n", + "\n", + "Out input is in two blocks:\n", + "\n", + "1. The page order rules - one rule per line. These are pairs of rules, e.g. `47|53`. This means that `if` an update contains *both* of these page numbers, then page `47` must be printed at some point *before* `53`.\n", + "1. The specified page numbers required in a particular update - one update set per line.\n", + "\n", + "The sample input:\n", + "\n", + "```text\n", + "47|53\n", + "97|13\n", + "97|61\n", + "97|47\n", + "75|29\n", + "61|13\n", + "75|53\n", + "29|13\n", + "97|29\n", + "53|29\n", + "61|53\n", + "97|53\n", + "61|29\n", + "47|13\n", + "75|47\n", + "97|75\n", + "47|61\n", + "75|61\n", + "47|29\n", + "75|13\n", + "53|13\n", + "\n", + "75,47,61,53,29\n", + "97,61,53,29,13\n", + "75,29,13\n", + "75,97,47,61,53\n", + "61,13,29\n", + "97,13,75,29,47\n", + "```\n", + "\n", + "**What is the sum of middle page numbers from only the updates are correctly ordered?**\n", + "\n", + "#### Solution Approach\n", + "\n", + "Rules for a given update:\n", + "\n", + "- For any page number N, there should be a rule `B|N` for every `B` that comes BEFORE it.\n", + "- For any page number N, there must NOT be a rule `B|N` for any `B` that comes AFTER it.\n", + "- For any page number N, there should be a rule `N|A` for every `A` that comes AFTER it.\n", + "- For any page number N, there must NOT be a rule `N|A` for any `A` that comes BEFORE it.\n", + "\n", + "- The rules appear to be a complete set, meaning that there wil be a rule for _every_ possible pair of pages. (?)\n", + "- A given update does necessarily include every page and therefore does not need to include every rule.\n", + "\n", + "Let's:\n", + "\n", + "- Build a dictionary mapping " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class PageOrdering():\n", + " \n", + " def __init__(self, data: str) -> None:\n", + " \n", + " comes_after, comes_before, updates = self._process_data(data)\n", + " self._comes_after = comes_after\n", + " self._comes_before = comes_before\n", + " self._updates = updates\n", + " \n", + " @property\n", + " def updates(self):\n", + " return self._updates\n", + " \n", + " def _test_comes_before(self, update: list[int]):\n", + " \"\"\"\n", + " - For any page number N, there should be a rule `B|N` for every `B` that comes BEFORE it.\n", + " - For any page number N, there must NOT be a rule `B|N` for any `B` that comes AFTER it.\n", + " - For any page number N, there should be a rule `N|A` for every `A` that comes AFTER it.\n", + " - For any page number N, there must NOT be a rule `N|A` for any `A` that comes BEFORE it.\n", + " \"\"\"\n", + " for page in enumerate(update):\n", + " if \n", + " \n", + " \n", + " def _process_data(self, data: str):\n", + " comes_after = {}\n", + " comes_before = {}\n", + " updates = [] \n", + " \n", + " # split into blocks.\n", + " rules_block, updates_block = data.split(\"\\n\\n\") \n", + " \n", + " # build two-way adjacency dictionary\n", + " for rule in rules_block.splitlines():\n", + " x, y = list(map(int, rule.split(\"|\")))\n", + " comes_after[x] = y\n", + " comes_before[y] = x\n", + " \n", + " # Turn updates block into list of lists\n", + " updates = [[int(x) for x in update_line.split(\",\")] for update_line in updates_block.splitlines()]\n", + " \n", + " return comes_after, comes_before, updates\n", + " \n", + " def __repr__(self) -> str:\n", + " return f\"PageOrdering(rules_len={len(self._comes_before)},updates_len={len(self._updates)})\"\n", + "\n", + " def __str__(self) -> str:\n", + " return \"\\n\".join(\",\".join(map(str, update_row)) for update_row in self._updates) \n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def solve_part1(data):\n", + " page_ordering = PageOrdering(data)\n", + " logger.debug(page_ordering)\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%time\n", + "sample_inputs = []\n", + "sample_inputs.append(\"\"\"\\\n", + "47|53\n", + "97|13\n", + "97|61\n", + "97|47\n", + "75|29\n", + "61|13\n", + "75|53\n", + "29|13\n", + "97|29\n", + "53|29\n", + "61|53\n", + "97|53\n", + "61|29\n", + "47|13\n", + "75|47\n", + "97|75\n", + "47|61\n", + "75|61\n", + "47|29\n", + "75|13\n", + "53|13\n", + "\n", + "75,47,61,53,29\n", + "97,61,53,29,13\n", + "75,29,13\n", + "75,97,47,61,53\n", + "61,13,29\n", + "97,13,75,29,47\"\"\")\n", + "sample_answers = [143]\n", + "\n", + "for curr_input, curr_ans in zip(sample_inputs, sample_answers):\n", + " validate(solve_part1(curr_input), curr_ans) # test with sample data\n", + " logger.info(\"Test passed\")\n", + "\n", + "logger.info(\"All tests passed!\")\n", + "\n", + "soln = solve_part1(input_data)\n", + "logger.info(f\"Part 1 soln={soln}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Day 5 Part 2\n", + "\n", + "Overview..." + ] + }, + { + "cell_type": "code", + "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 = []\n", + "sample_inputs.append(\"\"\"\\\n", + "47|53\n", + "97|13\n", + "97|61\n", + "97|47\n", + "75|29\n", + "61|13\n", + "75|53\n", + "29|13\n", + "97|29\n", + "53|29\n", + "61|53\n", + "97|53\n", + "61|29\n", + "47|13\n", + "75|47\n", + "97|75\n", + "47|61\n", + "75|61\n", + "47|29\n", + "75|13\n", + "53|13\n", + "\n", + "75,47,61,53,29\n", + "97,61,53,29,13\n", + "75,29,13\n", + "75,97,47,61,53\n", + "61,13,29\n", + "97,13,75,29,47\"\"\")\n", + "sample_answers = [143]\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", + " logger.info(\"Test passed\") \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": {}, @@ -1633,7 +1924,7 @@ "toc_visible": true }, "kernelspec": { - "display_name": ".aoc-env", + "display_name": ".AoC-env", "language": "python", "name": "python3" }, @@ -1647,7 +1938,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.6" + "version": "3.11.9" }, "toc-autonumbering": false, "toc-showcode": false, diff --git a/src/AoC_2024/d05/input/input.txt b/src/AoC_2024/d05/input/input.txt new file mode 100644 index 0000000000000000000000000000000000000000..13caea096abf42f4150e199e883d17e385939d7a GIT binary patch literal 16068 zcmV;#K0CnxM@dveQdv+`0Og0cWAU|O|4F>u$^ZziDJ`=0LHy)_m;0Km3qahJ*VI+R z!+}gdMpP(8(w^>K#)#6nX)Su^oQ*ipZ`o;V_0!cpt#)3|fuubylW7|zuf?n#E16v?=+H&oeF zzYCZ5tob$b$)G{Wt_IKdI5&JeXeva9ZU&$YlN(DU~O+KK5FsSPnlG1&r;tZ(4ndn(oH%BWbeMucksp;75FFW9}TcS zkpbtpTFl=ZqQ%VaU_P>p@ZV)`)^yTySv6oZa?}*fSai-;Pg-(M=+~9HFBzti& z5AS>z55@fJ(xcXYnO{Yu>^XK$YcTY6?>kC2&=JH#r?yS#T20V&8?vkSzM* z%SZ0b|5N~YcaJmEBpfb(xO@w>N#`j?!PntO(ZNod%$T}7>SIQmJ#!|9rV}2PYZtXV zDqxj*bsE2J5Cx8iG}`jM#Vw4d^7mXkz<`(w>NJ0|&m`DhmVCa8D4nL+Q?66!8~0ev z`g1!3K-#NcNs^L3)3C%sIOGa7jC7#>6-*pb$fgmm+&OXRdEhMw&SmJ_tl!Sr-}CzK z(0%skp^nuP%fpyC8}>B9hX2D1!JGUH2(>!@zOe9%!f;uy8B0x8IHFo-DBA!c{s z&@|yIZ)Ik`q?T23>F(?1M*M=$i5rYb7W_1IJO|DY@WMd%k#vOsvUMrucVFgcq;vEi zBz7JcR=V_^@$lcK=C!}}B;NY!DkI3L+0D>FD!YpiY^lY;$NK&$Y+_0;ckgXU7 z-%Vkm^&wR!-rAFT+`jorwN10WOTcea(I@X>K3n+|@MFcRkJoN?rHN|*gw=+Gy8cIY zC7{I@f=tA5W!#>1M`pl+X0{^Hc}%pVNM76mP$O&r(}YZ@wBt%!bY)fGEEaf~wl&e# zJev-7p9=h^mRfK#2L5s**0^8LluK$xdQahj)iv_nXAyi7=AHt1fMZK5+o&&4i_E-M zq~l_TiQe!L*?=vh?S44;lmJi--66m}^jFGV$6P9T4br@vcwI4m-NHFOEnyaGvoyKe zeRTh)@n$vAj`m#;KQY0)Q_2RuNa6i$WjrgP*>pbTbyA#~bS#X2gT#T%bN9u?%S~-o zJ{h&=Pql>NU8NV>jGJT5@`rHx1%QUq28MX*GJxVYi5Xy10Xe>gN#)+g&M->cO%{|E zW57mnxXKVBv}Qz2XW!^gL}`^WqxU8Zq!h^^TwU}t_cdqin!uXQ&y5@8U`f~;ALPuc zYb!FKYfJ*< zqZ?u|(G~_2gjT%lG^Xf|@QvBHlG�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