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