Skip to content

Commit

Permalink
Day 8: use cycle & add a section about different ways to choose direc…
Browse files Browse the repository at this point in the history
…tion
  • Loading branch information
Hamatti committed Dec 8, 2023
1 parent c2ff8bf commit 520be59
Showing 1 changed file with 59 additions and 11 deletions.
70 changes: 59 additions & 11 deletions src/day_8.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,14 @@
"source": [
"To solve this puzzle, I start with node `AAA` and loop until I have stepped into `ZZZ`.\n",
"\n",
"To keep `instructions` running even if it runs out, I use _math_. Using modulo operator (`%`) with a length of a list is a good way to keep the index bound between 0 and length of list - 1.\n",
"To keep `instructions` running even if it runs out, I use [itertools.cycle](https://docs.python.org/3/library/itertools.html#itertools.cycle).\n",
"\n",
"I them pattern match against the instructions and either take the first or the second of the next values. In part 2 I realized that pattern matching was bit too much here since we just have two values but I wanted to leave it here so you can compare it with the if/else choice in part 2."
]
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 9,
"id": "fd4c01ea",
"metadata": {},
"outputs": [
Expand All @@ -106,13 +106,14 @@
}
],
"source": [
"from itertools import cycle\n",
"\n",
"def solve_part_1(instructions, the_map):\n",
" current = 'AAA'\n",
" end = 'ZZZ'\n",
"\n",
" steps = 0\n",
" while True:\n",
" instruction = instructions[steps % len(instructions)]\n",
" for instruction in cycle(instructions):\n",
" steps += 1\n",
" match instruction:\n",
" case 'L':\n",
Expand Down Expand Up @@ -191,7 +192,7 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 12,
"id": "0d499914",
"metadata": {},
"outputs": [
Expand All @@ -205,18 +206,18 @@
],
"source": [
"import math\n",
"from itertools import cycle\n",
"\n",
"\n",
"def find_loop(node, the_map):\n",
"def find_loop(node, the_map, instructions):\n",
" sequence = []\n",
" step = 0\n",
" while True:\n",
" mod_step = step % len(instructions)\n",
" \n",
" instruction = instructions[mod_step]\n",
" instructions_length = len(instructions)\n",
" for instruction in cycle(instructions):\n",
" idx = 0 if instruction == 'L' else 1\n",
" node = the_map[node][idx]\n",
" \n",
" mod_step = step % instructions_length\n",
" if (mod_step, node) in sequence:\n",
" return step, sequence\n",
" \n",
Expand All @@ -232,7 +233,7 @@
"start_nodes = [key for key in the_map if key.endswith('A')]\n",
"last_z_in_each_loop = []\n",
"for node in start_nodes:\n",
" loop_step, seq = find_loop(node, the_map)\n",
" loop_step, seq = find_loop(node, the_map, instructions)\n",
" last_z_offset = find_last_z_node(seq)\n",
" last_z_in_each_loop.append(loop_step - last_z_offset)\n",
"\n",
Expand All @@ -241,6 +242,53 @@
"assert part_2 == 12357789728873"
]
},
{
"cell_type": "markdown",
"id": "9397c8c5",
"metadata": {},
"source": [
"## Few ways to get the next step\n",
"\n",
"There are multiple different ways to map our next step based on an instruction and a map.\n",
"\n",
"In each of these, the `node` refers to current position and `the_map` is a dictionary that looks like `{ \"key\": (\"left_node\", \"right_node\") }`.\n",
"\n",
"Which one to use depends on the case and how many different options there are. The if/else in either form is great if there's only 2 options. With more options, I'd use either a dictionary or pattern matching approach. Pattern matching gives the best \"bang for buck\" as it improves readability and enables doing more than just simple value mapping like guards or more complex patterns.\n",
"\n",
"### Using if/else:\n",
"\n",
"```python\n",
"if instruction == 'L':\n",
" node = the_map[node][0]\n",
"else:\n",
" node = the_map[node][1]\n",
"```\n",
"\n",
"or with ternary operation:\n",
"\n",
"```python\n",
"index = 0 if instruction == 'L' else 1\n",
"node = the_map[node][idx]\n",
"```\n",
"\n",
"### Using pattern matching:\n",
"\n",
"```python\n",
"match instruction:\n",
" case 'L':\n",
" node = the_map[node][0]\n",
" case 'R':\n",
" node = the_map[node][1]\n",
"```\n",
"\n",
"### Using a dictionary\n",
"\n",
"```python\n",
"left_right = { 'left': 0, 'right': 1 }\n",
"node = the_map[node][left_right[instruction]]\n",
"```"
]
},
{
"cell_type": "markdown",
"id": "b5af38ca",
Expand Down

0 comments on commit 520be59

Please sign in to comment.