Update 2015 solutions
This commit is contained in:
parent
87ab42743e
commit
e73fa3bae7
16
2015/d1.py
16
2015/d1.py
@ -1,8 +1,9 @@
|
||||
from lib import *
|
||||
from lib import get_data
|
||||
|
||||
data = open(0).read()
|
||||
data = get_data(__file__)
|
||||
|
||||
part_2 = True
|
||||
t = sum((1 if c == "(" else -1 for c in data))
|
||||
print(t)
|
||||
|
||||
floor = 0
|
||||
for i, c in enumerate(data):
|
||||
@ -10,13 +11,6 @@ for i, c in enumerate(data):
|
||||
floor += 1
|
||||
elif c == ")":
|
||||
floor -= 1
|
||||
else:
|
||||
print(c)
|
||||
assert False
|
||||
|
||||
if part_2 and floor == -1:
|
||||
if floor == -1:
|
||||
print(i + 1)
|
||||
break
|
||||
|
||||
if not part_2:
|
||||
print(floor)
|
||||
|
54
2015/d10.py
54
2015/d10.py
@ -1,35 +1,29 @@
|
||||
from functools import lru_cache
|
||||
data = open(0).read().strip()
|
||||
from lib import get_data
|
||||
|
||||
part_1 = False
|
||||
if part_1:
|
||||
repeats = 40
|
||||
else:
|
||||
repeats = 50
|
||||
data = get_data(__file__)
|
||||
|
||||
@lru_cache
|
||||
def look_and_say(data: str) -> str:
|
||||
r = ""
|
||||
i = 0
|
||||
while i < len(data):
|
||||
count = 0
|
||||
c = data[i]
|
||||
while i < len(data) and data[i] == c:
|
||||
|
||||
def iter(xs):
|
||||
if not xs:
|
||||
return []
|
||||
grouped = []
|
||||
current_element = xs[0]
|
||||
count = 1
|
||||
for element in xs[1:]:
|
||||
if element == current_element:
|
||||
count += 1
|
||||
i += 1
|
||||
r += f"{count}{c}"
|
||||
return r
|
||||
else:
|
||||
grouped.append(count)
|
||||
grouped.append(current_element)
|
||||
current_element = element
|
||||
count = 1
|
||||
grouped.append(count)
|
||||
grouped.append(current_element)
|
||||
return grouped
|
||||
|
||||
CHUNK_SIZE = 10000
|
||||
for _ in range(repeats):
|
||||
ndata = ""
|
||||
lo, up = 0, CHUNK_SIZE
|
||||
while up < len(data):
|
||||
while up < len(data) and data[up - 1] == data[up]:
|
||||
up += 1
|
||||
ndata += look_and_say(data[lo:up])
|
||||
lo, up = up, up + CHUNK_SIZE
|
||||
ndata += look_and_say(data[lo:up])
|
||||
data = ndata
|
||||
|
||||
print(len(data))
|
||||
for repeat in [40, 50]:
|
||||
xs = list(map(int, list(data.strip())))
|
||||
for _ in range(repeat):
|
||||
xs = iter(xs)
|
||||
print(len(xs))
|
||||
|
19
2015/d11.py
19
2015/d11.py
@ -1,4 +1,7 @@
|
||||
data = open(0).read().strip()
|
||||
from lib import get_data
|
||||
|
||||
data = get_data(__file__).strip()
|
||||
|
||||
|
||||
def is_valid(pw):
|
||||
# Passwords must include one increasing straight of at least three letters,
|
||||
@ -26,24 +29,26 @@ def is_valid(pw):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def inc(pw):
|
||||
pw = list(map(ord, pw))
|
||||
for i in range(len(pw) - 1, -1, -1):
|
||||
pw[i] += 1
|
||||
if pw[i] == ord('z') + 1:
|
||||
pw[i] = ord('a')
|
||||
if pw[i] == ord("z") + 1:
|
||||
pw[i] = ord("a")
|
||||
else:
|
||||
break
|
||||
return "".join(map(chr, pw))
|
||||
|
||||
part_1 = False
|
||||
|
||||
part_1 = True
|
||||
valid_count = 0
|
||||
while True:
|
||||
data = inc(data)
|
||||
if is_valid(data):
|
||||
valid_count += 1
|
||||
if part_1 and valid_count == 1:
|
||||
break
|
||||
elif valid_count == 2:
|
||||
break
|
||||
print(data)
|
||||
elif valid_count == 2:
|
||||
print(data)
|
||||
break
|
||||
|
54
2015/d12.py
54
2015/d12.py
@ -1,27 +1,37 @@
|
||||
from lib import get_data
|
||||
import json
|
||||
|
||||
data = open(0).read().strip()
|
||||
part_2 = False
|
||||
data = get_data(__file__).strip()
|
||||
|
||||
def addup(d):
|
||||
r = 0
|
||||
if isinstance(d, list):
|
||||
for e in d:
|
||||
v = addup(e)
|
||||
if v is not None:
|
||||
r += v
|
||||
elif isinstance(d, dict):
|
||||
for e in d.values():
|
||||
v = addup(e)
|
||||
if v is None:
|
||||
return 0
|
||||
r += v
|
||||
elif isinstance(d, str):
|
||||
if part_2 and d == "red":
|
||||
return None
|
||||
o = json.loads(data)
|
||||
|
||||
|
||||
def xsum(obj, part_2=False):
|
||||
t = 0
|
||||
if type(obj) is int:
|
||||
t += obj
|
||||
elif type(obj) is list:
|
||||
for o in obj:
|
||||
t += xsum(o, part_2)
|
||||
elif type(obj) is dict:
|
||||
if part_2:
|
||||
st = 0
|
||||
for o in obj.values():
|
||||
st += xsum(o, part_2)
|
||||
if type(o) is str and o == "red":
|
||||
break
|
||||
else:
|
||||
r += d
|
||||
return r
|
||||
t += st
|
||||
else:
|
||||
for o in obj.values():
|
||||
t += xsum(o, part_2)
|
||||
elif type(obj) is str:
|
||||
pass
|
||||
else:
|
||||
print(obj)
|
||||
assert False
|
||||
return t
|
||||
|
||||
data = json.loads(data)
|
||||
print(addup(data))
|
||||
|
||||
print(xsum(o))
|
||||
print(xsum(o, True))
|
||||
|
49
2015/d13.py
49
2015/d13.py
@ -1,35 +1,32 @@
|
||||
from lib import get_data
|
||||
from collections import defaultdict
|
||||
from itertools import permutations
|
||||
data = open(0).read().strip()
|
||||
|
||||
part_2 = False
|
||||
data = get_data(__file__).strip()
|
||||
|
||||
pairs = defaultdict(int)
|
||||
people = set()
|
||||
scores = {}
|
||||
|
||||
for line in data.splitlines():
|
||||
a, _, wl, score, _, _, _, _, _, _, b = line.split()
|
||||
b = b.replace(".", "")
|
||||
score = int(score)
|
||||
if wl == "lose":
|
||||
score = -score
|
||||
a, _, gainlose, amount, _, _, _, _, _, _, b = line[:-1].split()
|
||||
amount = int(amount)
|
||||
if gainlose == "lose":
|
||||
amount = -amount
|
||||
pairs[(a, b)] = amount
|
||||
people.add(a)
|
||||
people.add(b)
|
||||
scores[(a, b)] = score
|
||||
if part_2:
|
||||
scores[(a, "me")] = 0
|
||||
scores[("me", a)] = 0
|
||||
scores[(b, "me")] = 0
|
||||
scores[("me", b)] = 0
|
||||
|
||||
if part_2:
|
||||
people.add("me")
|
||||
|
||||
max_score = 0
|
||||
for p in permutations(list(people)):
|
||||
s = 0
|
||||
for i in range(len(p)):
|
||||
a, b = p[i], p[(i + 1) % len(p)]
|
||||
s += scores[(a, b)]
|
||||
s += scores[(b, a)]
|
||||
max_score = max(max_score, s)
|
||||
def calc_gain(people):
|
||||
maxgain = 0
|
||||
for xs in permutations(list(people)):
|
||||
gain = 0
|
||||
for i in range(len(xs)):
|
||||
gain += pairs[(xs[i], xs[(i + 1) % len(xs)])]
|
||||
gain += pairs[(xs[(i + 1) % len(xs)], xs[i])]
|
||||
maxgain = max(maxgain, gain)
|
||||
return maxgain
|
||||
|
||||
print(max_score)
|
||||
|
||||
print(calc_gain(people))
|
||||
people.add("Felix")
|
||||
print(calc_gain(people))
|
||||
|
79
2015/d14.py
79
2015/d14.py
@ -1,53 +1,40 @@
|
||||
import lib
|
||||
data = open(0).read().strip()
|
||||
from lib import get_data
|
||||
from lib import ints, fst
|
||||
from collections import defaultdict
|
||||
|
||||
part_1 = False
|
||||
|
||||
rds = []
|
||||
max_dist = 0
|
||||
gtime = 2503
|
||||
rds = []
|
||||
data = get_data(__file__).strip()
|
||||
deers = []
|
||||
for line in data.splitlines():
|
||||
speed, time, rest = lib.str_to_ints(line)
|
||||
rds.append([speed, time, rest, 0, 0, 0])
|
||||
speed *= 1000
|
||||
speed, time, rest = ints(line)
|
||||
deers.append([0, speed, time, rest, time, 0])
|
||||
|
||||
dist = 0
|
||||
ctime = 0
|
||||
while ctime < gtime:
|
||||
t = min(time, gtime - ctime)
|
||||
dist += (speed * t)
|
||||
ctime += time
|
||||
ctime += rest
|
||||
max_dist = max(dist, max_dist)
|
||||
points = defaultdict(int)
|
||||
for _ in range(2503):
|
||||
max_dists = defaultdict(list)
|
||||
for i, deer in enumerate(deers):
|
||||
dist, speed, time, rest, time_left, rest_left = deer
|
||||
if time_left > 0:
|
||||
time_left -= 1
|
||||
dist += speed
|
||||
elif time_left == 0:
|
||||
time_left = -1
|
||||
rest_left = rest - 1
|
||||
elif rest_left > 0:
|
||||
rest_left -= 1
|
||||
elif rest_left == 0:
|
||||
time_left = time - 1
|
||||
dist += speed
|
||||
rest_left = -1
|
||||
max_dists[dist].append(i)
|
||||
|
||||
if part_1:
|
||||
print(max_dist // 1000)
|
||||
deer[0] = dist
|
||||
deer[4] = time_left
|
||||
deer[5] = rest_left
|
||||
|
||||
scores = [0 for _ in range(len(rds))]
|
||||
for _ in range(gtime):
|
||||
for i in range(len(rds)):
|
||||
speed, time, rest, dist, travel_time, rest_time = rds[i]
|
||||
rd = rds[i]
|
||||
if travel_time < time:
|
||||
rd[3] += speed
|
||||
rd[4] += 1
|
||||
elif rest_time < rest:
|
||||
rd[5] += 1
|
||||
if rd[5] == rest:
|
||||
rd[4] = 0
|
||||
rd[5] = 0
|
||||
max_deers = max(max_dists.items())
|
||||
for di in max_deers[1]:
|
||||
points[di] += 1
|
||||
|
||||
max_i = -1
|
||||
max_v = 0
|
||||
for i, rd in enumerate(rds):
|
||||
if rd[3] > max_v:
|
||||
max_i = i
|
||||
max_v = rd[3]
|
||||
for i, rd in enumerate(rds):
|
||||
if rd[3] == max_v:
|
||||
scores[i] += 1
|
||||
|
||||
if not part_1:
|
||||
print(max(scores))
|
||||
|
||||
print(max(map(fst, deers)))
|
||||
print(max(points.values()))
|
||||
|
20
2015/d2.py
20
2015/d2.py
@ -1,19 +1,17 @@
|
||||
from lib import *
|
||||
from lib import get_data, ints
|
||||
|
||||
data = open(0).readlines()
|
||||
data = get_data(__file__)
|
||||
|
||||
part_1 = True
|
||||
if part_1:
|
||||
a = 0
|
||||
for line in data:
|
||||
l, w, h = list(map(int, line.split("x")))
|
||||
for line in data.splitlines():
|
||||
l, w, h = ints(line)
|
||||
slack = min([l * w, w * h, h * l])
|
||||
a += (2*l*w + 2*w*h + 2*h*l + slack)
|
||||
else:
|
||||
a += 2 * l * w + 2 * w * h + 2 * h * l + slack
|
||||
print(a)
|
||||
|
||||
a = 0
|
||||
for line in data:
|
||||
l, w, h = list(map(int, line.split("x")))
|
||||
for line in data.splitlines():
|
||||
l, w, h = ints(line)
|
||||
sd = min([2 * (l + w), 2 * (w + h), 2 * (h + l)])
|
||||
a += sd + (l * w * h)
|
||||
|
||||
print(a)
|
||||
|
@ -4,6 +4,7 @@ import lib
|
||||
data = int(open(0).read().strip())
|
||||
part_1 = False
|
||||
|
||||
|
||||
def calc(n):
|
||||
fs = lib.prime_factors(n)
|
||||
vs = set([1, n])
|
||||
@ -21,6 +22,7 @@ def calc(n):
|
||||
r += e * 11
|
||||
return r
|
||||
|
||||
|
||||
for i in range(3, 10000000):
|
||||
c = calc(i)
|
||||
if c >= data:
|
||||
|
23
2015/d3.py
23
2015/d3.py
@ -1,9 +1,7 @@
|
||||
import sys
|
||||
from lib import *
|
||||
from lib import get_data
|
||||
from lib import V
|
||||
|
||||
data = open(0).read()
|
||||
|
||||
part_1 = False
|
||||
data = get_data(__file__)
|
||||
|
||||
DIRS = {
|
||||
"^": (-1, 0),
|
||||
@ -12,30 +10,27 @@ DIRS = {
|
||||
"<": (0, -1),
|
||||
}
|
||||
|
||||
if part_1:
|
||||
pos = (0, 0)
|
||||
pos = V(0, 0)
|
||||
poss = set([pos])
|
||||
|
||||
for c in data:
|
||||
d = DIRS[c]
|
||||
pos = pos[0] + d[0], pos[1] + d[1]
|
||||
pos = pos + d
|
||||
poss.add(pos)
|
||||
|
||||
print(len(poss))
|
||||
sys.exit(0)
|
||||
|
||||
a = (0, 0)
|
||||
b = (0, 0)
|
||||
a = V(0, 0)
|
||||
b = V(0, 0)
|
||||
poss = set([a, b])
|
||||
for i, c in enumerate(data):
|
||||
if i % 2 == 0:
|
||||
d = DIRS[c]
|
||||
a = a[0] + d[0], a[1] + d[1]
|
||||
a = a + d
|
||||
poss.add(a)
|
||||
else:
|
||||
d = DIRS[c]
|
||||
b = b[0] + d[0], b[1] + d[1]
|
||||
b = b + d
|
||||
poss.add(b)
|
||||
|
||||
print(len(poss))
|
||||
sys.exit(0)
|
||||
|
13
2015/d4.py
13
2015/d4.py
@ -1,15 +1,9 @@
|
||||
from lib import *
|
||||
from lib import get_data
|
||||
import hashlib
|
||||
|
||||
part_1 = True
|
||||
|
||||
if part_1:
|
||||
digits = 5
|
||||
else:
|
||||
digits = 6
|
||||
|
||||
data = open(0).read().strip()
|
||||
data = get_data(__file__).strip()
|
||||
|
||||
for digits in [5, 6]:
|
||||
for i in range(10**9):
|
||||
text = data + str(i)
|
||||
md5_hash = hashlib.md5(text.encode()).hexdigest()
|
||||
@ -19,4 +13,3 @@ for i in range(10**9):
|
||||
else:
|
||||
print(i)
|
||||
break
|
||||
|
||||
|
95
2015/d5.py
95
2015/d5.py
@ -1,53 +1,56 @@
|
||||
from lib import *
|
||||
from lib import get_data
|
||||
|
||||
data = open(0).read()
|
||||
data = get_data(__file__)
|
||||
|
||||
part_1 = True
|
||||
if part_1:
|
||||
res = 0
|
||||
for line in data.splitlines():
|
||||
|
||||
def is_nice(line):
|
||||
# It contains at least three vowels (aeiou only), like aei, xazegov, or aeiouaeiouaeiou.
|
||||
vc = 0
|
||||
for c in line:
|
||||
if c in "aoeui":
|
||||
vc += 1
|
||||
for v in "aeiou":
|
||||
vc += line.count(v)
|
||||
if vc < 3:
|
||||
continue
|
||||
return False
|
||||
|
||||
prev = None
|
||||
for c in line:
|
||||
if c == prev:
|
||||
break
|
||||
prev = c
|
||||
else:
|
||||
continue
|
||||
|
||||
contains = False
|
||||
ss = ["ab", "cd", "pq", "xy"]
|
||||
for s in ss:
|
||||
if s in line:
|
||||
contains = True
|
||||
|
||||
if contains:
|
||||
continue
|
||||
res += 1
|
||||
print(res)
|
||||
else:
|
||||
res = 0
|
||||
for line in data.splitlines():
|
||||
pairs = {}
|
||||
for i in range(0, len(line) - 1):
|
||||
p = line[i:i+2]
|
||||
if p in pairs and i > pairs[p] + 1:
|
||||
break
|
||||
if not p in pairs:
|
||||
pairs[p] = i
|
||||
else:
|
||||
continue
|
||||
|
||||
for i in range(0, len(line) - 2):
|
||||
if line[i] == line[i + 2]:
|
||||
# It contains at least one letter that appears twice in a row, like xx,
|
||||
# abcdde (dd), or aabbccdd (aa, bb, cc, or dd).
|
||||
for i in range(len(line) - 1):
|
||||
if line[i] == line[i + 1]:
|
||||
break
|
||||
else:
|
||||
continue
|
||||
res += 1
|
||||
print(res)
|
||||
return False
|
||||
|
||||
# It does not contain the strings ab, cd, pq, or xy, even if they are
|
||||
# part of one of the other requirements.
|
||||
for i in range(len(line) - 1):
|
||||
cc = "".join(line[i : i + 2])
|
||||
if cc in ["ab", "cd", "pq", "xy"]:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def is_nice_2(line):
|
||||
good = False
|
||||
for i in range(len(line) - 1):
|
||||
cc = "".join(line[i : i + 2])
|
||||
for j in range(i + 2, len(line) - 1):
|
||||
dd = "".join(line[j : j + 2])
|
||||
if cc == dd:
|
||||
good = True
|
||||
if not good:
|
||||
return False
|
||||
|
||||
for i in range(len(line) - 2):
|
||||
cc = "".join(line[i : i + 3])
|
||||
if cc[0] == cc[2]:
|
||||
break
|
||||
else:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
t = sum(1 if is_nice(line) else 0 for line in data.splitlines())
|
||||
print(t)
|
||||
|
||||
|
||||
t = sum(1 if is_nice_2(line) else 0 for line in data.splitlines())
|
||||
print(t)
|
||||
|
46
2015/d6.py
46
2015/d6.py
@ -1,33 +1,29 @@
|
||||
from lib import *
|
||||
from lib import get_data, ints
|
||||
from collections import defaultdict as DD
|
||||
|
||||
data = open(0).read()
|
||||
|
||||
part_2 = True
|
||||
lights = [[0 for _ in range(1000)] for _ in range(1000)]
|
||||
data = get_data(__file__)
|
||||
|
||||
ons = set()
|
||||
ons2 = DD(int)
|
||||
for line in data.splitlines():
|
||||
x1, y1, x2, y2 = str_to_ints(line)
|
||||
x1, y1, x2, y2 = ints(line)
|
||||
for x in range(x1, x2 + 1):
|
||||
for y in range(y1, y2 + 1):
|
||||
if part_2:
|
||||
if "on" in line:
|
||||
lights[x][y] += 1
|
||||
elif "off" in line:
|
||||
lights[x][y] = max(0, lights[x][y] - 1)
|
||||
if "off" in line:
|
||||
if (x, y) in ons:
|
||||
ons.remove((x, y))
|
||||
ons2[(x, y)] = max(ons2[(x, y)] - 1, 0)
|
||||
elif "on" in line:
|
||||
ons.add((x, y))
|
||||
ons2[(x, y)] += 1
|
||||
elif "toggle" in line:
|
||||
if (x, y) in ons:
|
||||
ons.remove((x, y))
|
||||
else:
|
||||
lights[x][y] += 2
|
||||
ons.add((x, y))
|
||||
ons2[(x, y)] += 2
|
||||
else:
|
||||
if "on" in line:
|
||||
lights[x][y] = 1
|
||||
elif "off" in line:
|
||||
lights[x][y] = 0
|
||||
else:
|
||||
if lights[x][y] == 1:
|
||||
lights[x][y] = 0
|
||||
else:
|
||||
lights[x][y] = 1
|
||||
assert False
|
||||
|
||||
res = 0
|
||||
for row in lights:
|
||||
res += sum(row)
|
||||
print(res)
|
||||
print(len(ons))
|
||||
print(sum(ons2.values()))
|
||||
|
124
2015/d7.py
124
2015/d7.py
@ -1,90 +1,54 @@
|
||||
from lib import *
|
||||
from lib import get_data
|
||||
|
||||
data = open(0).read()
|
||||
data = get_data(__file__)
|
||||
|
||||
part_2 = False
|
||||
if part_2:
|
||||
gates = {"b": 16076}
|
||||
|
||||
def run(wires={}):
|
||||
def get(a):
|
||||
try:
|
||||
return int(a)
|
||||
except ValueError:
|
||||
pass
|
||||
if a in wires:
|
||||
return wires[a]
|
||||
else:
|
||||
gates = {}
|
||||
return None
|
||||
|
||||
while "a" not in gates:
|
||||
while "a" not in wires:
|
||||
for line in data.splitlines():
|
||||
lhs, rhs = line.split(" -> ")
|
||||
if part_2 and rhs == "b":
|
||||
if rhs in wires:
|
||||
continue
|
||||
lhs = lhs.strip()
|
||||
if "NOT" in lhs:
|
||||
op, op1 = lhs.split(" ")
|
||||
assert op == "NOT"
|
||||
try:
|
||||
op1 = int(op1)
|
||||
gates[rhs] = ~op1 & 0xffff
|
||||
except ValueError:
|
||||
if op1 in gates and isinstance(gates[op1], int):
|
||||
gates[rhs] = ~gates[op1] & 0xffff
|
||||
elif "OR" in lhs:
|
||||
op1, op, op2 = lhs.split(" ")
|
||||
assert op == "OR"
|
||||
try:
|
||||
op1 = int(op1)
|
||||
except ValueError:
|
||||
if op1 in gates and isinstance(gates[op1], int):
|
||||
op1 = gates[op1]
|
||||
try:
|
||||
op2 = int(op2)
|
||||
except ValueError:
|
||||
if op2 in gates and isinstance(gates[op2], int):
|
||||
op2 = gates[op2]
|
||||
match lhs.split():
|
||||
case [a, "AND", b]:
|
||||
a, b = get(a), get(b)
|
||||
if a is not None and b is not None:
|
||||
wires[rhs] = a & b
|
||||
case [a, "OR", b]:
|
||||
a, b = get(a), get(b)
|
||||
if a is not None and b is not None:
|
||||
wires[rhs] = a | b
|
||||
case [a, "LSHIFT", b]:
|
||||
a, b = get(a), get(b)
|
||||
if a is not None and b is not None:
|
||||
wires[rhs] = a << b
|
||||
case [a, "RSHIFT", b]:
|
||||
a, b = get(a), get(b)
|
||||
if a is not None and b is not None:
|
||||
wires[rhs] = a >> b
|
||||
case ["NOT", a]:
|
||||
a = get(a)
|
||||
if a is not None:
|
||||
wires[rhs] = ~a & 0xFFFF
|
||||
case [a]:
|
||||
a = get(a)
|
||||
if a is not None:
|
||||
wires[rhs] = a
|
||||
return wires
|
||||
|
||||
if not (isinstance(op1, int) and isinstance(op2, int)):
|
||||
continue
|
||||
gates[rhs] = (op1 | op2)
|
||||
elif "AND" in lhs:
|
||||
op1, op, op2 = lhs.split(" ")
|
||||
assert op == "AND"
|
||||
try:
|
||||
op1 = int(op1)
|
||||
except ValueError:
|
||||
if op1 in gates and isinstance(gates[op1], int):
|
||||
op1 = gates[op1]
|
||||
try:
|
||||
op2 = int(op2)
|
||||
except ValueError:
|
||||
if op2 in gates and isinstance(gates[op2], int):
|
||||
op2 = gates[op2]
|
||||
|
||||
if not (isinstance(op1, int) and isinstance(op2, int)):
|
||||
continue
|
||||
gates[rhs] = (op1 & op2)
|
||||
elif "LSHIFT" in lhs:
|
||||
op1, op, op2 = lhs.split(" ")
|
||||
op2 = int(op2)
|
||||
try:
|
||||
op1 = int(op1)
|
||||
except ValueError:
|
||||
if op1 in gates:
|
||||
op1 = gates[op1]
|
||||
else:
|
||||
continue
|
||||
gates[rhs] = (op1 << op2) & 0xffff
|
||||
elif "RSHIFT" in lhs:
|
||||
op1, op, op2 = lhs.split(" ")
|
||||
op2 = int(op2)
|
||||
try:
|
||||
op1 = int(op1)
|
||||
except ValueError:
|
||||
if op1 in gates:
|
||||
op1 = gates[op1]
|
||||
else:
|
||||
continue
|
||||
gates[rhs] = (op1 >> op2) & 0xffff
|
||||
else:
|
||||
try:
|
||||
lhs = int(lhs)
|
||||
gates[rhs] = lhs
|
||||
except ValueError:
|
||||
if lhs in gates:
|
||||
gates[rhs] = gates[lhs]
|
||||
a = run()["a"]
|
||||
print(a)
|
||||
|
||||
print(gates["a"])
|
||||
a2 = run(wires={"b": a})["a"]
|
||||
print(a2)
|
||||
|
11
2015/d8.py
11
2015/d8.py
@ -1,9 +1,8 @@
|
||||
from lib import *
|
||||
from lib import get_data
|
||||
import re
|
||||
|
||||
data = open(0).read()
|
||||
part_1 = False
|
||||
data = get_data(__file__)
|
||||
|
||||
if part_1:
|
||||
r1 = re.compile(r"\\x[0-9a-f][0-9a-f]")
|
||||
r2 = re.compile(r"\\\\")
|
||||
r3 = re.compile(r"\\\"")
|
||||
@ -16,11 +15,11 @@ if part_1:
|
||||
line = r3.sub("^", line)
|
||||
enc += len(line) - 2
|
||||
print(mem - enc)
|
||||
else:
|
||||
|
||||
ori, enc = 0, 0
|
||||
for line in data.splitlines():
|
||||
ori += len(line)
|
||||
line = line.replace("\\", "\\\\")
|
||||
line = line.replace("\"", "\\\"")
|
||||
line = line.replace('"', '\\"')
|
||||
enc += len(line) + 2
|
||||
print(enc - ori)
|
||||
|
49
2015/d9.py
49
2015/d9.py
@ -1,42 +1,27 @@
|
||||
from lib import *
|
||||
from typing import Iterator
|
||||
from lib import get_data
|
||||
from itertools import permutations
|
||||
|
||||
# Just for fun instead of using itertools.permutations.
|
||||
def permutations(xs) -> Iterator:
|
||||
assert len(xs) > 0
|
||||
if len(xs) == 1:
|
||||
yield xs
|
||||
else:
|
||||
x = xs.pop()
|
||||
for p in permutations(xs):
|
||||
for i in range(len(p) + 1):
|
||||
pn = list(p)
|
||||
pn.insert(i, x)
|
||||
yield pn
|
||||
|
||||
part_1 = False
|
||||
data = open(0).read()
|
||||
data = get_data(__file__)
|
||||
|
||||
dists = {}
|
||||
nodes = set()
|
||||
for line in data.splitlines():
|
||||
path, dist = line.split(" = ")
|
||||
dist = int(dist)
|
||||
a, b = path.split(" to ")
|
||||
a, _, b, _, d = line.split()
|
||||
nodes.add(a)
|
||||
nodes.add(b)
|
||||
dist = int(d)
|
||||
dists[(a, b)] = dist
|
||||
dists[(b, a)] = dist
|
||||
|
||||
if part_1:
|
||||
mdist = 10**12
|
||||
for route in permutations(nodes):
|
||||
dist = sum([dists[(route[i], route[i + 1])] for i in range(len(route) - 1)])
|
||||
mdist = min(dist, mdist)
|
||||
print(mdist)
|
||||
else:
|
||||
mdist = 0
|
||||
for route in permutations(nodes):
|
||||
dist = sum([dists[(route[i], route[i + 1])] for i in range(len(route) - 1)])
|
||||
mdist = max(dist, mdist)
|
||||
print(mdist)
|
||||
d_min = 10**12
|
||||
d_max = 0
|
||||
for p in permutations(list(nodes)):
|
||||
d = 0
|
||||
for i in range(len(p) - 1):
|
||||
a, b = p[i], p[i + 1]
|
||||
d += dists[(a, b)]
|
||||
d_min = min(d, d_min)
|
||||
d_max = max(d, d_max)
|
||||
|
||||
print(d_min)
|
||||
print(d_max)
|
||||
|
33
lib.py
33
lib.py
@ -226,7 +226,7 @@ def count_trailing_repeats(lst):
|
||||
class A_Star(object):
|
||||
def __init__(self, starts, is_goal, h, d, neighbors):
|
||||
"""
|
||||
:param h: heuristic function
|
||||
:param h: heuristic function (never overestimate)
|
||||
:param d: cost from node to node function
|
||||
:param neighbors: neighbors function
|
||||
"""
|
||||
@ -297,6 +297,35 @@ def mod_inverse(a, m):
|
||||
|
||||
g, x, _ = egcd(a, m)
|
||||
if g != 1:
|
||||
raise Exception('Modular inverse does not exist')
|
||||
raise Exception("Modular inverse does not exist")
|
||||
else:
|
||||
return x % m
|
||||
|
||||
|
||||
class V:
|
||||
def __init__(self, *args):
|
||||
self.xs: tuple[int] = tuple(args)
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, V):
|
||||
return all(v1 == v2 for v1, v2 in zip(self.xs, other.xs))
|
||||
elif hasattr(other, "__len__") and len(self.xs) == len(other):
|
||||
return all(v1 == v2 for v1, v2 in zip(self.xs, other))
|
||||
return False
|
||||
|
||||
def __getitem__(self, i: int):
|
||||
return self.xs[i]
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.xs)
|
||||
|
||||
def __add__(self, other):
|
||||
if isinstance(other, V):
|
||||
return V(*[v1 + v2 for v1, v2 in zip(self.xs, other.xs)])
|
||||
assert hasattr(other, "__len__"), f"V.__add__({self}, {other}) missing `len`"
|
||||
assert len(self.xs) == len(other), f"V.__add__({self}, {other}) `len` mismatch"
|
||||
return V(*[v1 + v2 for v1, v2 in zip(self.xs, other)])
|
||||
|
||||
def __repr__(self):
|
||||
s = ", ".join(map(str, self.xs))
|
||||
return f"V({s})"
|
||||
|
Loading…
Reference in New Issue
Block a user