Skip to content

Commit 736ec8f

Browse files
committed
Added day 2021-24
1 parent 06d5f91 commit 736ec8f

File tree

2 files changed

+293
-0
lines changed

2 files changed

+293
-0
lines changed

2021/24-Arithmetic Logic Unit.ods

13.6 KB
Binary file not shown.

2021/24-Arithmetic Logic Unit.py

Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
# -------------------------------- Input data ---------------------------------------- #
2+
import os, grid, graph, dot, assembly, re, itertools, copy, functools
3+
from collections import Counter, deque, defaultdict
4+
5+
from compass import *
6+
7+
8+
# This functions come from https://github.com/mcpower/adventofcode - Thanks!
9+
def lmap(func, *iterables):
10+
return list(map(func, *iterables))
11+
12+
13+
def ints(s: str):
14+
return lmap(int, re.findall(r"-?\d+", s)) # thanks mserrano!
15+
16+
17+
def positive_ints(s: str):
18+
return lmap(int, re.findall(r"\d+", s)) # thanks mserrano!
19+
20+
21+
def floats(s: str):
22+
return lmap(float, re.findall(r"-?\d+(?:\.\d+)?", s))
23+
24+
25+
def positive_floats(s: str):
26+
return lmap(float, re.findall(r"\d+(?:\.\d+)?", s))
27+
28+
29+
def words(s: str):
30+
return re.findall(r"[a-zA-Z]+", s)
31+
32+
33+
test_data = {}
34+
35+
test = 1
36+
test_data[test] = {
37+
"input": """inp w
38+
add z w
39+
mod z 2
40+
div w 2
41+
add y w
42+
mod y 2
43+
div w 2
44+
add x w
45+
mod x 2
46+
div w 2
47+
mod w 2""",
48+
"expected": ["Unknown", "Unknown"],
49+
}
50+
51+
test = "real"
52+
input_file = os.path.join(
53+
os.path.dirname(__file__),
54+
"Inputs",
55+
os.path.basename(__file__).replace(".py", ".txt"),
56+
)
57+
test_data[test] = {
58+
"input": open(input_file, "r+").read(),
59+
"expected": ["92928914999991", "91811211611981"],
60+
}
61+
62+
63+
# -------------------------------- Control program execution ------------------------- #
64+
65+
case_to_test = "real"
66+
part_to_test = 2
67+
68+
# -------------------------------- Initialize some variables ------------------------- #
69+
70+
puzzle_input = test_data[case_to_test]["input"]
71+
puzzle_expected_result = test_data[case_to_test]["expected"][part_to_test - 1]
72+
puzzle_actual_result = "Unknown"
73+
74+
75+
# -------------------------------- Actual code execution ----------------------------- #
76+
77+
# Conver integer to 36-character binary
78+
# str_value = "{0:>036b}".format(value)
79+
# Convert binary string to number
80+
# value = int(str_value, 2)
81+
82+
83+
# The goal of this file is two-fold:
84+
# - The first part outputs a readable 'formula' for each step
85+
# - The second one executes the program for real
86+
87+
# Based on the 1st part, I manually executed program steps
88+
# Each time a simplification was possible (= values yielding 0), I wrote & applied the corresponding hypothesis
89+
# At the end, I had a set of hypothesis to match & I manually found the 2 corresponding values
90+
91+
92+
program = [line.split(" ") for line in puzzle_input.split("\n")]
93+
94+
95+
generate_formula = False
96+
if generate_formula: # Generating a formula
97+
98+
def add(a, b):
99+
if a == "0":
100+
return b
101+
if b == "0":
102+
return a
103+
try:
104+
return str((int(a) + int(b)))
105+
except:
106+
if len(a) <= 2 and len(b) <= 2:
107+
return a + "+" + b
108+
if len(a) <= 2:
109+
return a + "+(" + b + ")"
110+
if len(b) <= 2:
111+
return "(" + a + ")+" + b
112+
return "(" + a + ")+(" + b + ")"
113+
114+
def mul(a, b):
115+
if a == "0":
116+
return "0"
117+
if b == "0":
118+
return "0"
119+
if a == "1":
120+
return b
121+
if b == "1":
122+
return a
123+
try:
124+
return str((int(a) * int(b)))
125+
except:
126+
if len(a) <= 2 and len(b) <= 2:
127+
return a + "*" + b
128+
if len(a) <= 2:
129+
return a + "*(" + b + ")"
130+
if len(b) <= 2:
131+
return "(" + a + ")*" + b
132+
return "(" + a + ")*(" + b + ")"
133+
134+
def div(a, b):
135+
if a == "0":
136+
return "0"
137+
if b == "1":
138+
return a
139+
140+
if len(a) <= 2 and len(b) <= 2:
141+
return a + "//" + b
142+
if len(a) <= 2:
143+
return a + "//(" + b + ")"
144+
if len(b) <= 2:
145+
return "(" + a + ")//" + b
146+
return "(" + a + ")//(" + b + ")"
147+
148+
def mod(a, b):
149+
if a == "0":
150+
return "0"
151+
152+
if len(a) <= 2 and len(b) <= 2:
153+
return a + "%" + b
154+
if len(a) <= 2:
155+
return a + "%(" + b + ")"
156+
if len(b) <= 2:
157+
return "(" + a + ")%" + b
158+
return "(" + a + ")%(" + b + ")"
159+
160+
def eql(a, b):
161+
if a[0] == "i" and b == "0":
162+
return "0"
163+
if b[0] == "i" and a == "0":
164+
return "0"
165+
if a[0] == "i" and len(b) > 1 and all(x in "1234567890" for x in b):
166+
return "0"
167+
if b[0] == "i" and len(a) > 1 and all(x in "1234567890" for x in a):
168+
return "0"
169+
170+
if all(x in "1234567890" for x in a) and all(x in "1234567890" for x in b):
171+
return str((a == b) * 1)
172+
173+
if len(a) <= 2 and len(b) <= 2:
174+
return a + "==" + b
175+
if len(a) <= 2:
176+
return a + "==(" + b + ")"
177+
if len(b) <= 2:
178+
return "(" + a + ")==" + b
179+
180+
return "(" + a + ")==(" + b + ")"
181+
182+
vals = {i: "0" for i in "wxyz"}
183+
inputs = ["i" + str(i + 1) for i in range(14)]
184+
current_input = 0
185+
for j, instruction in enumerate(program):
186+
# print ('before', instruction, vals)
187+
if instruction[0] == "inp":
188+
vals[instruction[1]] = inputs[current_input]
189+
current_input += 1
190+
else:
191+
operands = []
192+
for i in (1, 2):
193+
if instruction[i].isalpha():
194+
operands.append(vals[instruction[i]])
195+
else:
196+
operands.append(instruction[i])
197+
198+
operation = {"add": add, "mul": mul, "div": div, "mod": mod, "eql": eql}[
199+
instruction[0]
200+
]
201+
202+
vals[instruction[1]] = functools.reduce(operation, operands)
203+
204+
# The below are simplifications
205+
# For example if the formula is "input1+10==input2", this is never possible (input2 <= 9)
206+
if j == 25:
207+
vals["x"] = "1"
208+
if j == 39:
209+
vals["x"] = "i2+11"
210+
if j == 43:
211+
vals["x"] = "1"
212+
if j == 57:
213+
vals["x"] = "i3+7"
214+
if j == 58:
215+
vals["z"] = "(i1+4)*26+i2+11"
216+
if j == 61:
217+
vals["x"] = "(i3-7)!=i4"
218+
if j == 78:
219+
vals["x"] = "0"
220+
if j == 93:
221+
vals["x"] = "i5+11"
222+
if j == 95:
223+
vals["x"] = "i5+1"
224+
if j == 97:
225+
vals["x"] = "i5+1!=i6"
226+
if j == 94:
227+
vals[
228+
"z"
229+
] = "((((i1+4)*26+i2+11)*(25*((i3-7)!=i4)+1))+((i4+2)*((i3-7)!=i4)))"
230+
if j == 115 or j == 133:
231+
vals["x"] = "1"
232+
if j == 147:
233+
vals["x"] = "i8+12"
234+
if j == 155:
235+
vals["x"] = "(i8+5)!=i9"
236+
if j == 168:
237+
vals["x"] = "0"
238+
if j == 183:
239+
vals["x"] = "i10+2"
240+
if j == 185:
241+
vals["x"] = "i10"
242+
if j == 187:
243+
vals["x"] = "i10!=i11"
244+
if j == 196:
245+
vals["y"] = "(i11+11)*(i10!=i11)"
246+
print("after", j, instruction, vals)
247+
if j == 200:
248+
break
249+
250+
print(inputs, vals["z"])
251+
252+
else:
253+
add = lambda a, b: a + b
254+
mul = lambda a, b: a * b
255+
div = lambda a, b: a // b
256+
mod = lambda a, b: a % b
257+
eql = lambda a, b: (a == b) * 1
258+
259+
input_value = "92928914999991" if part_to_test == 1 else "91811211611981"
260+
vals = {i: 0 for i in "wxyz"}
261+
inputs = lmap(int, tuple(input_value))
262+
current_input = 0
263+
for j, instruction in enumerate(program):
264+
# print ('before', instruction, vals)
265+
if instruction[0] == "inp":
266+
vals[instruction[1]] = inputs[current_input]
267+
current_input += 1
268+
else:
269+
operands = []
270+
for i in (1, 2):
271+
if instruction[i].isalpha():
272+
operands.append(vals[instruction[i]])
273+
else:
274+
operands.append(int(instruction[i]))
275+
276+
operation = {"add": add, "mul": mul, "div": div, "mod": mod, "eql": eql}[
277+
instruction[0]
278+
]
279+
280+
vals[instruction[1]] = functools.reduce(operation, operands)
281+
# print (instruction, vals)
282+
if vals["z"] == 0:
283+
puzzle_actual_result = input_value
284+
285+
286+
# -------------------------------- Outputs / results --------------------------------- #
287+
288+
print("Case :", case_to_test, "- Part", part_to_test)
289+
print("Expected result : " + str(puzzle_expected_result))
290+
print("Actual result : " + str(puzzle_actual_result))
291+
# Date created: 2021-12-24 11:07:56.259334
292+
# Part 1: 2021-12-25 02:07:10
293+
# Part 2: 2021-12-25 02:16:46

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy