Comply with mypy conventions

This commit is contained in:
David Doblas Jiménez
2022-01-14 11:21:56 +01:00
parent 6a514d342f
commit 5e76b029a0
39 changed files with 113 additions and 0 deletions

188
src/Year_2020/P18.py Normal file
View File

@@ -0,0 +1,188 @@
# --- Day 18: Operation Order ---
# As you look out the window and notice a heavily-forested continent slowly
# appear over the horizon, you are interrupted by the child sitting next to
# you. They're curious if you could help them with their math homework.
# Unfortunately, it seems like this "math" follows different rules than you
# remember.
# The homework (your puzzle input) consists of a series of expressions that
# consist of addition (+), multiplication (*), and parentheses ((...)). Just
# like normal math, parentheses indicate that the expression inside must be
# evaluated before it can be used by the surrounding expression. Addition still
# finds the sum of the numbers on both sides of the operator, and
# multiplication still finds the product.
# However, the rules of operator precedence have changed. Rather than
# evaluating multiplication before addition, the operators have the same
# precedence, and are evaluated left-to-right regardless of the order in which
# they appear.
# For example, the steps to evaluate the expression 1 + 2 * 3 + 4 * 5 + 6 are
# as follows:
# 1 + 2 * 3 + 4 * 5 + 6
# 3 * 3 + 4 * 5 + 6
# 9 + 4 * 5 + 6
# 13 * 5 + 6
# 65 + 6
# 71
# Parentheses can override this order; for example, here is what happens if
# parentheses are added to form 1 + (2 * 3) + (4 * (5 + 6)):
# 1 + (2 * 3) + (4 * (5 + 6))
# 1 + 6 + (4 * (5 + 6))
# 7 + (4 * (5 + 6))
# 7 + (4 * 11 )
# 7 + 44
# 51
# Here are a few more examples:
# 2 * 3 + (4 * 5) becomes 26.
# 5 + (8 * 3 + 9 + 3 * 4 * 3) becomes 437.
# 5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4)) becomes 12240.
# ((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2 becomes 13632.
# Before you can help with the homework, you need to understand it yourself.
# Evaluate the expression on each line of the homework; what is the sum of the
# resulting values?
with open("files/P18.txt", "r") as f:
homework = [line for line in f.read().strip().split("\n")]
def eval(n1, n2, op) -> int:
if op == "+":
return n1 + n2
elif op == "*":
return n1 * n2
def simplify(expr) -> str:
while len(expr) > 1:
n1 = int(expr.pop())
op = expr.pop()
n2 = int(expr.pop())
result = eval(n1, n2, op)
expr.append(str(result))
return expr[0]
def part_1() -> None:
total = 0
for line in homework:
line = line.replace("(", "( ")
line = line.replace(")", " )")
expr = line.split()
stack = []
for char in expr:
if char.isdigit() or char in ["+", "*", "("]:
stack.append(char)
elif char == ")":
ordered_stack = []
while stack[len(stack) - 1] != "(":
ordered_stack.append(stack.pop())
stack.pop()
result = simplify(ordered_stack)
stack.append(result)
stack.reverse()
result = simplify(stack)
total += int(result)
print(f"The result of evaluating my homework is {total}")
# --- Part Two ---
# You manage to answer the child's questions and they finish part 1 of their
# homework, but get stuck when they reach the next section: advanced math.
# Now, addition and multiplication have different precedence levels, but
# they're not the ones you're familiar with. Instead, addition is evaluated
# before multiplication.
# For example, the steps to evaluate the expression 1 + 2 * 3 + 4 * 5 + 6 are
# now as follows:
# 1 + 2 * 3 + 4 * 5 + 6
# 3 * 3 + 4 * 5 + 6
# 3 * 7 * 5 + 6
# 3 * 7 * 11
# 21 * 11
# 231
# Here are the other examples from above:
# 1 + (2 * 3) + (4 * (5 + 6)) still becomes 51.
# 2 * 3 + (4 * 5) becomes 46.
# 5 + (8 * 3 + 9 + 3 * 4 * 3) becomes 1445.
# 5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4)) becomes 669060.
# ((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2 becomes 23340.
# What do you get if you add up the results of evaluating the homework problems
# using these new rules?
def simplify_rules(expr) -> str:
while len(expr) > 1:
ordered_stack, hold = [], []
done = False
while not done and len(expr) > 0:
char = expr.pop()
if char == "+":
done = True
hold.append(char)
if not done and len(expr) == 0:
result = simplify(hold)
expr.append(result)
else:
ordered_stack.append(expr.pop())
for _ in range(2):
ordered_stack.append(hold.pop())
result = simplify(ordered_stack)
hold.append(result)
while len(hold) > 0:
expr.append(hold.pop())
return expr[0]
def part_2() -> None:
total = 0
for line in homework:
line = line.replace("(", "( ")
line = line.replace(")", " )")
expr = line.split()
stack = []
for char in expr:
if char.isdigit() or char in ["+", "*", "("]:
stack.append(char)
elif char == ")":
ordered_stack = []
while stack[len(stack) - 1] != "(":
ordered_stack.append(stack.pop())
stack.pop()
result = simplify_rules(ordered_stack)
stack.append(result)
stack.reverse()
result = simplify_rules(stack)
total += int(result)
print(f"The result of evaluating my homework is {total}")
if __name__ == "__main__":
part_1()
part_2()