import re from copy import deepcopy def parse(filename: str) -> tuple[list[list[str]], list[tuple[int, int, int]]]: stacks_of_crates = [] operations = [] finalised_stacks = False with open(filename) as f: while not finalised_stacks: row = f.readline()[:-1] if re.match(r"(\s{3}|\[.\])\s?", row): crates = [] while row != "": crate = row[0:3] crates.append(crate[1]) row = row[4:] for idx, crate in enumerate(crates): if crate != " ": if idx < len(stacks_of_crates): stacks_of_crates[idx].append(crate) else: stacks_of_crates.append([crate]) else: if idx >= len(stacks_of_crates): stacks_of_crates.append([]) else: finalised_stacks = True numbers = re.findall(r" \d ", row) last = int(numbers[len(numbers) - 1]) assert last == len(stacks_of_crates) f.readline() while line := f.readline(): if match := re.match(r"move (\d+) from (\d) to (\d)", line): operations.append((int(match.group(1)), int(match.group(2)), int(match.group(3)))) return list(map(lambda x: list(reversed(x)), stacks_of_crates)), operations def pretty_print(stacks: list[list[str]]) -> None: max_len = max(map(len, stacks)) the_stacks = deepcopy(stacks) for idx, stack in enumerate(the_stacks): for i in range(max_len - len(stack)): the_stacks[idx].append(" ") for i in range(max_len): for j in range(len(the_stacks)): char = the_stacks[j].pop() if char != " ": print(f"[{char}]", end=" ") else: print(" ", end=" ") print("") print("".join([f" {a} " for a in range(1, len(the_stacks) + 1)])) pass