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
|
floor = 0
|
||||||
for i, c in enumerate(data):
|
for i, c in enumerate(data):
|
||||||
@ -10,13 +11,6 @@ for i, c in enumerate(data):
|
|||||||
floor += 1
|
floor += 1
|
||||||
elif c == ")":
|
elif c == ")":
|
||||||
floor -= 1
|
floor -= 1
|
||||||
else:
|
if floor == -1:
|
||||||
print(c)
|
|
||||||
assert False
|
|
||||||
|
|
||||||
if part_2 and floor == -1:
|
|
||||||
print(i + 1)
|
print(i + 1)
|
||||||
break
|
break
|
||||||
|
|
||||||
if not part_2:
|
|
||||||
print(floor)
|
|
||||||
|
54
2015/d10.py
54
2015/d10.py
@ -1,35 +1,29 @@
|
|||||||
from functools import lru_cache
|
from lib import get_data
|
||||||
data = open(0).read().strip()
|
|
||||||
|
|
||||||
part_1 = False
|
data = get_data(__file__)
|
||||||
if part_1:
|
|
||||||
repeats = 40
|
|
||||||
else:
|
|
||||||
repeats = 50
|
|
||||||
|
|
||||||
@lru_cache
|
|
||||||
def look_and_say(data: str) -> str:
|
def iter(xs):
|
||||||
r = ""
|
if not xs:
|
||||||
i = 0
|
return []
|
||||||
while i < len(data):
|
grouped = []
|
||||||
count = 0
|
current_element = xs[0]
|
||||||
c = data[i]
|
count = 1
|
||||||
while i < len(data) and data[i] == c:
|
for element in xs[1:]:
|
||||||
|
if element == current_element:
|
||||||
count += 1
|
count += 1
|
||||||
i += 1
|
else:
|
||||||
r += f"{count}{c}"
|
grouped.append(count)
|
||||||
return r
|
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))
|
||||||
|
23
2015/d11.py
23
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):
|
def is_valid(pw):
|
||||||
# Passwords must include one increasing straight of at least three letters,
|
# Passwords must include one increasing straight of at least three letters,
|
||||||
@ -26,24 +29,26 @@ def is_valid(pw):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def inc(pw):
|
def inc(pw):
|
||||||
pw = list(map(ord, pw))
|
pw = list(map(ord, pw))
|
||||||
for i in range(len(pw) - 1, -1, -1):
|
for i in range(len(pw) - 1, -1, -1):
|
||||||
pw[i] += 1
|
pw[i] += 1
|
||||||
if pw[i] == ord('z') + 1:
|
if pw[i] == ord("z") + 1:
|
||||||
pw[i] = ord('a')
|
pw[i] = ord("a")
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
return "".join(map(chr, pw))
|
return "".join(map(chr, pw))
|
||||||
|
|
||||||
part_1 = False
|
|
||||||
|
part_1 = True
|
||||||
valid_count = 0
|
valid_count = 0
|
||||||
while True:
|
while True:
|
||||||
data = inc(data)
|
data = inc(data)
|
||||||
if is_valid(data):
|
if is_valid(data):
|
||||||
valid_count += 1
|
valid_count += 1
|
||||||
if part_1 and valid_count == 1:
|
if part_1 and valid_count == 1:
|
||||||
break
|
print(data)
|
||||||
elif valid_count == 2:
|
elif valid_count == 2:
|
||||||
break
|
print(data)
|
||||||
print(data)
|
break
|
||||||
|
54
2015/d12.py
54
2015/d12.py
@ -1,27 +1,37 @@
|
|||||||
|
from lib import get_data
|
||||||
import json
|
import json
|
||||||
|
|
||||||
data = open(0).read().strip()
|
data = get_data(__file__).strip()
|
||||||
part_2 = False
|
|
||||||
|
|
||||||
def addup(d):
|
o = json.loads(data)
|
||||||
r = 0
|
|
||||||
if isinstance(d, list):
|
|
||||||
for e in d:
|
def xsum(obj, part_2=False):
|
||||||
v = addup(e)
|
t = 0
|
||||||
if v is not None:
|
if type(obj) is int:
|
||||||
r += v
|
t += obj
|
||||||
elif isinstance(d, dict):
|
elif type(obj) is list:
|
||||||
for e in d.values():
|
for o in obj:
|
||||||
v = addup(e)
|
t += xsum(o, part_2)
|
||||||
if v is None:
|
elif type(obj) is dict:
|
||||||
return 0
|
if part_2:
|
||||||
r += v
|
st = 0
|
||||||
elif isinstance(d, str):
|
for o in obj.values():
|
||||||
if part_2 and d == "red":
|
st += xsum(o, part_2)
|
||||||
return None
|
if type(o) is str and o == "red":
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
t += st
|
||||||
|
else:
|
||||||
|
for o in obj.values():
|
||||||
|
t += xsum(o, part_2)
|
||||||
|
elif type(obj) is str:
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
r += d
|
print(obj)
|
||||||
return r
|
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
|
from itertools import permutations
|
||||||
data = open(0).read().strip()
|
|
||||||
|
|
||||||
part_2 = False
|
data = get_data(__file__).strip()
|
||||||
|
|
||||||
|
pairs = defaultdict(int)
|
||||||
people = set()
|
people = set()
|
||||||
scores = {}
|
|
||||||
for line in data.splitlines():
|
for line in data.splitlines():
|
||||||
a, _, wl, score, _, _, _, _, _, _, b = line.split()
|
a, _, gainlose, amount, _, _, _, _, _, _, b = line[:-1].split()
|
||||||
b = b.replace(".", "")
|
amount = int(amount)
|
||||||
score = int(score)
|
if gainlose == "lose":
|
||||||
if wl == "lose":
|
amount = -amount
|
||||||
score = -score
|
pairs[(a, b)] = amount
|
||||||
people.add(a)
|
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
|
def calc_gain(people):
|
||||||
for p in permutations(list(people)):
|
maxgain = 0
|
||||||
s = 0
|
for xs in permutations(list(people)):
|
||||||
for i in range(len(p)):
|
gain = 0
|
||||||
a, b = p[i], p[(i + 1) % len(p)]
|
for i in range(len(xs)):
|
||||||
s += scores[(a, b)]
|
gain += pairs[(xs[i], xs[(i + 1) % len(xs)])]
|
||||||
s += scores[(b, a)]
|
gain += pairs[(xs[(i + 1) % len(xs)], xs[i])]
|
||||||
max_score = max(max_score, s)
|
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
|
from lib import get_data
|
||||||
data = open(0).read().strip()
|
from lib import ints, fst
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
part_1 = False
|
data = get_data(__file__).strip()
|
||||||
|
deers = []
|
||||||
rds = []
|
|
||||||
max_dist = 0
|
|
||||||
gtime = 2503
|
|
||||||
rds = []
|
|
||||||
for line in data.splitlines():
|
for line in data.splitlines():
|
||||||
speed, time, rest = lib.str_to_ints(line)
|
speed, time, rest = ints(line)
|
||||||
rds.append([speed, time, rest, 0, 0, 0])
|
deers.append([0, speed, time, rest, time, 0])
|
||||||
speed *= 1000
|
|
||||||
|
|
||||||
dist = 0
|
points = defaultdict(int)
|
||||||
ctime = 0
|
for _ in range(2503):
|
||||||
while ctime < gtime:
|
max_dists = defaultdict(list)
|
||||||
t = min(time, gtime - ctime)
|
for i, deer in enumerate(deers):
|
||||||
dist += (speed * t)
|
dist, speed, time, rest, time_left, rest_left = deer
|
||||||
ctime += time
|
if time_left > 0:
|
||||||
ctime += rest
|
time_left -= 1
|
||||||
max_dist = max(dist, max_dist)
|
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:
|
deer[0] = dist
|
||||||
print(max_dist // 1000)
|
deer[4] = time_left
|
||||||
|
deer[5] = rest_left
|
||||||
|
|
||||||
scores = [0 for _ in range(len(rds))]
|
max_deers = max(max_dists.items())
|
||||||
for _ in range(gtime):
|
for di in max_deers[1]:
|
||||||
for i in range(len(rds)):
|
points[di] += 1
|
||||||
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_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()))
|
||||||
|
30
2015/d2.py
30
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")))
|
|
||||||
slack = min([l * w, w * h, h * l])
|
|
||||||
a += (2*l*w + 2*w*h + 2*h*l + slack)
|
|
||||||
else:
|
|
||||||
a = 0
|
|
||||||
for line in data:
|
|
||||||
l, w, h = list(map(int, line.split("x")))
|
|
||||||
sd = min([2 * (l + w), 2 * (w + h), 2 * (h + l)])
|
|
||||||
a += sd + (l * w * h)
|
|
||||||
|
|
||||||
|
a = 0
|
||||||
|
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
|
||||||
|
print(a)
|
||||||
|
|
||||||
|
a = 0
|
||||||
|
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)
|
print(a)
|
||||||
|
@ -4,6 +4,7 @@ import lib
|
|||||||
data = int(open(0).read().strip())
|
data = int(open(0).read().strip())
|
||||||
part_1 = False
|
part_1 = False
|
||||||
|
|
||||||
|
|
||||||
def calc(n):
|
def calc(n):
|
||||||
fs = lib.prime_factors(n)
|
fs = lib.prime_factors(n)
|
||||||
vs = set([1, n])
|
vs = set([1, n])
|
||||||
@ -21,6 +22,7 @@ def calc(n):
|
|||||||
r += e * 11
|
r += e * 11
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
for i in range(3, 10000000):
|
for i in range(3, 10000000):
|
||||||
c = calc(i)
|
c = calc(i)
|
||||||
if c >= data:
|
if c >= data:
|
||||||
|
33
2015/d3.py
33
2015/d3.py
@ -1,9 +1,7 @@
|
|||||||
import sys
|
from lib import get_data
|
||||||
from lib import *
|
from lib import V
|
||||||
|
|
||||||
data = open(0).read()
|
data = get_data(__file__)
|
||||||
|
|
||||||
part_1 = False
|
|
||||||
|
|
||||||
DIRS = {
|
DIRS = {
|
||||||
"^": (-1, 0),
|
"^": (-1, 0),
|
||||||
@ -12,30 +10,27 @@ DIRS = {
|
|||||||
"<": (0, -1),
|
"<": (0, -1),
|
||||||
}
|
}
|
||||||
|
|
||||||
if part_1:
|
pos = V(0, 0)
|
||||||
pos = (0, 0)
|
poss = set([pos])
|
||||||
poss = set([pos])
|
|
||||||
|
|
||||||
for c in data:
|
for c in data:
|
||||||
d = DIRS[c]
|
d = DIRS[c]
|
||||||
pos = pos[0] + d[0], pos[1] + d[1]
|
pos = pos + d
|
||||||
poss.add(pos)
|
poss.add(pos)
|
||||||
|
|
||||||
print(len(poss))
|
print(len(poss))
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
a = (0, 0)
|
a = V(0, 0)
|
||||||
b = (0, 0)
|
b = V(0, 0)
|
||||||
poss = set([a, b])
|
poss = set([a, b])
|
||||||
for i, c in enumerate(data):
|
for i, c in enumerate(data):
|
||||||
if i % 2 == 0:
|
if i % 2 == 0:
|
||||||
d = DIRS[c]
|
d = DIRS[c]
|
||||||
a = a[0] + d[0], a[1] + d[1]
|
a = a + d
|
||||||
poss.add(a)
|
poss.add(a)
|
||||||
else:
|
else:
|
||||||
d = DIRS[c]
|
d = DIRS[c]
|
||||||
b = b[0] + d[0], b[1] + d[1]
|
b = b + d
|
||||||
poss.add(b)
|
poss.add(b)
|
||||||
|
|
||||||
print(len(poss))
|
print(len(poss))
|
||||||
sys.exit(0)
|
|
||||||
|
29
2015/d4.py
29
2015/d4.py
@ -1,22 +1,15 @@
|
|||||||
from lib import *
|
from lib import get_data
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
||||||
part_1 = True
|
data = get_data(__file__).strip()
|
||||||
|
|
||||||
if part_1:
|
for digits in [5, 6]:
|
||||||
digits = 5
|
for i in range(10**9):
|
||||||
else:
|
text = data + str(i)
|
||||||
digits = 6
|
md5_hash = hashlib.md5(text.encode()).hexdigest()
|
||||||
|
for c in md5_hash[:digits]:
|
||||||
data = open(0).read().strip()
|
if c != "0":
|
||||||
|
break
|
||||||
for i in range(10**9):
|
else:
|
||||||
text = data + str(i)
|
print(i)
|
||||||
md5_hash = hashlib.md5(text.encode()).hexdigest()
|
|
||||||
for c in md5_hash[:digits]:
|
|
||||||
if c != "0":
|
|
||||||
break
|
break
|
||||||
else:
|
|
||||||
print(i)
|
|
||||||
break
|
|
||||||
|
|
||||||
|
97
2015/d5.py
97
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():
|
|
||||||
vc = 0
|
|
||||||
for c in line:
|
|
||||||
if c in "aoeui":
|
|
||||||
vc += 1
|
|
||||||
if vc < 3:
|
|
||||||
continue
|
|
||||||
|
|
||||||
prev = None
|
def is_nice(line):
|
||||||
for c in line:
|
# It contains at least three vowels (aeiou only), like aei, xazegov, or aeiouaeiouaeiou.
|
||||||
if c == prev:
|
vc = 0
|
||||||
break
|
for v in "aeiou":
|
||||||
prev = c
|
vc += line.count(v)
|
||||||
else:
|
if vc < 3:
|
||||||
continue
|
return False
|
||||||
|
|
||||||
contains = False
|
# It contains at least one letter that appears twice in a row, like xx,
|
||||||
ss = ["ab", "cd", "pq", "xy"]
|
# abcdde (dd), or aabbccdd (aa, bb, cc, or dd).
|
||||||
for s in ss:
|
for i in range(len(line) - 1):
|
||||||
if s in line:
|
if line[i] == line[i + 1]:
|
||||||
contains = True
|
break
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
if contains:
|
# It does not contain the strings ab, cd, pq, or xy, even if they are
|
||||||
continue
|
# part of one of the other requirements.
|
||||||
res += 1
|
for i in range(len(line) - 1):
|
||||||
print(res)
|
cc = "".join(line[i : i + 2])
|
||||||
else:
|
if cc in ["ab", "cd", "pq", "xy"]:
|
||||||
res = 0
|
return False
|
||||||
for line in data.splitlines():
|
return True
|
||||||
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]:
|
def is_nice_2(line):
|
||||||
break
|
good = False
|
||||||
else:
|
for i in range(len(line) - 1):
|
||||||
continue
|
cc = "".join(line[i : i + 2])
|
||||||
res += 1
|
for j in range(i + 2, len(line) - 1):
|
||||||
print(res)
|
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()
|
data = get_data(__file__)
|
||||||
|
|
||||||
part_2 = True
|
|
||||||
lights = [[0 for _ in range(1000)] for _ in range(1000)]
|
|
||||||
|
|
||||||
|
ons = set()
|
||||||
|
ons2 = DD(int)
|
||||||
for line in data.splitlines():
|
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 x in range(x1, x2 + 1):
|
||||||
for y in range(y1, y2 + 1):
|
for y in range(y1, y2 + 1):
|
||||||
if part_2:
|
if "off" in line:
|
||||||
if "on" in line:
|
if (x, y) in ons:
|
||||||
lights[x][y] += 1
|
ons.remove((x, y))
|
||||||
elif "off" in line:
|
ons2[(x, y)] = max(ons2[(x, y)] - 1, 0)
|
||||||
lights[x][y] = max(0, lights[x][y] - 1)
|
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:
|
else:
|
||||||
lights[x][y] += 2
|
ons.add((x, y))
|
||||||
|
ons2[(x, y)] += 2
|
||||||
else:
|
else:
|
||||||
if "on" in line:
|
assert False
|
||||||
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
|
|
||||||
|
|
||||||
res = 0
|
print(len(ons))
|
||||||
for row in lights:
|
print(sum(ons2.values()))
|
||||||
res += sum(row)
|
|
||||||
print(res)
|
|
||||||
|
134
2015/d7.py
134
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}
|
|
||||||
else:
|
|
||||||
gates = {}
|
|
||||||
|
|
||||||
while "a" not in gates:
|
def run(wires={}):
|
||||||
for line in data.splitlines():
|
def get(a):
|
||||||
lhs, rhs = line.split(" -> ")
|
try:
|
||||||
if part_2 and rhs == "b":
|
return int(a)
|
||||||
continue
|
except ValueError:
|
||||||
lhs = lhs.strip()
|
pass
|
||||||
if "NOT" in lhs:
|
if a in wires:
|
||||||
op, op1 = lhs.split(" ")
|
return wires[a]
|
||||||
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]
|
|
||||||
|
|
||||||
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:
|
else:
|
||||||
try:
|
return None
|
||||||
lhs = int(lhs)
|
|
||||||
gates[rhs] = lhs
|
|
||||||
except ValueError:
|
|
||||||
if lhs in gates:
|
|
||||||
gates[rhs] = gates[lhs]
|
|
||||||
|
|
||||||
print(gates["a"])
|
while "a" not in wires:
|
||||||
|
for line in data.splitlines():
|
||||||
|
lhs, rhs = line.split(" -> ")
|
||||||
|
if rhs in wires:
|
||||||
|
continue
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
a = run()["a"]
|
||||||
|
print(a)
|
||||||
|
|
||||||
|
a2 = run(wires={"b": a})["a"]
|
||||||
|
print(a2)
|
||||||
|
45
2015/d8.py
45
2015/d8.py
@ -1,26 +1,25 @@
|
|||||||
from lib import *
|
from lib import get_data
|
||||||
|
import re
|
||||||
|
|
||||||
data = open(0).read()
|
data = get_data(__file__)
|
||||||
part_1 = False
|
|
||||||
|
|
||||||
if part_1:
|
r1 = re.compile(r"\\x[0-9a-f][0-9a-f]")
|
||||||
r1 = re.compile(r"\\x[0-9a-f][0-9a-f]")
|
r2 = re.compile(r"\\\\")
|
||||||
r2 = re.compile(r"\\\\")
|
r3 = re.compile(r"\\\"")
|
||||||
r3 = re.compile(r"\\\"")
|
|
||||||
|
|
||||||
enc, mem = 0, 0
|
enc, mem = 0, 0
|
||||||
for line in data.splitlines():
|
for line in data.splitlines():
|
||||||
mem += len(line)
|
mem += len(line)
|
||||||
line = r1.sub("^", line)
|
line = r1.sub("^", line)
|
||||||
line = r2.sub("^", line)
|
line = r2.sub("^", line)
|
||||||
line = r3.sub("^", line)
|
line = r3.sub("^", line)
|
||||||
enc += len(line) - 2
|
enc += len(line) - 2
|
||||||
print(mem - enc)
|
print(mem - enc)
|
||||||
else:
|
|
||||||
ori, enc = 0, 0
|
ori, enc = 0, 0
|
||||||
for line in data.splitlines():
|
for line in data.splitlines():
|
||||||
ori += len(line)
|
ori += len(line)
|
||||||
line = line.replace("\\", "\\\\")
|
line = line.replace("\\", "\\\\")
|
||||||
line = line.replace("\"", "\\\"")
|
line = line.replace('"', '\\"')
|
||||||
enc += len(line) + 2
|
enc += len(line) + 2
|
||||||
print(enc - ori)
|
print(enc - ori)
|
||||||
|
49
2015/d9.py
49
2015/d9.py
@ -1,42 +1,27 @@
|
|||||||
from lib import *
|
from lib import get_data
|
||||||
from typing import Iterator
|
from itertools import permutations
|
||||||
|
|
||||||
# Just for fun instead of using itertools.permutations.
|
data = get_data(__file__)
|
||||||
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()
|
|
||||||
|
|
||||||
dists = {}
|
dists = {}
|
||||||
nodes = set()
|
nodes = set()
|
||||||
for line in data.splitlines():
|
for line in data.splitlines():
|
||||||
path, dist = line.split(" = ")
|
a, _, b, _, d = line.split()
|
||||||
dist = int(dist)
|
|
||||||
a, b = path.split(" to ")
|
|
||||||
nodes.add(a)
|
nodes.add(a)
|
||||||
nodes.add(b)
|
nodes.add(b)
|
||||||
|
dist = int(d)
|
||||||
dists[(a, b)] = dist
|
dists[(a, b)] = dist
|
||||||
dists[(b, a)] = dist
|
dists[(b, a)] = dist
|
||||||
|
|
||||||
if part_1:
|
d_min = 10**12
|
||||||
mdist = 10**12
|
d_max = 0
|
||||||
for route in permutations(nodes):
|
for p in permutations(list(nodes)):
|
||||||
dist = sum([dists[(route[i], route[i + 1])] for i in range(len(route) - 1)])
|
d = 0
|
||||||
mdist = min(dist, mdist)
|
for i in range(len(p) - 1):
|
||||||
print(mdist)
|
a, b = p[i], p[i + 1]
|
||||||
else:
|
d += dists[(a, b)]
|
||||||
mdist = 0
|
d_min = min(d, d_min)
|
||||||
for route in permutations(nodes):
|
d_max = max(d, d_max)
|
||||||
dist = sum([dists[(route[i], route[i + 1])] for i in range(len(route) - 1)])
|
|
||||||
mdist = max(dist, mdist)
|
print(d_min)
|
||||||
print(mdist)
|
print(d_max)
|
||||||
|
33
lib.py
33
lib.py
@ -226,7 +226,7 @@ def count_trailing_repeats(lst):
|
|||||||
class A_Star(object):
|
class A_Star(object):
|
||||||
def __init__(self, starts, is_goal, h, d, neighbors):
|
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 d: cost from node to node function
|
||||||
:param neighbors: neighbors function
|
:param neighbors: neighbors function
|
||||||
"""
|
"""
|
||||||
@ -297,6 +297,35 @@ def mod_inverse(a, m):
|
|||||||
|
|
||||||
g, x, _ = egcd(a, m)
|
g, x, _ = egcd(a, m)
|
||||||
if g != 1:
|
if g != 1:
|
||||||
raise Exception('Modular inverse does not exist')
|
raise Exception("Modular inverse does not exist")
|
||||||
else:
|
else:
|
||||||
return x % m
|
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