import itertools import re from utils.input import read_input_lines class Instruction: def __init__(self, line: str): parsed = re.search(r"move (\d+) from (\d+) to (\d+)", line) self.moved_count = int(parsed.group(1)) self.from_column = int(parsed.group(2)) - 1 self.to_column = int(parsed.group(3)) - 1 lines = iter(read_input_lines()) initial_stack_configuration_lines = list(itertools.takewhile(lambda line: len(line) > 0, lines))[:-1] instructions = [Instruction(line) for line in lines] initial_stacks = list() for line in reversed(initial_stack_configuration_lines): for stack_index, character_index in enumerate(range(1, len(line), 4)): crate = line[character_index] if crate == " ": continue for i in range(len(initial_stacks), stack_index + 1): initial_stacks.append(list()) initial_stacks[stack_index].append(crate) def copy_initial_stacks() -> list[list[str]]: return [stack.copy() for stack in initial_stacks] def print_stacks(title: str, stacks: list[list[str]]): print(f"Top of each stack in {title}: ", end = "") for stack in stacks: print(stack[-1], end = "") print() stacks = copy_initial_stacks() for instruction in instructions: for _ in range(instruction.moved_count): moved_crate = stacks[instruction.from_column].pop() stacks[instruction.to_column].append(moved_crate) print_stacks("part 1", stacks) stacks = copy_initial_stacks() for instruction in instructions: taken_crates = list() for _ in range(instruction.moved_count): taken_crates.append(stacks[instruction.from_column].pop()) for crate in reversed(taken_crates): stacks[instruction.to_column].append(crate) print_stacks("part 2", stacks)