Day 6: Trash Compactor

Megathread guidelines

  • Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
  • You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL

FAQ

  • Pyro
    link
    fedilink
    arrow-up
    2
    ·
    1 month ago

    Python

    For part1, regex is king. Thought about rotating the grid for part2, but going column by column is simple enough.

    view code
    import re
    from operator import add, mul
    
    def part1(data: str):
        # split into row, but do not split into cells yet
        rows = data.splitlines()
        m = len(rows)   # number of rows
    
        # initialize the result and operator arrays
        # the operators array will store the operator function for each column block
        # the result array will store the initial value for each column block
        operators = []
        res = []
        # using regex to skip variable number of spaces
        for symbol in re.findall(r'\S', rows[-1]):
            if symbol == '+':
                operators.append(add)
                res.append(0)
            elif symbol == '*':
                operators.append(mul)
                res.append(1)
    
        n = len(res)    # number of columns
        # iterate through each row, except the last one
        for i in range(m-1):
            # use regex to find all numbers in the row
            for j, num in enumerate(map(int, re.findall(r'\d+', rows[i]))):
                # apply the operator to update the result for the appropriate column
                res[j] = operators[j](res[j], num)
    
        return sum(res)
    
    def part2(data: str):
        # completely split into grid
        grid = [list(line) for line in data.splitlines()]
        m, n = len(grid), len(grid[0])
        
        res = 0
        
        curr = None     # current value of the block
        op = None       # operator for the block
        for j in range(n):
            if curr is None:
                # we just started a new block
                # update the current value and operator based on the symbol
                symbol = grid[-1][j]
                curr = 0 if symbol == '+' else 1
                op = add if symbol == '+' else mul
            
            # read the number from the column
            num = 0
            for i in range(m-1):
                if grid[i][j] != ' ':
                    num = num * 10 + int(grid[i][j])
            # if there is no number, we are at the end of a block
            if num == 0:
                # add the block value to the result
                #   and reset the current value and operator
                res += curr
                curr = None
                op = None
                continue
            
            # otherwise, update the current value using the operator
            curr = op(curr, num)
        # finally, don't forget to add the last block value that's being tracked
        res += curr
    
        return res
    
    sample = """123 328  51 64 
     45 64  387 23 
      6 98  215 314
    *   +   *   +  """
    assert part1(sample) == 4277556
    assert part2(sample) == 3263827