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 0000000..13caea0 Binary files /dev/null and b/src/AoC_2024/d05/input/input.txt differ