Skip to content

Commit

Permalink
Starting d22
Browse files Browse the repository at this point in the history
  • Loading branch information
derailed-dash committed Dec 22, 2023
1 parent 98d3c38 commit 57a05be
Show file tree
Hide file tree
Showing 2 changed files with 224 additions and 1 deletion.
225 changes: 224 additions & 1 deletion src/AoC_2023/Dazbo's_Advent_of_Code_2023.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
"source": [
"from __future__ import annotations\n",
"from dataclasses import asdict, dataclass, field\n",
"from typing import Optional, cast\n",
"from typing import Optional, Callable, cast\n",
"from enum import Enum, auto\n",
"from functools import cache, reduce\n",
"from itertools import permutations, combinations, count, cycle\n",
Expand Down Expand Up @@ -8090,6 +8090,229 @@
"logger.info(f\"Part 2 soln={soln}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"## Day 22: Sand Slabs"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"DAY = \"22\" # 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. 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 22 Part 1\n",
"\n",
"We need to disintegrate bricks of sand into free flowing sand. The bricks are falling into a stack.\n",
"\n",
"We have a snaptshot of the bricks whilst they were falling. The example looks like this:\n",
"\n",
"```text\n",
"1,0,1~1,2,1\n",
"0,0,2~2,0,2\n",
"0,2,3~2,2,3\n",
"0,0,4~0,2,4\n",
"2,0,5~2,2,5\n",
"0,1,6~2,1,6\n",
"1,1,8~1,1,9\n",
"```\n",
"\n",
"- Each row represents two 3D coordinates, `x,y,z`. Each coordinate is a cube. Thus, each brick can be represented as a number of cubes.\n",
" - The z-axis extends up into their air, whereas the x and y axes represent a plane at any given value of z.\n",
" - 2,2,2~2,2,2: This is a single cube brick.\n",
" - 0,0,10~1,0,10: This is a two cube brick, oriented horizontally. I.e. the x axis has coordinates 0 and 1.\n",
" - 0,0,1~0,0,10: This is a 10-cube brick, oriented vertically. I.e. the y axis is from 1 to 10 inclusive.\n",
"- The ground is at `z=0`.\n",
"- The lowest possible z coordinate of a brick is 1.\n",
"- The input shows the order the bricks fell. I.e. FIFO with the first at the top. \n",
"- Some bricks are still falling through the air!! For example, there is a one unit z gap between the last two bricks.\n",
"- Bricks always fall with constant orientation. I.e. only their z value will change as they fall.\n",
"\n",
"Oh god. It's Jenga!\n",
"\n",
"**Figure how the blocks will settle based on the snapshot. Once they've settled, consider disintegrating a single brick; how many bricks could be safely chosen as the one to get disintegrated?**\n",
"\n",
"**My solution:**\n",
"\n",
"We need to:\n",
"\n",
"- Determine the configuration of the bricks once they've settled.\n",
"- Determine which bricks then support other bricks.\n",
"- We can disintegrate any bricks that are not the sole support of another brick.\n",
"\n",
"Approach:\n",
"\n",
"- We can settle bricks based on occupied coordinates. Looking at the real input, I can see that that bricks dimensions are always single digit, so we should be okay to store occupied locations in a set. I.e. the set volume space won't get too huge.\n",
"- Then, we can build a graph to represent the support network.\n",
"\n",
"First, a `Brick` class:\n",
"\n",
"- Stores the two corners.\n",
"- Can determine it's lower and upper values of any axis.\n",
"- Can update its z values (i.e. as it falls)\n",
"- Can return the inclusive range of any axis.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"@dataclass\n",
"class Brick():\n",
" corner_1: tuple[int,int,int]\n",
" corner_2: tuple[int,int,int]\n",
" \n",
" def max_for_axis(self, axis: int):\n",
" return self._axis_limit(max, axis)\n",
" \n",
" def min_for_axis(self, axis: int):\n",
" return self._axis_limit(min, axis)\n",
" \n",
" def _axis_limit(self, op: Callable, axis: int):\n",
" return op(self.corner_1[axis], self.corner_2[axis])\n",
" \n",
" def update_z(self, new_bottom_z: int):\n",
" z_delta = self.min_for_axis(2) - new_bottom_z\n",
" self.corner_1 = (self.corner_1[0], self.corner_1[1], self.corner_1[2] - z_delta)\n",
" self.corner_2 = (self.corner_2[0], self.corner_2[1], self.corner_2[2] - z_delta)\n",
" \n",
" def get_dim_range(self, axis: int):\n",
" return (self.min_for_axis(axis), self.max_for_axis(axis))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def parse_bricks(data: list[str]) -> list[Brick]: \n",
" bricks = []\n",
" for line in data:\n",
" corner_1, corner_2 = line.split(\"~\")\n",
" (x1, y1, z1) = [int(val) for val in corner_1.split(\",\")]\n",
" (x2, y2, z2) = [int(val) for val in corner_2.split(\",\")]\n",
" bricks.append(Brick((x1, y1, z1), (x2, y2, z2)))\n",
" \n",
" return bricks"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def solve_part1(data):\n",
" bricks = parse_bricks(data)\n",
" \n",
" for brick in bricks:\n",
" logger.debug(f\"{brick=}\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%%time\n",
"sample_inputs = []\n",
"sample_inputs.append(\"\"\"1,0,1~1,2,1\n",
"0,0,2~2,0,2\n",
"0,2,3~2,2,3\n",
"0,0,4~0,2,4\n",
"2,0,5~2,2,5\n",
"0,1,6~2,1,6\n",
"1,1,8~1,1,9\"\"\")\n",
"sample_answers = [5]\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 22 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 = [\"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": {},
Expand Down
Binary file added src/AoC_2023/d22/input/input.txt
Binary file not shown.

0 comments on commit 57a05be

Please sign in to comment.