···11+import fileinput
22+import math
33+import re
44+55+GROUP_RE = r'[\d*+]+'
66+77+88+# Parse problem input.
99+MATRIX = []
1010+ALL_NUMS = []
1111+for y, line in enumerate(fileinput.input()):
1212+ # Parse whole groups for part 1.
1313+ groups = re.findall(GROUP_RE, line)
1414+ if '*' not in groups:
1515+ ALL_NUMS.append(groups)
1616+ else:
1717+ OPS = groups
1818+1919+ # Add a "simulated" blank line before the list of
2020+ # operations to make part 2 processing easier.
2121+ MATRIX.append([' ' for _ in range(len(MATRIX[-1]))])
2222+2323+ # Create a matrix to transpose for part 2.
2424+ MATRIX.append(list(line))
2525+2626+2727+# Solve part 1.
2828+OPERANDS = list(zip(*ALL_NUMS))
2929+PART_1 = 0
3030+for operands, op in zip(OPERANDS, OPS):
3131+ operands = [int(n) for n in operands]
3232+ if op == '+':
3333+ PART_1 += sum(operands)
3434+ else:
3535+ PART_1 += math.prod(operands)
3636+3737+print("Part 1:", PART_1)
3838+3939+4040+# Solve part 2.
4141+FLIPPED = list(zip(*MATRIX))
4242+TAPE = ''.join(''.join(col) for col in reversed(FLIPPED))
4343+PART_2 = 0
4444+4545+buffer = []
4646+for group in re.findall(GROUP_RE, TAPE):
4747+ if group == '+':
4848+ PART_2 += sum(buffer)
4949+ buffer = []
5050+ elif group == '*':
5151+ PART_2 += math.prod(buffer)
5252+ buffer = []
5353+ else:
5454+ buffer.append(int(group))
5555+5656+print("Part 2:", PART_2)
5757+5858+