Sean McLemon | Advent of Code

Home | Czech | Blog | GitHub | Advent Of Code | Notes


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