-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
119 lines (95 loc) · 3.71 KB
/
main.py
File metadata and controls
119 lines (95 loc) · 3.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import time
import argparse
import re
operations = {
"+": (lambda a, b: a+b),
"-": (lambda a, b: a-b),
"*": (lambda a, b: a*b),
"/": (lambda a, b: a/b)
}
inverse = {
"/": "*",
"*": "/",
"+": "-",
"-": "+"
}
def job(monkey):
monkey = monkey.strip()
if monkey.isnumeric():
return [int(monkey)]
monkey = monkey.split(" ")
return monkey
def solve_root(monkeys, curr):
global operations
if len(monkeys[curr]) == 1:
return monkeys[curr][0]
left = solve_root(monkeys, monkeys[curr][0])
right = solve_root(monkeys, monkeys[curr][2])
return operations[monkeys[curr][1]](left, right)
def get_expression(monkeys, curr, needle="humn"):
global operations
if curr == needle:
return f"({needle})"
if len(monkeys[curr]) == 1:
return "(" + str(monkeys[curr][0]) + ")"
left = get_expression(monkeys, monkeys[curr][0], needle)
right = get_expression(monkeys, monkeys[curr][2], needle)
return "(" + left + monkeys[curr][1] + right + ")"
def split_with_brackets(expr):
num_opening = 0
for idx, ch in enumerate(expr):
if ch == "(":
num_opening += 1
if ch == ")":
num_opening -= 1
if num_opening == 0:
idx += 1
return expr[:idx], expr[idx:idx+1], expr[idx+1:]
return "", "", ""
def solve_equation(expr, solution, needle="humn"):
global inverse
if expr == needle:
return solution
left, operation, right = split_with_brackets(expr)
evaluated = eval(left if needle in right else right)
searched = right if needle in right else left
op = inverse[operation]
if needle in right and (operation == "-" or operation == "/"):
solution, evaluated = evaluated, solution
op = operation
solution = eval(f"{solution}{op}{evaluated}")
return solve_equation(searched[1:-1], solution, needle)
def main(input_file, stage=1):
with open(input_file) as file:
monkeys = {monkey.split(":")[0]: job(monkey.split(":")[1]) for monkey in file.readlines()}
l_result, r_result = solve_root(monkeys, monkeys["root"][0]), solve_root(monkeys, monkeys["root"][2])
if stage == 1:
# technically this could also be solved with get_expression + eval, but it is slower
result = int(operations[monkeys["root"][1]](l_result, r_result))
#assert result == 85616733059734
print(result)
return
needle = "humn"
l_expr = get_expression(monkeys, monkeys["root"][0], needle)[1:-1]
r_expr = get_expression(monkeys, monkeys["root"][2], needle)[1:-1]
needed = r_result if needle in l_expr else l_result
result = int(solve_equation(l_expr if needle in l_expr else r_expr, needed, needle))
#assert result == 3560324848168
print(result)
if __name__ == "__main__":
parser = argparse.ArgumentParser(
prog='main',
description='AdventOfCode main skeleton',
)
parser.add_argument("-e", "--example", action=argparse.BooleanOptionalAction, default=False, help="Set if you want to run the example")
parser.add_argument("-s", "--stage", action='store', default=0, help="Pass the stage you want to run", type=int)
args = parser.parse_args()
file_name = "example" if args.example else "input"
if args.stage == 1 or args.stage == 0:
start_time = time.time()
main(file_name, 1)
print(f"Stage 1 time: {time.time()-start_time:.10f}")
if args.stage == 2 or args.stage == 0:
start_time = time.time()
main(file_name, 2)
print(f"Stage 2 time: {time.time()-start_time:.10f}")