2022-12-05 - Supply Stacks
(original .ipynb)
Day 5 puzzle input is description a description of some crates, followed by some instructions that describe movements of items between them clean (mine is here). Part 1 involves following the movement instructions as if you're individually popping items the top of one and finding the top element of each. Part 2 involves the same but popping entire blocks in-place from one to another.
puzzle_input_str = open("./puzzle_input/day5.txt").read() test_input_str = """ [D] [N] [C] [Z] [M] [P] 1 2 3 move 1 from 2 to 1 move 3 from 1 to 3 move 2 from 2 to 1 move 1 from 1 to 2""" def parse_stacks(stacks_str): stack_lines = stacks_str.splitlines() num_stacks = 1 + int(len(stack_lines[0]) / 4) stacks = [list() for _ in range(1+num_stacks)] for line in stack_lines: for i in range(num_stacks): idx = 1+(i*4) if line[idx].isnumeric(): return stacks if line[idx] != " ": stacks[1+i].insert(0, line[idx]) raise Exception("shouldn't reach this") def parse_instruction(line): tokens = line.split(" ") return int(tokens[1]), int(tokens[3]), int(tokens[5]) def stack_move(stacks, count, source, dest): while count > 0: stacks[dest].append(stacks[source].pop()) count -= 1 def part_one(input_str, move=stack_move): stacks_str, instructions_str = input_str.split("\n\n") instructions = [parse_instruction(line) for line in instructions_str.splitlines()] stacks = parse_stacks(stacks_str) for count, source, dest in instructions: move(stacks, count, source, dest) stack_tops = [stack[-1] for stack in stacks if stack] return "".join(stack_tops) assert "CMZ" == part_one(test_input_str) print("part one:", part_one(puzzle_input_str))
part one: QPJPLMNNR
def inplace_move(stacks, count, source, dest): move_idx = len(stacks[source])-count stacks[dest] += stacks[source][move_idx:] del stacks[source][move_idx:] def part_two(input_str): return part_one(input_str, inplace_move) assert "MCD" == part_two(test_input_str) print("part two:", part_two(puzzle_input_str))
part two: BQDNWJPVJ