thiagowfx's avatar

Β¬ just serendipity πŸ€ (not just serendipity)

Advent of Code 2022: Day 5

β€’ 267 words β€’ 2 min β€’ updated

⚠️ This post is over one year old. It may no longer be up to date or relevant. Opinions may have changed.

Refer to the previous post about AoC, and to the git repository with my solutions in Python 3.

Link to Day #5 puzzle.

Rearrange crate stacks. Part two moves crates in order rather than one by one.

python
#!/usr/bin/env python3
import itertools
import sys
from copy import deepcopy


def parse_input(crates_unparsed):
    """
    Returns a dictionary in the following form:

    {
      1: 'ZN',
      2: 'MCD',
      3: 'P',
    }
    """

    crates = {}

    num_stacks = (len(crates_unparsed[0]) + 1) // 4
    max_height = len(crates_unparsed) - 1

    for i_stack in range(1, num_stacks + 1):
        stack_xaxis = 4 * (i_stack - 1) + 1

        # List comprehension version, not super readable:
        # crates[i_stack] = ''.join(list(filter(lambda x: x != ' ', [crates_unparsed[max_height - i][stack_xaxis]
        #                                                            for i in range(1, max_height + 1)])))

        crates[i_stack] = ''
        for i in range(1, max_height + 1):
            crate = crates_unparsed[max_height - i][stack_xaxis]
            if crate != ' ':
                crates[i_stack] += crate

    return crates


def move_crates(moves_unparsed, crates, *, reverse):
    for move_unparsed in moves_unparsed:
        _, quantity, _, src, _, dst = move_unparsed.split(' ')
        quantity, src, dst = int(quantity), int(src), int(dst)
        move_crate(crates, quantity, src, dst, reverse)
    return crates


def move_crate(crates, quantity, src, dst, reverse):
    if reverse:
        crates[dst] += crates[src][(-1) * quantity:][::-1]
    else:
        crates[dst] += crates[src][(-1) * quantity:]
    crates[src] = crates[src][:(-1) * quantity]


def main():
    with open(sys.argv[1]) as input:
        lines = input.read().splitlines()

    crates_unparsed, moves_unparsed = [list(group) for key, group in itertools.groupby(
        lines, lambda a: a == "") if not key]

    crates = parse_input(crates_unparsed)

    # Part 1
    crates_part1 = move_crates(moves_unparsed, deepcopy(crates), reverse=True)
    print(''.join([value[-1] for value in crates_part1.values()]))

    # Part 2
    crates_part2 = move_crates(moves_unparsed, deepcopy(crates), reverse=False)
    print(''.join([value[-1] for value in crates_part2.values()]))


if __name__ == '__main__':
    main()