From 4ec228f14fb70d3b57722a5d50ef4bed8f218f01 Mon Sep 17 00:00:00 2001 From: wieerwill Date: Sun, 10 Dec 2023 10:23:48 +0100 Subject: [PATCH] solve Day08 Part1 in python --- Day08/README.md | 35 ++++++++++++++++++ Day08/python/solution1.py | 74 +++++++++++++++++++++++++++++++++++++++ Day08/test.txt | 5 +++ README.md | 2 +- 4 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 Day08/README.md create mode 100644 Day08/python/solution1.py create mode 100644 Day08/test.txt diff --git a/Day08/README.md b/Day08/README.md new file mode 100644 index 0000000..6fce715 --- /dev/null +++ b/Day08/README.md @@ -0,0 +1,35 @@ +# Day 8: Haunted Wasteland +## Part One +You're still riding a camel across Desert Island when you spot a sandstorm quickly approaching. When you turn to warn the Elf, she disappears before your eyes! To be fair, she had just finished warning you about ghosts a few minutes ago. + +One of the camel's pouches is labeled "maps" - sure enough, it's full of documents (your puzzle input) about how to navigate the desert. At least, you're pretty sure that's what they are; one of the documents contains a list of left/right instructions, and the rest of the documents seem to describe some kind of network of labeled nodes. + +It seems like you're meant to use the left/right instructions to navigate the network. Perhaps if you have the camel follow the same instructions, you can escape the haunted wasteland! + +After examining the maps for a bit, two nodes stick out: AAA and ZZZ. You feel like AAA is where you are now, and you have to follow the left/right instructions until you reach ZZZ. + +This format defines each node of the network individually. For example: +``` +RL + +AAA = (BBB, CCC) +BBB = (DDD, EEE) +CCC = (ZZZ, GGG) +DDD = (DDD, DDD) +EEE = (EEE, EEE) +GGG = (GGG, GGG) +ZZZ = (ZZZ, ZZZ) +``` + +Starting with AAA, you need to look up the next element based on the next left/right instruction in your input. In this example, start with AAA and go right (R) by choosing the right element of AAA, CCC. Then, L means to choose the left element of CCC, ZZZ. By following the left/right instructions, you reach ZZZ in 2 steps. + +Of course, you might not find ZZZ right away. If you run out of left/right instructions, repeat the whole sequence of instructions as necessary: RL really means RLRLRLRLRLRLRLRL... and so on. For example, here is a situation that takes 6 steps to reach ZZZ: +``` +LLR + +AAA = (BBB, BBB) +BBB = (AAA, ZZZ) +ZZZ = (ZZZ, ZZZ) +``` + +Starting at AAA, follow the left/right instructions. How many steps are required to reach ZZZ? \ No newline at end of file diff --git a/Day08/python/solution1.py b/Day08/python/solution1.py new file mode 100644 index 0000000..cec712a --- /dev/null +++ b/Day08/python/solution1.py @@ -0,0 +1,74 @@ +def parse_file(file_path): + """Parse the input file to extract instructions and the node map.""" + try: + with open(file_path, 'r') as file: + lines = file.readlines() + + instructions = lines[0].strip() + node_map = {} + for line in lines[2:]: + node, neighbors = line.strip().split(' = ') + node_map[node] = tuple(neighbors[1:-1].split(', ')) + + return instructions, node_map + except Exception as e: + print(f"Error parsing file {file_path}: {e}") + raise + +def find_repeating_unit(sequence): + """Find the repeating unit in a sequence.""" + for i in range(1, len(sequence) + 1): + unit = sequence[:i] + if sequence == unit * (len(sequence) // len(unit)): + return unit + return sequence + +def navigate_network(instructions, node_map, start_node='AAA', end_node='ZZZ'): + """Navigate the network based on the instructions and return the number of steps.""" + current_node = start_node + steps = 0 + visited = set() + instruction_index = 0 + instructions = find_repeating_unit(instructions) + + while current_node != end_node: + if (current_node, instruction_index) in visited: + print(f"Loop detected at {current_node} with instruction index {instruction_index}") + return -1 # Indicates a loop without reaching the end node + + visited.add((current_node, instruction_index)) + direction = instructions[instruction_index % len(instructions)] + current_node = node_map[current_node][0 if direction == 'L' else 1] + instruction_index += 1 + steps += 1 + + return steps + +def run_test(): + """Run the test with the provided file path.""" + try: + expected_result = 6 + instructions, node_map = parse_file("../test.txt") + result = navigate_network(instructions, node_map) + assert result == expected_result, f"Test failed, expected {expected_result} but got {total_winnings}" + print(f"Test passed with {result} steps.") + except AssertionError as error: + print(error) + +def main(): + print("Start Tests") + run_test() + + try: + print("Start input.txt") + instructions, node_map = parse_file("../input.txt") + result = navigate_network(instructions, node_map) + if result == -1: + print("Failed to reach the end node due to a loop.") + else: + print(f"Reached the end node in {result} steps.") + except Exception as e: + print(f"Error during main execution: {e}") + +if __name__ == "__main__": + main() diff --git a/Day08/test.txt b/Day08/test.txt new file mode 100644 index 0000000..7d1b58d --- /dev/null +++ b/Day08/test.txt @@ -0,0 +1,5 @@ +LLR + +AAA = (BBB, BBB) +BBB = (AAA, ZZZ) +ZZZ = (ZZZ, ZZZ) diff --git a/README.md b/README.md index 3426940..c276347 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ I aim to complete each day's puzzle on the same day, but as with any challenge, | 05 | ✅ | ✅ | [Day05 README](/Day05/README.md) | | 06 | ✅ | ✅ | [Day06 README](/Day06/README.md) | | 07 | ✅ | ✅ | [Day07 README](/Day07/README.md) | -| 08 | ❓ | ❓ | [Day08 README](/Day08/README.md) | +| 08 | ✅ | ❓ | [Day08 README](/Day08/README.md) | | 09 | ❓ | ❓ | [Day09 README](/Day09/README.md) | | 10 | ❓ | ❓ | [Day10 README](/Day10/README.md) | | 11 | ❓ | ❓ | [Day11 README](/Day11/README.md) |