1
0
aoc-2020/18/main.py
2022-05-09 01:04:13 +00:00

107 lines
3.2 KiB
Python

import re
def getExpressions(filename):
with open(filename, "r") as f:
return f.read().splitlines()
def findMatchingPosition(line: str, pos: int) -> int:
depth = 1
end_pos = pos
while depth > 0:
end_pos += 1
if line[end_pos] == "(":
depth += 1
elif line[end_pos] == ")":
depth -= 1
return end_pos
def findMatchingParenthesis(line: str) -> list[tuple[int, int]]:
parens = []
for match in re.finditer(r"\(", line):
paren_start = match.start()
parent_end = findMatchingPosition(line, paren_start)
parens.append((paren_start, parent_end))
return parens
def determineTopParenthesis(parens: list[tuple[int, int]]) -> list[tuple[int, int]]:
top_parens = []
for i in range(len(parens)):
is_top_paren = True
for j in range(len(parens)):
if i != j and parens[i][0] > parens[j][0] and parens[i][1] < parens[j][1]:
is_top_paren = False
break
if is_top_paren:
top_parens.append(parens[i])
return top_parens
def evaluateExpression(expression: str):
parens = findMatchingParenthesis(expression)
top_parens = determineTopParenthesis(parens)
top_parens.sort(key=lambda p: p[0])
offset = 0
for paren in top_parens:
paren_start = paren[0] - offset
paren_end = paren[1] - offset
sub_value = evaluateExpression(expression[paren_start+1:paren_end])
expression = expression[:paren_start] + str(sub_value) + expression[paren_end+1:]
offset += (paren[1] - paren[0] - len(str(sub_value)) + 1)
parts = re.findall(r"(\d+|[\*\+])", expression)
result = int(parts[0])
for i in range(1, len(parts), 2):
if parts[i] == "*":
result *= int(parts[i+1])
elif parts[i] == "+":
result += int(parts[i+1])
return result
def evaluateAdvancedExpression(expression: str) -> int:
parens = findMatchingParenthesis(expression)
top_parens = determineTopParenthesis(parens)
top_parens.sort(key=lambda p: p[0])
offset = 0
for paren in top_parens:
paren_start = paren[0] - offset
paren_end = paren[1] - offset
sub_value = evaluateAdvancedExpression(expression[paren_start+1:paren_end])
expression = expression[:paren_start] + str(sub_value) + expression[paren_end+1:]
offset += (paren[1] - paren[0] - len(str(sub_value)) + 1)
parts = re.findall(r"(\d+|[\*\+])", expression)
i = 1
while i < len(parts):
if parts[i] == "+":
a = parts[i-1]
b = parts[i+1]
parts = parts[:i-1] + [int(a) + int(b)] + parts[i+2:]
i = -1
i += 2
result = int(parts[0])
for i in range(2, len(parts), 2):
result *= int(parts[i])
return result
def part1(filename: str) -> int:
total = 0
for expression in getExpressions(filename):
total += evaluateExpression(expression)
return total
def part2(filename: str) -> int:
total = 0
for expression in getExpressions(filename):
total += evaluateAdvancedExpression(expression)
return total
if __name__ == "__main__":
print("Part 1: ", part1("input.txt"))
print("Part 2: ", part2("input.txt"))