Add 2022 solutions
This commit is contained in:
parent
d582dfc777
commit
e9ba9cee63
20
2022/d1.py
Normal file
20
2022/d1.py
Normal file
@ -0,0 +1,20 @@
|
||||
from lib import *
|
||||
|
||||
def solve(input: Input, second=False):
|
||||
ps = input.text.split("\n\n")
|
||||
xss = map(lambda p: map(int, p.splitlines()), ps)
|
||||
xs = list(map(sum, xss))
|
||||
if not second:
|
||||
return max(xs)
|
||||
xs.sort()
|
||||
return sum(xs[-3:])
|
||||
|
||||
def main():
|
||||
DAY_INPUT = "d1.txt"
|
||||
print("Solution 1:", solve(Input(DAY_INPUT)))
|
||||
assert solve(Input(DAY_INPUT)) == 69883
|
||||
print("Solution 2:", solve(Input(DAY_INPUT), True))
|
||||
assert solve(Input(DAY_INPUT), True) == 207576
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
216
2022/d10.py
Normal file
216
2022/d10.py
Normal file
@ -0,0 +1,216 @@
|
||||
import re
|
||||
from string import ascii_lowercase, ascii_uppercase
|
||||
|
||||
EXAMPLE = """
|
||||
addx 15
|
||||
addx -11
|
||||
addx 6
|
||||
addx -3
|
||||
addx 5
|
||||
addx -1
|
||||
addx -8
|
||||
addx 13
|
||||
addx 4
|
||||
noop
|
||||
addx -1
|
||||
addx 5
|
||||
addx -1
|
||||
addx 5
|
||||
addx -1
|
||||
addx 5
|
||||
addx -1
|
||||
addx 5
|
||||
addx -1
|
||||
addx -35
|
||||
addx 1
|
||||
addx 24
|
||||
addx -19
|
||||
addx 1
|
||||
addx 16
|
||||
addx -11
|
||||
noop
|
||||
noop
|
||||
addx 21
|
||||
addx -15
|
||||
noop
|
||||
noop
|
||||
addx -3
|
||||
addx 9
|
||||
addx 1
|
||||
addx -3
|
||||
addx 8
|
||||
addx 1
|
||||
addx 5
|
||||
noop
|
||||
noop
|
||||
noop
|
||||
noop
|
||||
noop
|
||||
addx -36
|
||||
noop
|
||||
addx 1
|
||||
addx 7
|
||||
noop
|
||||
noop
|
||||
noop
|
||||
addx 2
|
||||
addx 6
|
||||
noop
|
||||
noop
|
||||
noop
|
||||
noop
|
||||
noop
|
||||
addx 1
|
||||
noop
|
||||
noop
|
||||
addx 7
|
||||
addx 1
|
||||
noop
|
||||
addx -13
|
||||
addx 13
|
||||
addx 7
|
||||
noop
|
||||
addx 1
|
||||
addx -33
|
||||
noop
|
||||
noop
|
||||
noop
|
||||
addx 2
|
||||
noop
|
||||
noop
|
||||
noop
|
||||
addx 8
|
||||
noop
|
||||
addx -1
|
||||
addx 2
|
||||
addx 1
|
||||
noop
|
||||
addx 17
|
||||
addx -9
|
||||
addx 1
|
||||
addx 1
|
||||
addx -3
|
||||
addx 11
|
||||
noop
|
||||
noop
|
||||
addx 1
|
||||
noop
|
||||
addx 1
|
||||
noop
|
||||
noop
|
||||
addx -13
|
||||
addx -19
|
||||
addx 1
|
||||
addx 3
|
||||
addx 26
|
||||
addx -30
|
||||
addx 12
|
||||
addx -1
|
||||
addx 3
|
||||
addx 1
|
||||
noop
|
||||
noop
|
||||
noop
|
||||
addx -9
|
||||
addx 18
|
||||
addx 1
|
||||
addx 2
|
||||
noop
|
||||
noop
|
||||
addx 9
|
||||
noop
|
||||
noop
|
||||
noop
|
||||
addx -1
|
||||
addx 2
|
||||
addx -37
|
||||
addx 1
|
||||
addx 3
|
||||
noop
|
||||
addx 15
|
||||
addx -21
|
||||
addx 22
|
||||
addx -6
|
||||
addx 1
|
||||
noop
|
||||
addx 2
|
||||
addx 1
|
||||
noop
|
||||
addx -10
|
||||
noop
|
||||
noop
|
||||
addx 20
|
||||
addx 1
|
||||
addx 2
|
||||
addx 2
|
||||
addx -6
|
||||
addx -11
|
||||
noop
|
||||
noop
|
||||
noop
|
||||
"""
|
||||
|
||||
def clean(text: str) -> list[str]:
|
||||
return list(filter(lambda l: l.strip() != "", text.splitlines()))
|
||||
|
||||
def solve(lines: list[str]):
|
||||
res = 0
|
||||
inst_count = 0
|
||||
value_x = 1
|
||||
cycles = [20, 60, 100, 140, 180, 220]
|
||||
for i, line in enumerate(lines):
|
||||
inst_count_before = inst_count
|
||||
addx = 0
|
||||
if line.startswith("noop"):
|
||||
inst_count += 1
|
||||
elif line.startswith("addx"):
|
||||
v = int(line.split()[1])
|
||||
value_x += v
|
||||
inst_count += 2
|
||||
addx = v
|
||||
else:
|
||||
raise Exception("Unexpected {line}")
|
||||
|
||||
for c in cycles:
|
||||
if inst_count_before < c and inst_count >= c:
|
||||
strength = (value_x - addx) * c
|
||||
res += strength
|
||||
print(inst_count, strength)
|
||||
# 15:10
|
||||
return res
|
||||
|
||||
def solve2(lines: list[str]):
|
||||
x_values = [1]
|
||||
for _, line in enumerate(lines):
|
||||
if line.startswith("noop"):
|
||||
x_values.append(x_values[-1])
|
||||
elif line.startswith("addx"):
|
||||
x_values.append(x_values[-1])
|
||||
v = int(line.split()[1])
|
||||
x_values.append(x_values[-1] + v)
|
||||
|
||||
s = ""
|
||||
for i, x in enumerate(x_values):
|
||||
col = i % 40
|
||||
if col == 0:
|
||||
s += "\n"
|
||||
if col == x - 1 or col == x or col == x + 1:
|
||||
s += "#"
|
||||
else:
|
||||
s += " "
|
||||
print(s)
|
||||
# 25:20
|
||||
|
||||
|
||||
def main():
|
||||
example = clean(EXAMPLE)
|
||||
print("Example 1:", solve(example))
|
||||
|
||||
data = clean(open("d10.txt").read())
|
||||
print("Solution 1:", solve(data))
|
||||
|
||||
data = clean(open("d10.txt").read())
|
||||
print("Solution 2:", solve2(data))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
143
2022/d11.py
Normal file
143
2022/d11.py
Normal file
@ -0,0 +1,143 @@
|
||||
import re
|
||||
from string import ascii_lowercase, ascii_uppercase
|
||||
|
||||
def extract_single_digit(line: str) -> int:
|
||||
r = re.compile(r"\d+")
|
||||
for m in r.findall(line):
|
||||
return int(m)
|
||||
raise Exception("No single digit sequence in '{line}'")
|
||||
|
||||
def extract_digits_list(line: str) -> list[int]:
|
||||
r = re.compile(r"\d+")
|
||||
return list(map(int, r.findall(line)))
|
||||
|
||||
EXAMPLE = """
|
||||
Monkey 0:
|
||||
Starting items: 79, 98
|
||||
Operation: new = old * 19
|
||||
Test: divisible by 23
|
||||
If true: throw to monkey 2
|
||||
If false: throw to monkey 3
|
||||
|
||||
Monkey 1:
|
||||
Starting items: 54, 65, 75, 74
|
||||
Operation: new = old + 6
|
||||
Test: divisible by 19
|
||||
If true: throw to monkey 2
|
||||
If false: throw to monkey 0
|
||||
|
||||
Monkey 2:
|
||||
Starting items: 79, 60, 97
|
||||
Operation: new = old * old
|
||||
Test: divisible by 13
|
||||
If true: throw to monkey 1
|
||||
If false: throw to monkey 3
|
||||
|
||||
Monkey 3:
|
||||
Starting items: 74
|
||||
Operation: new = old + 3
|
||||
Test: divisible by 17
|
||||
If true: throw to monkey 0
|
||||
If false: throw to monkey 1
|
||||
"""
|
||||
|
||||
def clean(text: str) -> list[str]:
|
||||
return list(filter(lambda l: l.strip() != "", text.splitlines()))
|
||||
|
||||
def get_monkesy(lines):
|
||||
monkeys = []
|
||||
for i, line in enumerate(lines):
|
||||
if line.startswith("Monkey"):
|
||||
d = extract_single_digit(line)
|
||||
monkeys.append([d])
|
||||
elif line.strip().startswith("Starting"):
|
||||
d = extract_digits_list(line)
|
||||
monkeys[-1].append(d)
|
||||
elif line.strip().startswith("Operation"):
|
||||
if "old * old" in line:
|
||||
f = lambda y: y * y
|
||||
monkeys[-1].append(f)
|
||||
elif "*" in line:
|
||||
d = extract_single_digit(line)
|
||||
f = lambda x: (lambda y: x * y)
|
||||
f = f(d)
|
||||
monkeys[-1].append(f)
|
||||
elif "+" in line:
|
||||
d = extract_single_digit(line)
|
||||
f = lambda x: (lambda y: x + y)
|
||||
f = f(d)
|
||||
monkeys[-1].append(f)
|
||||
else:
|
||||
raise Exception(line)
|
||||
elif line.strip().startswith("Test"):
|
||||
d = extract_single_digit(line)
|
||||
monkeys[-1].append(d)
|
||||
elif line.strip().startswith("If true"):
|
||||
d = extract_single_digit(line)
|
||||
monkeys[-1].append(d)
|
||||
elif line.strip().startswith("If false"):
|
||||
d = extract_single_digit(line)
|
||||
monkeys[-1].append(d)
|
||||
else:
|
||||
print(line)
|
||||
raise Exception("Unexpected line.")
|
||||
for m in monkeys:
|
||||
m.append(0)
|
||||
return monkeys
|
||||
|
||||
def solve(lines: list[str]):
|
||||
monkeys = get_monkesy(lines)
|
||||
for _ in range(20):
|
||||
for monkey in monkeys:
|
||||
id, items, op, test, if_true, if_false, count = monkey
|
||||
while items:
|
||||
item = items.pop()
|
||||
monkey[6] += 1
|
||||
worry = item
|
||||
worry = op(worry)
|
||||
worry //= 3
|
||||
if worry % test == 0:
|
||||
monkeys[if_true][1].append(worry)
|
||||
else:
|
||||
monkeys[if_false][1].append(worry)
|
||||
monkeys[id][1] = monkeys[id][1][1:]
|
||||
counts = sorted([m[6] for m in monkeys])[-2:]
|
||||
return counts[0] * counts[1]
|
||||
|
||||
def solve2(lines: list[str]):
|
||||
monkeys = get_monkesy(lines)
|
||||
mod = 1
|
||||
for m in monkeys:
|
||||
mod *= m[3]
|
||||
|
||||
for _ in range(10000):
|
||||
for monkey in monkeys:
|
||||
id, items, op, test, if_true, if_false, count = monkey
|
||||
for item in list(items):
|
||||
monkey[6] += 1
|
||||
worry = item
|
||||
worry = op(worry)
|
||||
worry %= mod
|
||||
if worry % test == 0:
|
||||
monkeys[if_true][1].append(worry)
|
||||
else:
|
||||
monkeys[if_false][1].append(worry)
|
||||
monkeys[id][1] = monkeys[id][1][1:]
|
||||
counts = sorted([m[6] for m in monkeys])[-2:]
|
||||
return counts[0] * counts[1]
|
||||
|
||||
def main():
|
||||
example = clean(EXAMPLE)
|
||||
print("Example 1:", solve(example))
|
||||
|
||||
data = clean(open("d11.txt").read())
|
||||
print("Solution 1:", solve(data))
|
||||
|
||||
example = clean(EXAMPLE)
|
||||
print("Example 2:", solve2(example))
|
||||
|
||||
data = clean(open("d11.txt").read())
|
||||
print("Solution 2:", solve2(data))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
120
2022/d12.py
Normal file
120
2022/d12.py
Normal file
@ -0,0 +1,120 @@
|
||||
import lib
|
||||
|
||||
EXAMPLE = """
|
||||
Sabqponm
|
||||
abcryxxl
|
||||
accszExk
|
||||
acctuvwj
|
||||
abdefghi
|
||||
"""
|
||||
|
||||
def neighbors_4(row, col, rows, cols):
|
||||
n = []
|
||||
for r, c in [(1, 0), (-1, 0), (0, 1), (0, -1)]:
|
||||
new_row, new_col = row + r, col + c
|
||||
if new_row >= 0 and new_row < rows and new_col >= 0 and new_col < cols:
|
||||
n.append((new_row, new_col))
|
||||
return n
|
||||
|
||||
def solve(lines: list[str]):
|
||||
start = (0, 0)
|
||||
end = (0, 0)
|
||||
rows = len(lines)
|
||||
cols = len(lines[0])
|
||||
heights = []
|
||||
dists = []
|
||||
for (row, line) in enumerate(lines):
|
||||
heights.append([])
|
||||
dists.append([])
|
||||
for (col, c) in enumerate(line):
|
||||
if c == 'S':
|
||||
start = (row, col)
|
||||
heights[row].append(0)
|
||||
dists[row].append(0)
|
||||
elif c == 'E':
|
||||
end = (row, col)
|
||||
heights[row].append(26)
|
||||
dists[row].append(2**16)
|
||||
else:
|
||||
heights[row].append(ord(lines[row][col]) - ord('a'))
|
||||
dists[row].append(2**16)
|
||||
|
||||
active_fields = [start]
|
||||
while active_fields:
|
||||
row, col = active_fields.pop()
|
||||
current_dist = dists[row][col]
|
||||
current_height = heights[row][col]
|
||||
for row, col in neighbors_4(row, col, rows, cols):
|
||||
pot_height = heights[row][col]
|
||||
if current_height < pot_height - 1:
|
||||
continue
|
||||
if current_dist + 1 < dists[row][col]:
|
||||
dists[row][col] = current_dist + 1
|
||||
active_fields.append((row, col))
|
||||
|
||||
# for row in dists:
|
||||
# print(row)
|
||||
|
||||
# 34:00
|
||||
return dists[end[0]][end[1]]
|
||||
|
||||
def solve2(lines: list[str]):
|
||||
starts = []
|
||||
all_dists =[]
|
||||
for (row, line) in enumerate(lines):
|
||||
for (col, c) in enumerate(line):
|
||||
if c == 'S' or c == 'a':
|
||||
starts.append((row, col))
|
||||
|
||||
for start in starts:
|
||||
end = (0, 0)
|
||||
rows = len(lines)
|
||||
cols = len(lines[0])
|
||||
heights = []
|
||||
dists = []
|
||||
for (row, line) in enumerate(lines):
|
||||
heights.append([])
|
||||
dists.append([])
|
||||
for (col, c) in enumerate(line):
|
||||
if row == start[0] and col == start[1]:
|
||||
heights[row].append(0)
|
||||
dists[row].append(0)
|
||||
elif c == 'E':
|
||||
end = (row, col)
|
||||
heights[row].append(26)
|
||||
dists[row].append(2**16)
|
||||
else:
|
||||
heights[row].append(ord(lines[row][col]) - ord('a'))
|
||||
dists[row].append(2**16)
|
||||
|
||||
active_fields = [start]
|
||||
while active_fields:
|
||||
row, col = active_fields.pop()
|
||||
current_dist = dists[row][col]
|
||||
current_height = heights[row][col]
|
||||
for row, col in neighbors_4(row, col, rows, cols):
|
||||
pot_height = heights[row][col]
|
||||
if current_height < pot_height - 1:
|
||||
continue
|
||||
if current_dist + 1 < dists[row][col]:
|
||||
dists[row][col] = current_dist + 1
|
||||
active_fields.append((row, col))
|
||||
all_dists.append(dists[end[0]][end[1]])
|
||||
# 39:45
|
||||
return min(all_dists)
|
||||
|
||||
def main():
|
||||
lines = lib.str_to_lines_no_empty(EXAMPLE)
|
||||
print("Example 1:", solve(lines))
|
||||
|
||||
lines = lib.str_to_lines_no_empty(open("d12.txt").read())
|
||||
print("Solution 1:", solve(lines))
|
||||
|
||||
lines = lib.str_to_lines_no_empty(EXAMPLE)
|
||||
print("Example 2:", solve2(lines))
|
||||
|
||||
lines = lib.str_to_lines_no_empty(open("d12.txt").read())
|
||||
print("Solution 2:", solve2(lines))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
115
2022/d13.py
Normal file
115
2022/d13.py
Normal file
@ -0,0 +1,115 @@
|
||||
import lib
|
||||
|
||||
EXAMPLE = """[1,1,3,1,1]
|
||||
[1,1,5,1,1]
|
||||
|
||||
[[1],[2,3,4]]
|
||||
[[1],4]
|
||||
|
||||
[9]
|
||||
[[8,7,6]]
|
||||
|
||||
[[4,4],4,4]
|
||||
[[4,4],4,4,4]
|
||||
|
||||
[7,7,7,7]
|
||||
[7,7,7]
|
||||
|
||||
[]
|
||||
[3]
|
||||
|
||||
[[[]]]
|
||||
[[]]
|
||||
|
||||
[1,[2,[3,[4,[5,6,7]]]],8,9]
|
||||
[1,[2,[3,[4,[5,6,0]]]],8,9]
|
||||
"""
|
||||
|
||||
def right_order(a, b):
|
||||
if not a and not b:
|
||||
return None
|
||||
elif not a:
|
||||
return True
|
||||
elif not b:
|
||||
return False
|
||||
|
||||
l, r = a[0], b[0]
|
||||
if type(l) is int and type(r) is int:
|
||||
if l < r:
|
||||
return True
|
||||
elif l > r:
|
||||
return False
|
||||
else:
|
||||
return right_order(a[1:], b[1:])
|
||||
|
||||
if type(l) is int:
|
||||
l = [l]
|
||||
if type(r) is int:
|
||||
r = [r]
|
||||
|
||||
o = right_order(l, r)
|
||||
if o is not None:
|
||||
return o
|
||||
return right_order(a[1:], b[1:])
|
||||
|
||||
def solve(lines: list[str]):
|
||||
res = 0
|
||||
pairs = [[]]
|
||||
for (i, line) in enumerate(lines):
|
||||
if line.strip() == "":
|
||||
pairs.append([])
|
||||
else:
|
||||
pairs[-1].append(eval(line))
|
||||
for i, p in enumerate(pairs):
|
||||
if not len(p) == 2:
|
||||
continue
|
||||
a, b = p[0], p[1]
|
||||
o = right_order(a, b)
|
||||
if o is True:
|
||||
res += i + 1
|
||||
if o is None:
|
||||
raise Exception("NO DECISION")
|
||||
# 37:00
|
||||
return res
|
||||
|
||||
def solve2(lines: list[str]):
|
||||
res = 0
|
||||
|
||||
packets = list(map(eval, lines))
|
||||
p1 = [[2]]
|
||||
packets.append(p1)
|
||||
p2 = [[6]]
|
||||
packets.append(p2)
|
||||
|
||||
resorted = True
|
||||
while resorted:
|
||||
resorted = False
|
||||
for i in range(len(packets) - 1):
|
||||
if not right_order(packets[i], packets[i + 1]):
|
||||
packets[i], packets[i + 1] = packets[i + 1], packets[i]
|
||||
resorted = True
|
||||
p1i, p2i = 0, 0
|
||||
for (i, p) in enumerate(packets):
|
||||
if p == p1:
|
||||
p1i = i + 1
|
||||
elif p == p2:
|
||||
p2i = i + 1
|
||||
print(p1i, p2i)
|
||||
# 44:00
|
||||
return p1i * p2i
|
||||
|
||||
def main():
|
||||
lines = lib.str_to_lines(EXAMPLE)
|
||||
print("Example 1:", solve(lines))
|
||||
|
||||
lines = lib.str_to_lines(open("d13.txt").read())
|
||||
print("Solution 1:", solve(lines))
|
||||
|
||||
lines = lib.str_to_lines_no_empty(EXAMPLE)
|
||||
print("Example 2:", solve2(lines))
|
||||
|
||||
lines = lib.str_to_lines_no_empty(open("d13.txt").read())
|
||||
print("Solution 2:", solve2(lines))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
104
2022/d14.py
Normal file
104
2022/d14.py
Normal file
@ -0,0 +1,104 @@
|
||||
import lib
|
||||
|
||||
EXAMPLE = """
|
||||
498,4 -> 498,6 -> 496,6
|
||||
503,4 -> 502,4 -> 502,9 -> 494,9
|
||||
"""
|
||||
|
||||
def solve(lines: list[str]):
|
||||
c = set()
|
||||
for (i, line) in enumerate(lines):
|
||||
coords = [list(map(int, c.split(","))) for c in line.split(" -> ")]
|
||||
for i in range(len(coords) - 1):
|
||||
a, b = coords[i:i + 2]
|
||||
a_x, a_y = a
|
||||
b_x, b_y = b
|
||||
if a_x == b_x and a_y < b_y:
|
||||
for y in range(a_y, b_y + 1):
|
||||
c.add((a_x, y))
|
||||
elif a_x == b_x and a_y > b_y:
|
||||
for y in range(b_y, a_y + 1):
|
||||
c.add((a_x, y))
|
||||
elif a_y == b_y and a_x < b_x:
|
||||
for x in range(a_x, b_x + 1):
|
||||
c.add((x, a_y))
|
||||
elif a_y == b_y and a_x > b_x:
|
||||
for x in range(b_x, a_x + 1):
|
||||
c.add((x, a_y))
|
||||
else:
|
||||
raise Exception(f"unexpected {a=} {b=}")
|
||||
|
||||
largest_y = max(c, key=lambda c: c[1])[1]
|
||||
s = (500, 0)
|
||||
s_count = 0
|
||||
while s[1] < largest_y:
|
||||
if not (ns := (s[0], s[1] + 1)) in c:
|
||||
s = ns
|
||||
elif not (ns := (s[0] - 1, s[1] + 1)) in c:
|
||||
s = ns
|
||||
elif not (ns := (s[0] + 1, s[1] + 1)) in c:
|
||||
s = ns
|
||||
else:
|
||||
c.add(s)
|
||||
s = (500, 0)
|
||||
s_count += 1
|
||||
return s_count
|
||||
|
||||
def solve2(lines: list[str]):
|
||||
c = set()
|
||||
for (i, line) in enumerate(lines):
|
||||
coords = [list(map(int, c.split(","))) for c in line.split(" -> ")]
|
||||
for i in range(len(coords) - 1):
|
||||
a, b = coords[i:i + 2]
|
||||
a_x, a_y = a
|
||||
b_x, b_y = b
|
||||
if a_x == b_x and a_y < b_y:
|
||||
for y in range(a_y, b_y + 1):
|
||||
c.add((a_x, y))
|
||||
elif a_x == b_x and a_y > b_y:
|
||||
for y in range(b_y, a_y + 1):
|
||||
c.add((a_x, y))
|
||||
elif a_y == b_y and a_x < b_x:
|
||||
for x in range(a_x, b_x + 1):
|
||||
c.add((x, a_y))
|
||||
elif a_y == b_y and a_x > b_x:
|
||||
for x in range(b_x, a_x + 1):
|
||||
c.add((x, a_y))
|
||||
else:
|
||||
raise Exception(f"unexpected {a=} {b=}")
|
||||
|
||||
largest_y = max(c, key=lambda c: c[1])[1]
|
||||
for x in range(-10000, 10000):
|
||||
c.add((x, largest_y + 2))
|
||||
|
||||
s = (500, 0)
|
||||
s_count = 1
|
||||
while True:
|
||||
if not (ns := (s[0], s[1] + 1)) in c:
|
||||
s = ns
|
||||
elif not (ns := (s[0] - 1, s[1] + 1)) in c:
|
||||
s = ns
|
||||
elif not (ns := (s[0] + 1, s[1] + 1)) in c:
|
||||
s = ns
|
||||
elif s[1] == 0:
|
||||
return s_count
|
||||
else:
|
||||
c.add(s)
|
||||
s_count += 1
|
||||
s = (500, 0)
|
||||
|
||||
def main():
|
||||
lines = lib.str_to_lines_no_empty(EXAMPLE)
|
||||
print("Example 1:", solve(lines))
|
||||
|
||||
lines = lib.str_to_lines_no_empty(open("d14.txt").read())
|
||||
print("Solution 1:", solve(lines))
|
||||
|
||||
lines = lib.str_to_lines_no_empty(EXAMPLE)
|
||||
print("Example 2:", solve2(lines))
|
||||
|
||||
lines = lib.str_to_lines_no_empty(open("d14.txt").read())
|
||||
print("Solution 2:", solve2(lines))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
151
2022/d15.py
Normal file
151
2022/d15.py
Normal file
@ -0,0 +1,151 @@
|
||||
import lib
|
||||
import math
|
||||
|
||||
EXAMPLE = """
|
||||
Sensor at x=2, y=18: closest beacon is at x=-2, y=15
|
||||
Sensor at x=9, y=16: closest beacon is at x=10, y=16
|
||||
Sensor at x=13, y=2: closest beacon is at x=15, y=3
|
||||
Sensor at x=12, y=14: closest beacon is at x=10, y=16
|
||||
Sensor at x=10, y=20: closest beacon is at x=10, y=16
|
||||
Sensor at x=14, y=17: closest beacon is at x=10, y=16
|
||||
Sensor at x=8, y=7: closest beacon is at x=2, y=10
|
||||
Sensor at x=2, y=0: closest beacon is at x=2, y=10
|
||||
Sensor at x=0, y=11: closest beacon is at x=2, y=10
|
||||
Sensor at x=20, y=14: closest beacon is at x=25, y=17
|
||||
Sensor at x=17, y=20: closest beacon is at x=21, y=22
|
||||
Sensor at x=16, y=7: closest beacon is at x=15, y=3
|
||||
Sensor at x=14, y=3: closest beacon is at x=15, y=3
|
||||
Sensor at x=20, y=1: closest beacon is at x=15, y=3
|
||||
"""
|
||||
|
||||
def unify_ranges(ranges):
|
||||
# aaaaaaaaaaa
|
||||
# bbbb
|
||||
#
|
||||
# aaa
|
||||
# bbb
|
||||
#
|
||||
# aaa
|
||||
# bbb
|
||||
ranges = sorted(ranges)
|
||||
while True:
|
||||
for i in range(len(ranges) - 1):
|
||||
a, b = ranges[i], ranges[i + 1]
|
||||
if a == b:
|
||||
del ranges[i]
|
||||
break
|
||||
elif a[0] == b[0]:
|
||||
ranges[i] = (a[0], max(a[1], b[1]))
|
||||
del ranges[i + 1]
|
||||
break
|
||||
elif a[1] == b[1]:
|
||||
ranges[i] = (min(a[0], b[0]), b[1])
|
||||
del ranges[i + 1]
|
||||
break
|
||||
elif a[0] < b[0] and a[1] > b[1]:
|
||||
del ranges[i + 1]
|
||||
break
|
||||
elif a[0] > b[0] and a[1] < b[1]:
|
||||
del ranges[i]
|
||||
break
|
||||
elif a[1] < b[0]:
|
||||
pass
|
||||
elif a[0] <= b[1] and a[1] >= b[0]:
|
||||
ranges[i] = (a[0], b[1])
|
||||
del ranges[i + 1]
|
||||
break
|
||||
else:
|
||||
raise Exception("uhoh", a, b)
|
||||
else:
|
||||
return ranges
|
||||
return ranges
|
||||
|
||||
def mdist(dx, dy):
|
||||
return abs(dx) + abs(dy)
|
||||
|
||||
def xdist(dm, dy):
|
||||
x = dm - abs(dy)
|
||||
if x <= 0:
|
||||
return 0
|
||||
return x
|
||||
|
||||
def solve(lines: list[str], yt):
|
||||
sensors = []
|
||||
bacons = set()
|
||||
for (i, line) in enumerate(lines):
|
||||
digits = lib.str_to_ints(line)
|
||||
sx, sy, bx, by = digits
|
||||
sm = mdist(bx - sx, by - sy)
|
||||
sensors.append([sx, sy, sm])
|
||||
bacons.add((bx, by))
|
||||
|
||||
ranges = []
|
||||
for (sx, sy, sm) in sensors:
|
||||
x_range = xdist(sm, yt - sy)
|
||||
if x_range == 0:
|
||||
continue
|
||||
r = (sx - x_range, sx + x_range)
|
||||
# print(f"{sx=} {sy=} {r=}")
|
||||
ranges.append(r)
|
||||
|
||||
ranges = unify_ranges(ranges)
|
||||
r = 0
|
||||
for (a, b) in ranges:
|
||||
r += b - a + 1
|
||||
for (bx, by) in list(bacons):
|
||||
if by == yt and bx >= a and bx <= b:
|
||||
r -= 1
|
||||
# 140:00 I don't know what a Manhattan distance is.
|
||||
return r
|
||||
|
||||
def solve2(lines: list[str], xymax):
|
||||
sensors = []
|
||||
bacons = set()
|
||||
for (i, line) in enumerate(lines):
|
||||
digits = lib.str_to_ints(line)
|
||||
sx, sy, bx, by = digits
|
||||
sm = mdist(bx - sx, by - sy)
|
||||
sensors.append([sx, sy, sm])
|
||||
bacons.add((bx, by))
|
||||
|
||||
finds = []
|
||||
for yt in range(0, xymax):
|
||||
ranges = []
|
||||
for (sx, sy, sm) in sensors:
|
||||
x_range = xdist(sm, yt - sy)
|
||||
if x_range == 0:
|
||||
continue
|
||||
r = (sx - x_range, sx + x_range)
|
||||
ranges.append(r)
|
||||
ranges = unify_ranges(ranges)
|
||||
|
||||
if ranges[0][0] > 0:
|
||||
raise Exception("Bacon at 0.")
|
||||
elif ranges[-1][-1] < xymax:
|
||||
raise Exception("Bacon at xymax.")
|
||||
|
||||
for i in range(len(ranges) - 1):
|
||||
if ranges[i + 1][0] - ranges[i][1] > 1:
|
||||
finds.append((ranges[i][1] + 1, yt))
|
||||
if len(finds) != 1:
|
||||
raise Exception("TOO MANY FINDS")
|
||||
else:
|
||||
x, y = finds[0]
|
||||
return x * 4000000 + y
|
||||
# 10:00
|
||||
|
||||
def main():
|
||||
lines = lib.str_to_lines_no_empty(EXAMPLE)
|
||||
print("Example 1:", solve(lines, 10))
|
||||
|
||||
lines = lib.str_to_lines_no_empty(open("d15.txt").read())
|
||||
print("Solution 1:", solve(lines, 2000000))
|
||||
|
||||
lines = lib.str_to_lines_no_empty(EXAMPLE)
|
||||
print("Example 2:", solve2(lines, 20))
|
||||
|
||||
lines = lib.str_to_lines_no_empty(open("d15.txt").read())
|
||||
print("Solution 2:", solve2(lines, 4000000))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
100
2022/d16.py
Normal file
100
2022/d16.py
Normal file
@ -0,0 +1,100 @@
|
||||
import lib
|
||||
|
||||
EXAMPLE = """
|
||||
Valve AA has flow rate=0; tunnels lead to valves DD, II, BB
|
||||
Valve BB has flow rate=13; tunnels lead to valves CC, AA
|
||||
Valve CC has flow rate=2; tunnels lead to valves DD, BB
|
||||
Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE
|
||||
Valve EE has flow rate=3; tunnels lead to valves FF, DD
|
||||
Valve FF has flow rate=0; tunnels lead to valves EE, GG
|
||||
Valve GG has flow rate=0; tunnels lead to valves FF, HH
|
||||
Valve HH has flow rate=22; tunnel leads to valve GG
|
||||
Valve II has flow rate=0; tunnels lead to valves AA, JJ
|
||||
Valve JJ has flow rate=21; tunnel leads to valve II
|
||||
"""
|
||||
|
||||
def solve(lines: list[str]):
|
||||
nodes = {}
|
||||
for (i, line) in enumerate(lines):
|
||||
source = line.split(" ")[1]
|
||||
to_valves = list(map(lambda v: v.replace(",", ""), line.split(" ")[9:]))
|
||||
flow_rate = lib.str_to_int(line)
|
||||
nodes[source] = (flow_rate, to_valves)
|
||||
|
||||
|
||||
options = [(0, 0, "AA", ())]
|
||||
visited = set()
|
||||
for _ in range(30):
|
||||
new_options = []
|
||||
for (total, flow, current, valves) in options:
|
||||
valve_flow_rate = nodes[current][0]
|
||||
if not current in valves and valve_flow_rate > 0:
|
||||
o = (total + flow, flow + valve_flow_rate, current, valves + (current, ))
|
||||
new_options.append(o)
|
||||
for new_valve in nodes[current][1]:
|
||||
o = (total + flow, flow, new_valve, valves)
|
||||
new_options.append(o)
|
||||
|
||||
options = sorted(list(set(new_options)))[-100:]
|
||||
return options[-1][0]
|
||||
|
||||
|
||||
def solve2(lines: list[str]):
|
||||
nodes = {}
|
||||
for (i, line) in enumerate(lines):
|
||||
source = line.split(" ")[1]
|
||||
to_valves = list(map(lambda v: v.replace(",", ""), line.split(" ")[9:]))
|
||||
flow_rate = lib.str_to_int(line)
|
||||
nodes[source] = (flow_rate, to_valves)
|
||||
|
||||
options = [(0, 0, ("AA", "AA"), ())]
|
||||
for _ in range(26):
|
||||
new_options = []
|
||||
for (total, flow, (a, b), valves) in options:
|
||||
flow_a = nodes[a][0]
|
||||
flow_b = nodes[b][0]
|
||||
|
||||
# a turns on b moves
|
||||
if not a in valves and flow_a > 0:
|
||||
for new_valve_b in nodes[b][1]:
|
||||
o = (total + flow, flow + flow_a, (a, new_valve_b), valves + (a, ))
|
||||
new_options.append(o)
|
||||
|
||||
# a moves and b turns on
|
||||
if not b in valves and flow_b > 0:
|
||||
for new_valve_a in nodes[a][1]:
|
||||
o = (total + flow, flow + flow_b, (new_valve_a, b), valves + (b, ))
|
||||
new_options.append(o)
|
||||
|
||||
# both turn on
|
||||
if a != b and flow_a > 0 and flow_b > 0 and not a in valves and not b in valves:
|
||||
o = (total + flow, flow + flow_a + flow_b, (a, b), valves + (a, b, ))
|
||||
new_options.append(o)
|
||||
|
||||
# both move
|
||||
for new_valve_a in nodes[a][1]:
|
||||
for new_valve_b in nodes[b][1]:
|
||||
o = (total + flow, flow, (new_valve_a, new_valve_b), valves)
|
||||
new_options.append(o)
|
||||
|
||||
options = sorted(list(set(new_options)))[-1000:]
|
||||
# 52:00
|
||||
return options[-1][0]
|
||||
|
||||
|
||||
def main():
|
||||
lines = lib.str_to_lines_no_empty(EXAMPLE)
|
||||
print("Example 1:", solve(lines))
|
||||
|
||||
lines = lib.str_to_lines_no_empty(open("d16.txt").read())
|
||||
print("Solution 1:", solve(lines))
|
||||
|
||||
lines = lib.str_to_lines_no_empty(EXAMPLE)
|
||||
print("Example 2:", solve2(lines))
|
||||
|
||||
lines = lib.str_to_lines_no_empty(open("d16.txt").read())
|
||||
print("Solution 2:", solve2(lines))
|
||||
assert solve2(lines) == 2591
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
119
2022/d17.py
Normal file
119
2022/d17.py
Normal file
@ -0,0 +1,119 @@
|
||||
from lib import *
|
||||
|
||||
EXAMPLE = """>>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>"""
|
||||
|
||||
ROCKS = [
|
||||
[(0, 0), (0, 1), (0, 2), (0, 3)],
|
||||
[(0, 1), (-1, 0), (-1, 1), (-1, 2), (-2, 1)],
|
||||
[(0, 0), (0, 1), (0, 2), (-1, 2), (-2, 2)],
|
||||
[(0, 0), (-1, 0), (-2, 0), (-3, 0)],
|
||||
[(0, 0), (0, 1), (-1, 0), (-1, 1)],
|
||||
]
|
||||
|
||||
def printfall(coords):
|
||||
row_coords = list(map(lambda c: c[0], coords))
|
||||
col_coords = list(map(lambda c: c[1], coords))
|
||||
min_row, max_row = min(row_coords), max(row_coords)
|
||||
min_col, max_col = min(col_coords), max(col_coords)
|
||||
|
||||
s = ""
|
||||
for r in range(min_row, max_row + 1):
|
||||
for c in range(min_col, max_col + 1):
|
||||
s += "."
|
||||
s += "\n"
|
||||
g = Input(s).grid2()
|
||||
for c in coords:
|
||||
c = (c[0] + -min_row, c[1])
|
||||
g[tuple(c)] = "#"
|
||||
g.print()
|
||||
print()
|
||||
|
||||
def solve(input: Input, second=False):
|
||||
BLOWS = list(input.text.strip())
|
||||
width, blow_index = 7, 0
|
||||
|
||||
heighest = [0 for _ in range(width)]
|
||||
rocks = set([(0, i) for i in range(width)])
|
||||
|
||||
if second:
|
||||
target = 1000000000000
|
||||
nhs = {}
|
||||
else:
|
||||
target = 2022
|
||||
|
||||
i = 0
|
||||
while i < target:
|
||||
rock = ROCKS[i % len(ROCKS)]
|
||||
pos = (min(heighest) - 4, 2)
|
||||
|
||||
if second and i > 0 and all(abs(heighest[i] - heighest[i + 1]) <= 2 for i in range(len(heighest) - 1)):
|
||||
# long winded code to find repeating sequence
|
||||
nh = tuple([h - min(heighest) for h in heighest])
|
||||
if nh in nhs:
|
||||
nhs[nh].append((i, heighest[0]))
|
||||
else:
|
||||
nhs[nh] = [(i, heighest[0])]
|
||||
xs = nhs[nh]
|
||||
if len(xs) > 4 and all(xs[1][0] - xs[0][0] == xs[i + 1][0] - xs[i][0] for i in range(len(xs) - 1)):
|
||||
# we found a repeating sequence and can skip forward
|
||||
di = xs[-1][0] - xs[-2][0]
|
||||
dh = xs[-1][1] - xs[-2][1]
|
||||
repeat = (target - i) // di
|
||||
i += repeat * di
|
||||
heighest = [h + repeat * dh for h in heighest]
|
||||
for c, r in enumerate(heighest):
|
||||
rocks.add((r, c))
|
||||
nhs = {}
|
||||
continue
|
||||
|
||||
falling = True
|
||||
while falling:
|
||||
blow = BLOWS[blow_index % len(BLOWS)]
|
||||
blow_index += 1
|
||||
|
||||
dc = None
|
||||
if blow == ">":
|
||||
dc = 1
|
||||
elif blow == "<":
|
||||
dc = -1
|
||||
|
||||
for (ro, co) in rock:
|
||||
r = pos[0] + ro
|
||||
c = pos[1] + co + dc
|
||||
if c < 0 or c >= width or (r, c) in rocks:
|
||||
break
|
||||
else:
|
||||
pos = (pos[0], pos[1] + dc)
|
||||
|
||||
for (ro, co) in rock:
|
||||
r = pos[0] + ro + 1
|
||||
c = pos[1] + co
|
||||
if (r, c) in rocks:
|
||||
falling = False
|
||||
break
|
||||
else:
|
||||
pos = (pos[0] + 1, pos[1])
|
||||
|
||||
for (ro, co) in rock:
|
||||
r = pos[0] + ro
|
||||
c = pos[1] + co
|
||||
rocks.add((r, c))
|
||||
heighest[c] = min(heighest[c], r)
|
||||
|
||||
i += 1
|
||||
|
||||
return -min(heighest)
|
||||
|
||||
def main():
|
||||
_, day = extract_year_and_date(__file__)
|
||||
DAY_INPUT = f"i{day}.txt"
|
||||
print("Example 1:", solve(Input(EXAMPLE)))
|
||||
s1 = solve(Input(DAY_INPUT))
|
||||
assert s1 == 3102
|
||||
print("Solution 1:", s1)
|
||||
print("Example 2:", solve(Input(EXAMPLE), True))
|
||||
print("Solution 2:", solve(Input(DAY_INPUT), True))
|
||||
assert solve(Input(DAY_INPUT), True) == 1539823008825
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
71
2022/d18.py
Normal file
71
2022/d18.py
Normal file
@ -0,0 +1,71 @@
|
||||
from lib import *
|
||||
|
||||
EXAMPLE = """2,2,2
|
||||
1,2,2
|
||||
3,2,2
|
||||
2,1,2
|
||||
2,3,2
|
||||
2,2,1
|
||||
2,2,3
|
||||
2,2,4
|
||||
2,2,6
|
||||
1,2,5
|
||||
3,2,5
|
||||
2,1,5
|
||||
2,3,5
|
||||
"""
|
||||
|
||||
|
||||
def solve(input: Input, second=False):
|
||||
cubes = set([tuple(map(int, l.split(",")))for l in input.text.splitlines()])
|
||||
res = len(cubes) * 6
|
||||
|
||||
if second:
|
||||
min_x = min([c[0] for c in cubes]) - 1
|
||||
max_x = max([c[0] for c in cubes]) + 1
|
||||
min_y = min([c[1] for c in cubes]) - 1
|
||||
max_y = max([c[1] for c in cubes]) + 1
|
||||
min_z = min([c[2] for c in cubes]) - 1
|
||||
max_z = max([c[2] for c in cubes]) + 1
|
||||
surrounded = set([(x, y, z)
|
||||
for x in range(min_x, max_x + 1)
|
||||
for y in range(min_y, max_y + 1)
|
||||
for z in range(min_z, max_z + 1)])
|
||||
surrounded -= cubes
|
||||
vs = [(min_x, min_y, min_z)]
|
||||
while vs:
|
||||
(x, y, z) = vs.pop()
|
||||
for dx, dy, dz in [(1, 0, 0), (-1, 0, 0), (0, 1, 0), (0, -1, 0), (0, 0, 1), (0, 0, -1)]:
|
||||
t = x + dx, y + dy, z + dz
|
||||
if t in surrounded:
|
||||
surrounded.remove(t)
|
||||
vs.append(t)
|
||||
for x, y, z in list(surrounded):
|
||||
for dx, dy, dz in [(1, 0, 0), (-1, 0, 0), (0, 1, 0), (0, -1, 0), (0, 0, 1), (0, 0, -1)]:
|
||||
nc = x + dx, y + dy, z + dz
|
||||
if nc in cubes:
|
||||
res -= 1
|
||||
|
||||
for x, y, z in list(cubes):
|
||||
for dx, dy, dz in [(1, 0, 0), (-1, 0, 0), (0, 1, 0), (0, -1, 0), (0, 0, 1), (0, 0, -1)]:
|
||||
nc = x + dx, y + dy, z + dz
|
||||
if nc in cubes:
|
||||
res -= 1
|
||||
return res
|
||||
|
||||
def main():
|
||||
DAY_INPUT = "d18.txt"
|
||||
|
||||
print("Example 1:", solve(Input(EXAMPLE)))
|
||||
print("Solution 1:", solve(Input(DAY_INPUT)))
|
||||
# 10:30........
|
||||
|
||||
print("Example 2:", solve(Input(EXAMPLE), True))
|
||||
print("Solution 2:", solve(Input(DAY_INPUT), True))
|
||||
assert solve(Input(DAY_INPUT), True) == 2064
|
||||
# 30:00
|
||||
|
||||
return
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
117
2022/d19.py
Normal file
117
2022/d19.py
Normal file
@ -0,0 +1,117 @@
|
||||
from lib import *
|
||||
|
||||
EXAMPLE = """
|
||||
Blueprint 1:
|
||||
Each ore robot costs 4 ore.
|
||||
Each clay robot costs 2 ore.
|
||||
Each obsidian robot costs 3 ore and 14 clay.
|
||||
Each geode robot costs 2 ore and 7 obsidian.
|
||||
|
||||
Blueprint 2:
|
||||
Each ore robot costs 2 ore.
|
||||
Each clay robot costs 3 ore.
|
||||
Each obsidian robot costs 3 ore and 8 clay.
|
||||
Each geode robot costs 3 ore and 12 obsidian.
|
||||
"""
|
||||
|
||||
def solve(input: Input, second=False):
|
||||
if not second:
|
||||
res = 0
|
||||
else:
|
||||
res = 1
|
||||
bps = []
|
||||
for line in input.text.replace(".", ".\n").replace(":", ":\n").splitlines():
|
||||
if "Blueprint" in line:
|
||||
bps.append([])
|
||||
elif "ore robot" in line:
|
||||
cost = str_to_ints(line)
|
||||
cost += [0, 0]
|
||||
bps[-1].append(cost)
|
||||
elif "clay robot" in line:
|
||||
cost = str_to_ints(line)
|
||||
cost += [0, 0]
|
||||
bps[-1].append(cost)
|
||||
elif "obsidian robot" in line:
|
||||
cost = str_to_ints(line)
|
||||
cost += [0,]
|
||||
bps[-1].append(cost)
|
||||
elif "geode robot" in line:
|
||||
cost = str_to_ints(line)
|
||||
cost.insert(1, 0)
|
||||
bps[-1].append(cost)
|
||||
|
||||
if second:
|
||||
bps = bps[:3]
|
||||
time = 32
|
||||
else:
|
||||
time = 24
|
||||
|
||||
end_states = []
|
||||
for i, bp in enumerate(bps):
|
||||
# ((ore bots, clay bots, obs bots, geo bots), (ore, clay, obs, geo))
|
||||
start = ((1, 0, 0, 0), (0, 0, 0, 0))
|
||||
states = [start]
|
||||
seen = set(states)
|
||||
|
||||
for _ in range(time):
|
||||
new_states = []
|
||||
while states:
|
||||
bots, ress = states.pop()
|
||||
|
||||
add_ress = [0, 0, 0, 0]
|
||||
for boti, count in enumerate(bots):
|
||||
add_ress[boti] += count
|
||||
|
||||
all_built = True
|
||||
for boti, cost in enumerate(bp):
|
||||
if ress[0] >= cost[0] and ress[1] >= cost[1] and ress[2] >= cost[2]:
|
||||
new_ress = list(ress)
|
||||
new_ress[0] -= cost[0]
|
||||
new_ress[1] -= cost[1]
|
||||
new_ress[2] -= cost[2]
|
||||
new_ress = tuple(map(sum, zip(new_ress, add_ress)))
|
||||
new_bots = list(bots)
|
||||
new_bots[boti] += 1
|
||||
new_state = (tuple(new_bots), new_ress)
|
||||
if not new_state in seen:
|
||||
new_states.append(new_state)
|
||||
seen.add(new_state)
|
||||
else:
|
||||
all_built = False
|
||||
|
||||
# XXX: our search space is too large here it is possible to
|
||||
# optimze by not storing reduntant paths (paths where we acrue
|
||||
# more of a resource than we need), but I don't know how to
|
||||
# make it more efficient right now.
|
||||
if not all_built:
|
||||
new_ress = tuple(map(sum, zip(ress, add_ress)))
|
||||
new_state = (bots, new_ress)
|
||||
if not new_state in seen:
|
||||
new_states.append(new_state)
|
||||
seen.add(new_state)
|
||||
|
||||
# prune to keep search space "reasonable"
|
||||
states = sorted(new_states, key=lambda s: list(reversed(s[0])), reverse=True)[:100000]
|
||||
|
||||
if not second:
|
||||
r = max(states, key=lambda s: s[1][3])
|
||||
q = (i + 1) * r[1][3]
|
||||
# print(i + 1, r, q)
|
||||
res += q
|
||||
else:
|
||||
r = max(states, key=lambda r: r[1][3])
|
||||
res *= r[1][3]
|
||||
return res
|
||||
|
||||
def main():
|
||||
DAY_INPUT = "d19.txt"
|
||||
e1 = solve(Input(EXAMPLE))
|
||||
print("Example 1:", e1)
|
||||
assert e1 == 33
|
||||
print("Solution 1:", solve(Input(DAY_INPUT)))
|
||||
print("Example 2:", solve(Input(EXAMPLE), True))
|
||||
print("Solution 2:", solve(Input(DAY_INPUT), True))
|
||||
return
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
98
2022/d2.py
Normal file
98
2022/d2.py
Normal file
@ -0,0 +1,98 @@
|
||||
import re
|
||||
|
||||
EXAMPLE = """
|
||||
A Y
|
||||
B X
|
||||
C Z
|
||||
"""
|
||||
|
||||
def clean(text: str) -> list[str]:
|
||||
return list(filter(lambda l: l.strip() != "", text.splitlines()))
|
||||
# return list(text.splitlines()))
|
||||
|
||||
def solve(lines: list[str]):
|
||||
s = 0
|
||||
for (i, line) in enumerate(lines):
|
||||
a, b = line.split(" ")
|
||||
if b == "X":
|
||||
s += 1
|
||||
if a == "A":
|
||||
s += 3
|
||||
elif a == "B":
|
||||
s += 0
|
||||
elif a == "C":
|
||||
s += 6
|
||||
else:
|
||||
print("invalid")
|
||||
elif b == "Y":
|
||||
s += 2
|
||||
if a == "A":
|
||||
s += 6
|
||||
elif a == "B":
|
||||
s += 3
|
||||
elif a == "C":
|
||||
s += 0
|
||||
else:
|
||||
print("invalid")
|
||||
elif b == "Z":
|
||||
s += 3
|
||||
if a == "A":
|
||||
s += 0
|
||||
elif a == "B":
|
||||
s += 6
|
||||
elif a == "C":
|
||||
s += 3
|
||||
else:
|
||||
print("invalid")
|
||||
return s
|
||||
|
||||
def solve2(lines: list[str]):
|
||||
s = 0
|
||||
for (i, line) in enumerate(lines):
|
||||
a, b = line.split(" ")
|
||||
if a == "A":
|
||||
if b == "X": # lose
|
||||
s += 3
|
||||
elif b == "Y": # draw
|
||||
s += 4
|
||||
elif b == "Z": # win
|
||||
s += 8
|
||||
else:
|
||||
print("invalid")
|
||||
elif a == "B":
|
||||
if b == "X": # lose
|
||||
s += 1
|
||||
elif b == "Y": # draw
|
||||
s += 5
|
||||
elif b == "Z": # win
|
||||
s += 9
|
||||
else:
|
||||
print("invalid")
|
||||
elif a == "C":
|
||||
if b == "X": # lose
|
||||
s += 2
|
||||
elif b == "Y": # draw
|
||||
s += 6
|
||||
elif b == "Z": # win
|
||||
s += 7
|
||||
else:
|
||||
print("invalid")
|
||||
return s
|
||||
|
||||
def main():
|
||||
example = clean(EXAMPLE)
|
||||
print("Example 1:", solve(example))
|
||||
|
||||
data = clean(open("d2.txt").read())
|
||||
print("Solution 1:", solve(data))
|
||||
assert solve(data) == 14069
|
||||
|
||||
example = clean(EXAMPLE)
|
||||
print("Example 2:", solve2(example))
|
||||
|
||||
data = clean(open("d2.txt").read())
|
||||
print("Solution 2:", solve2(data))
|
||||
assert solve2(data) == 12411
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
73
2022/d20.py
Normal file
73
2022/d20.py
Normal file
@ -0,0 +1,73 @@
|
||||
from lib import *
|
||||
|
||||
EXAMPLE = """1
|
||||
2
|
||||
-3
|
||||
3
|
||||
-2
|
||||
0
|
||||
4
|
||||
"""
|
||||
|
||||
|
||||
def move(xs, i, move):
|
||||
move = move % (len(xs) - 1)
|
||||
ni = (i + move + 1) % len(xs)
|
||||
xsi, xs[i] = xs[i], None
|
||||
xs.insert(ni, xsi)
|
||||
xs.remove(None)
|
||||
return xs
|
||||
|
||||
|
||||
def asserts():
|
||||
assert move([1, 2, 3], 0, 0) == [1, 2, 3]
|
||||
assert move([1, 2, 3], 0, 1) == [2, 1, 3]
|
||||
assert move([1, 2, 3], 0, 2) == [1, 2, 3]
|
||||
assert move([1, 2, 3], 0, 3) == [2, 1, 3]
|
||||
assert move([1, 2, 3], 0, 4) == [1, 2, 3]
|
||||
assert move([1, 2, 3], 0, 5) == [2, 1, 3]
|
||||
assert move([1, 2, 3], 0, 2) == [1, 2, 3]
|
||||
assert move([3, 2, 1], 2, 1) == [3, 1, 2]
|
||||
assert move([3, 2, 1], 2, 2) == [1, 3, 2]
|
||||
|
||||
assert move([4, -2, 5, 6, 7, 8, 9,], 1, -2) == [4, 5, 6, 7, 8, -2, 9]
|
||||
assert move([1, 2, -2, -3, 0, 3, 4], 2, -2) == [-2, 1, 2, -3, 0, 3, 4]
|
||||
|
||||
|
||||
def solve(input: Input, second=False):
|
||||
xs = list(map(int, input.lines()))
|
||||
if second:
|
||||
xs = list(map(lambda n: n * 811589153, xs))
|
||||
ys = list(range(len(xs)))
|
||||
oys = ys[:]
|
||||
|
||||
repeat = 1
|
||||
if second:
|
||||
repeat = 10
|
||||
for _ in range(repeat):
|
||||
for o in oys:
|
||||
i = ys.index(o)
|
||||
movev = xs[o]
|
||||
move(ys, i, movev)
|
||||
|
||||
xs = [xs[i] for i in ys]
|
||||
s = 0
|
||||
i0 = xs.index(0)
|
||||
for i in range(1, 4):
|
||||
ni = (i0 + i * 1000) % len(ys)
|
||||
s += xs[ni]
|
||||
return s
|
||||
|
||||
|
||||
def main():
|
||||
DAY_INPUT = "d20.txt"
|
||||
print("Example 1:", solve(Input(EXAMPLE)))
|
||||
print("Solution 1:", solve(Input(DAY_INPUT)))
|
||||
print("Example 2:", solve(Input(EXAMPLE), True))
|
||||
print("Solution 2:", solve(Input(DAY_INPUT), True))
|
||||
assert solve(Input(DAY_INPUT), True) == 6704537992933
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asserts()
|
||||
main()
|
105
2022/d21.py
Normal file
105
2022/d21.py
Normal file
@ -0,0 +1,105 @@
|
||||
from lib import *
|
||||
|
||||
EXAMPLE = """root: pppw + sjmn
|
||||
dbpl: 5
|
||||
cczh: sllz + lgvd
|
||||
zczc: 2
|
||||
ptdq: humn - dvpt
|
||||
dvpt: 3
|
||||
lfqf: 4
|
||||
humn: 5
|
||||
ljgn: 2
|
||||
sjmn: drzm * dbpl
|
||||
sllz: 4
|
||||
pppw: cczh / lfqf
|
||||
lgvd: ljgn * ptdq
|
||||
drzm: hmdt - zczc
|
||||
hmdt: 32
|
||||
"""
|
||||
|
||||
def resolve(monkeys, s):
|
||||
equ = monkeys[s]
|
||||
try:
|
||||
return int(equ)
|
||||
except ValueError:
|
||||
pass
|
||||
l, op, r = equ.split(" ")
|
||||
l = resolve(monkeys, l)
|
||||
r = resolve(monkeys, r)
|
||||
res = eval(f"{l}{op}{r}")
|
||||
monkeys[s] = res
|
||||
return res
|
||||
|
||||
|
||||
def resolve2(monkeys, s):
|
||||
if s == "humn":
|
||||
return tuple()
|
||||
|
||||
equ = monkeys[s]
|
||||
try:
|
||||
return int(equ)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
l, op, r = equ.split(" ")
|
||||
if s == "root":
|
||||
op = "=="
|
||||
|
||||
l = resolve2(monkeys, l)
|
||||
r = resolve2(monkeys, r)
|
||||
|
||||
if isinstance(l, tuple) or isinstance(r, tuple):
|
||||
return (l, op, r)
|
||||
if op == "/":
|
||||
op = "//"
|
||||
res = eval(f"{l}{op}{r}")
|
||||
monkeys[s] = res
|
||||
return res
|
||||
|
||||
|
||||
def simplify(equ, exp):
|
||||
if equ == tuple():
|
||||
return exp
|
||||
l, op, r = equ
|
||||
if op == '/' and isinstance(r, int):
|
||||
return simplify(l, exp * r)
|
||||
elif op == '+' and isinstance(l, int):
|
||||
return simplify(r, exp - l)
|
||||
elif op == '+' and isinstance(r, int):
|
||||
return simplify(l, exp - r)
|
||||
elif op == '-' and isinstance(l, int):
|
||||
return simplify(r, -(exp - l))
|
||||
elif op == '-' and isinstance(r, int):
|
||||
return simplify(l, exp + r)
|
||||
elif op == '*' and isinstance(r, int):
|
||||
return simplify(l, exp // r)
|
||||
elif op == '*' and isinstance(l, int):
|
||||
return simplify(r, exp // l)
|
||||
|
||||
|
||||
def solve(input: Input, second=False):
|
||||
res = 0
|
||||
monkeys = {}
|
||||
for line in input.lines():
|
||||
l, r = line.split(": ")
|
||||
monkeys[l] = r
|
||||
|
||||
if not second:
|
||||
return int(resolve(monkeys, "root"))
|
||||
else:
|
||||
equ = resolve2(monkeys, "root")
|
||||
assert equ[1] == '=='
|
||||
return simplify(equ[0], equ[2])
|
||||
|
||||
|
||||
def main():
|
||||
DAY_INPUT = "d21.txt"
|
||||
print("Example 1:", solve(Input(EXAMPLE)))
|
||||
print("Solution 1:", solve(Input(DAY_INPUT)))
|
||||
print("Example 2:", solve(Input(EXAMPLE), True))
|
||||
print("Solution 2:", solve(Input(DAY_INPUT), True))
|
||||
assert solve(Input(DAY_INPUT), True) == 3243420789721
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
237
2022/d22.py
Normal file
237
2022/d22.py
Normal file
@ -0,0 +1,237 @@
|
||||
from lib import *
|
||||
|
||||
EXAMPLE = """ 0..#
|
||||
.#..
|
||||
#...
|
||||
....
|
||||
1..#2...3..#
|
||||
........#...
|
||||
..#....#....
|
||||
..........#.
|
||||
4..#5...
|
||||
.....#..
|
||||
.#......
|
||||
......#.
|
||||
|
||||
10R5L5R10L4R5L5"""
|
||||
|
||||
|
||||
E = (0, 1)
|
||||
S = (1, 0)
|
||||
W = (0, -1)
|
||||
N = (-1, 0)
|
||||
|
||||
DIRS = [
|
||||
E,
|
||||
S,
|
||||
W,
|
||||
N,
|
||||
]
|
||||
|
||||
# XXX: not hands free - i created this manually probably there is some way to
|
||||
# figure it out from the input, but id don't know how right now.
|
||||
trans_example = {
|
||||
(0, N): (1, S),
|
||||
(0, E): (5, W),
|
||||
(0, S): (3, S),
|
||||
(0, W): (2, S),
|
||||
(1, N): (0, S),
|
||||
(1, E): (2, E),
|
||||
(1, S): (4, N),
|
||||
(1, W): (5, N),
|
||||
(2, N): (0, E),
|
||||
(2, E): (3, E),
|
||||
(2, S): (4, E),
|
||||
(2, W): (1, W),
|
||||
(3, N): (0, N),
|
||||
(3, E): (5, S),
|
||||
(3, S): (4, S),
|
||||
(3, W): (2, W),
|
||||
(4, N): (3, N),
|
||||
(4, E): (5, E),
|
||||
(4, S): (1, N),
|
||||
(4, W): (2, N),
|
||||
(5, N): (3, W),
|
||||
(5, E): (0, W),
|
||||
(5, S): (1, E),
|
||||
(5, W): (4, W),
|
||||
}
|
||||
|
||||
trans_input = {
|
||||
(0, N): (5, E),
|
||||
(0, E): (1, E),
|
||||
(0, S): (2, S),
|
||||
(0, W): (3, E),
|
||||
(1, N): (5, N),
|
||||
(1, E): (4, W),
|
||||
(1, S): (2, W),
|
||||
(1, W): (0, W),
|
||||
(2, N): (0, N),
|
||||
(2, E): (1, N),
|
||||
(2, S): (4, S),
|
||||
(2, W): (3, S),
|
||||
(3, N): (2, E),
|
||||
(3, E): (4, E),
|
||||
(3, S): (5, S),
|
||||
(3, W): (0, E),
|
||||
(4, N): (2, N),
|
||||
(4, E): (1, W),
|
||||
(4, S): (5, W),
|
||||
(4, W): (3, W),
|
||||
(5, N): (3, N),
|
||||
(5, E): (4, N),
|
||||
(5, S): (1, S),
|
||||
(5, W): (0, S),
|
||||
}
|
||||
|
||||
def parse_steps(steps):
|
||||
insts = re.compile(r"(\d+)([LR])").findall(steps)
|
||||
lastn = re.compile(r"\d+").findall(steps)[-1]
|
||||
insts.append((lastn, None))
|
||||
return insts
|
||||
|
||||
|
||||
def solve(input: Input):
|
||||
grid, steps = input.text.split("\n\n")
|
||||
insts = parse_steps(steps)
|
||||
|
||||
grid = list(map(list, grid.splitlines()))
|
||||
rows = len(grid)
|
||||
|
||||
startcol = 0
|
||||
while grid[0][startcol] == ' ':
|
||||
startcol += 1
|
||||
pos = (0, startcol)
|
||||
dir = (0, 1)
|
||||
for n, turn in insts:
|
||||
nrow, ncol = pos
|
||||
for _ in range(int(n)):
|
||||
nrow = (nrow + dir[0]) % rows
|
||||
ncol = (ncol + dir[1]) % len(grid[nrow])
|
||||
while grid[nrow][ncol] == ' ':
|
||||
nrow = (nrow + dir[0]) % rows
|
||||
ncol = (ncol + dir[1]) % len(grid[nrow])
|
||||
if grid[nrow][ncol] == '#':
|
||||
break
|
||||
pos = (nrow, ncol)
|
||||
if turn is not None:
|
||||
dir = DIRS[(DIRS.index(dir) + 1 if turn == 'R' else DIRS.index(dir) - 1) % 4]
|
||||
|
||||
return 1000 * (pos[0] + 1) + 4 * (pos[1] + 1) + DIRS.index(dir)
|
||||
|
||||
|
||||
def solve2(input: Input, square_size=4):
|
||||
squares = []
|
||||
grid, steps = input.text.split("\n\n")
|
||||
insts = parse_steps(steps)
|
||||
grid_rows = grid.splitlines()
|
||||
for r in range(0, len(grid_rows), square_size):
|
||||
for c in range(0, len(grid_rows[r]), square_size):
|
||||
square = []
|
||||
for sr in range(r, r + square_size):
|
||||
square.append(grid_rows[sr][c:c+square_size])
|
||||
if square[0][0] != ' ':
|
||||
squares.append(square)
|
||||
|
||||
def flip(n):
|
||||
return square_size - 1 - n
|
||||
|
||||
def teleport(dir, sqi, row, col):
|
||||
if square_size == 4:
|
||||
nsqi, ndir = trans_example[(sqi, dir)]
|
||||
elif square_size == 50:
|
||||
nsqi, ndir = trans_input[(sqi, dir)]
|
||||
else:
|
||||
assert False
|
||||
nrow, ncol = None, None
|
||||
|
||||
if ndir == N:
|
||||
nrow = square_size - 1
|
||||
elif ndir == S:
|
||||
nrow = 0
|
||||
elif ndir == E:
|
||||
ncol = 0
|
||||
elif ndir == W:
|
||||
ncol = square_size - 1
|
||||
|
||||
if dir == N:
|
||||
if ndir == N:
|
||||
ncol = col
|
||||
elif ndir == S:
|
||||
ncol = flip(col)
|
||||
elif ndir == E:
|
||||
nrow = col
|
||||
elif ndir == W:
|
||||
nrow = square_size - 1 - col
|
||||
elif dir == S:
|
||||
if ndir == N:
|
||||
ncol = flip(col)
|
||||
elif ndir == S:
|
||||
ncol = col
|
||||
elif ndir == E:
|
||||
nrow = square_size - 1 - col
|
||||
elif ndir == W:
|
||||
nrow = col
|
||||
elif dir == E:
|
||||
if ndir == N:
|
||||
ncol = row
|
||||
elif ndir == S:
|
||||
ncol = flip(row)
|
||||
elif ndir == E:
|
||||
nrow = row
|
||||
elif ndir == W:
|
||||
nrow = square_size - 1 - row
|
||||
elif dir == W:
|
||||
if ndir == N:
|
||||
ncol = flip(row)
|
||||
elif ndir == S:
|
||||
ncol = row
|
||||
elif ndir == E:
|
||||
nrow = flip(row)
|
||||
elif ndir == W:
|
||||
nrow = row
|
||||
|
||||
assert nrow is not None
|
||||
assert ncol is not None
|
||||
return ndir, nsqi, nrow, ncol
|
||||
|
||||
# for square in squares:
|
||||
# print("\n".join(square), "\n")
|
||||
|
||||
dir, sqi, row, col = E, 0, 0, 0
|
||||
for n, turn in insts:
|
||||
# print(f"{sqi=} {row=} {col=} {dir=}")
|
||||
for _ in range(int(n)):
|
||||
nrow = row + dir[0]
|
||||
ncol = col + dir[1]
|
||||
if nrow < 0 or nrow >= square_size or ncol < 0 or ncol >= square_size:
|
||||
ndir, nsqi, nrow, ncol = teleport(dir, sqi, nrow, ncol)
|
||||
else:
|
||||
ndir, nsqi = dir, sqi
|
||||
if squares[nsqi][nrow][ncol] != '#':
|
||||
dir, sqi, row, col = ndir, nsqi, nrow, ncol
|
||||
if turn is not None:
|
||||
dir = DIRS[(DIRS.index(dir) + 1 if turn == 'R' else DIRS.index(dir) - 1) % 4]
|
||||
print(f"{sqi=} {row=} {col=} {dir=}")
|
||||
|
||||
if square_size == 4:
|
||||
# sqi=2 row=0 col=2 dir=(-1, 0)
|
||||
return 1000 * (4 + 0 + 1) + 4 * (4 + 2 + 1) + DIRS.index((-1, 0))
|
||||
elif square_size == 50:
|
||||
# sqi=1 row=11 col=14 dir=(0, -1)
|
||||
return 1000 * (0 + 11 + 1) + 4 * (100 + 14 + 1) + DIRS.index((0, -1))
|
||||
else:
|
||||
assert False
|
||||
|
||||
def main():
|
||||
DAY_INPUT = "d22.txt"
|
||||
print("Example 1:", solve(Input(EXAMPLE)))
|
||||
print("Solution 1:", solve(Input(DAY_INPUT)))
|
||||
assert solve(Input(DAY_INPUT)) == 149250
|
||||
|
||||
print("Example 2:", solve2(Input(EXAMPLE)))
|
||||
print("Solution 2:", solve2(Input("d22.txt"), 50))
|
||||
return
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
120
2022/d23.py
Normal file
120
2022/d23.py
Normal file
@ -0,0 +1,120 @@
|
||||
from lib import *
|
||||
|
||||
EXAMPLE = """....#..
|
||||
..###.#
|
||||
#...#.#
|
||||
.#...##
|
||||
#.###..
|
||||
##.#.##
|
||||
.#..#..
|
||||
"""
|
||||
|
||||
# EXAMPLE = """.....
|
||||
# ..##.
|
||||
# ..#..
|
||||
# .....
|
||||
# ..##.
|
||||
# .....
|
||||
# """
|
||||
|
||||
N = (-1, 0)
|
||||
NE = (-1, 1)
|
||||
E = (0, 1)
|
||||
SE = (1, 1)
|
||||
S = (1, 0)
|
||||
SW = (1, -1)
|
||||
W = (0, -1)
|
||||
NW = (-1, -1)
|
||||
|
||||
adj8 = [
|
||||
N,
|
||||
NE,
|
||||
E,
|
||||
SE,
|
||||
S,
|
||||
SW,
|
||||
W,
|
||||
NW,
|
||||
]
|
||||
|
||||
def print_field(elves):
|
||||
rmin, rmax = min(map(fst, elves)), max(map(fst, elves))
|
||||
cmin, cmax = min(map(snd, elves)), max(map(snd, elves))
|
||||
count = 0
|
||||
for row in range(rmin, rmax + 1):
|
||||
rs = ""
|
||||
for col in range(cmin, cmax + 1):
|
||||
if (row, col) in elves:
|
||||
rs += "#"
|
||||
else:
|
||||
rs += "."
|
||||
count += 1
|
||||
print(rs)
|
||||
print()
|
||||
return count
|
||||
|
||||
def solve(input: Input, second=False):
|
||||
dirs_to_check = [
|
||||
(N, NE, NW),
|
||||
(S, SE, SW),
|
||||
(W, NW, SW),
|
||||
(E, NE, SE),
|
||||
]
|
||||
|
||||
round = 0
|
||||
elves = input.grid2().find('#')
|
||||
while True:
|
||||
# print_field(elves)
|
||||
nes = set()
|
||||
proposed_fields = {}
|
||||
for e in list(elves):
|
||||
for o in adj8:
|
||||
adj = (e[0] + o[0], e[1] + o[1])
|
||||
if adj in elves:
|
||||
break
|
||||
else:
|
||||
nes.add(e)
|
||||
continue
|
||||
|
||||
proposed_field = None
|
||||
for dirs in dirs_to_check:
|
||||
for o in dirs:
|
||||
adj = (e[0] + o[0], e[1] + o[1])
|
||||
if adj in elves:
|
||||
break
|
||||
else:
|
||||
o = dirs[0]
|
||||
proposed_field = (e[0] + o[0], e[1] + o[1])
|
||||
break
|
||||
|
||||
if proposed_field is None:
|
||||
nes.add(e)
|
||||
elif proposed_field in proposed_fields:
|
||||
proposed_fields[proposed_field].append(e)
|
||||
else:
|
||||
proposed_fields[proposed_field] = [e]
|
||||
|
||||
for ne, olves in proposed_fields.items():
|
||||
if len(olves) == 1:
|
||||
nes.add(ne)
|
||||
else:
|
||||
for e in olves:
|
||||
nes.add(e)
|
||||
|
||||
dirs_to_check = dirs_to_check[1:] + dirs_to_check[:1]
|
||||
round += 1
|
||||
if second and elves == nes:
|
||||
return round
|
||||
elif not second and round == 10:
|
||||
return print_field(nes)
|
||||
elves = nes
|
||||
|
||||
def main():
|
||||
DAY_INPUT = "d23.txt"
|
||||
print("Example 1:", solve(Input(EXAMPLE)))
|
||||
print("Solution 1:", solve(Input(DAY_INPUT)))
|
||||
print("Example 2:", solve(Input(EXAMPLE), True))
|
||||
print("Solution 2:", solve(Input(DAY_INPUT), True))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
93
2022/d24.py
Normal file
93
2022/d24.py
Normal file
@ -0,0 +1,93 @@
|
||||
from lib import *
|
||||
|
||||
EXAMPLE = """#.#####
|
||||
#.....#
|
||||
#>....#
|
||||
#.....#
|
||||
#...v.#
|
||||
#.....#
|
||||
#####.#
|
||||
"""
|
||||
|
||||
EXAMPLE = """#.######
|
||||
#>>.<^<#
|
||||
#.<..<<#
|
||||
#>v.><>#
|
||||
#<^v^^>#
|
||||
######.#
|
||||
"""
|
||||
|
||||
B2DIR = {
|
||||
">": (0, 1),
|
||||
"v": (1, 0),
|
||||
"<": (0, -1),
|
||||
"^": (-1, 0),
|
||||
}
|
||||
|
||||
ADJ5 = [
|
||||
(-1, 0),
|
||||
(0, 1),
|
||||
(1, 0),
|
||||
(0, -1),
|
||||
(0, 0),
|
||||
]
|
||||
|
||||
def solve(input: Input, second=False):
|
||||
g = input.grid2()
|
||||
start = (0, g.rows()[0].index('.'))
|
||||
poss = set([(start, 0)])
|
||||
end = (g.n_rows - 1, g.rows()[-1].index('.'))
|
||||
bzs = []
|
||||
for d in B2DIR.keys():
|
||||
for b in g.find(d):
|
||||
bzs.append((b, B2DIR[d]))
|
||||
|
||||
for time in range(10**9):
|
||||
nbzs = []
|
||||
bzsset = set()
|
||||
for pos, dir in bzs:
|
||||
row, col = add2(pos, dir)
|
||||
if row == 0:
|
||||
row = g.n_rows - 2
|
||||
elif row == g.n_rows - 1:
|
||||
row = 1
|
||||
if col == 0:
|
||||
col = g.n_cols - 2
|
||||
elif col == g.n_cols - 1:
|
||||
col = 1
|
||||
nbzs.append(((row, col), dir))
|
||||
bzsset.add((row, col))
|
||||
bzs = nbzs
|
||||
|
||||
nposs = set()
|
||||
while poss:
|
||||
pos, round = poss.pop()
|
||||
for adj in ADJ5:
|
||||
npos = add2(pos, adj)
|
||||
if npos[0] < 0 or npos[0] >= g.n_rows or npos[1] < 0 or npos[1] >= g.n_cols:
|
||||
continue
|
||||
if not second:
|
||||
if npos not in bzsset and g[npos] != '#':
|
||||
nposs.add((npos, round))
|
||||
if npos == end:
|
||||
return time + 1
|
||||
else:
|
||||
if npos == end and round == 0:
|
||||
nposs.add((npos, round + 1))
|
||||
elif npos == end and round == 2:
|
||||
return time + 1
|
||||
elif npos == start and round == 1:
|
||||
nposs.add((npos, round + 1))
|
||||
elif npos not in bzsset and g[npos] != '#':
|
||||
nposs.add((npos, round))
|
||||
poss = nposs
|
||||
|
||||
def main():
|
||||
DAY_INPUT = "d24.txt"
|
||||
print("Example 1:", solve(Input(EXAMPLE)))
|
||||
print("Solution 1:", solve(Input(DAY_INPUT)))
|
||||
print("Example 2:", solve(Input(EXAMPLE), True))
|
||||
print("Solution 2:", solve(Input(DAY_INPUT), True))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
82
2022/d25.py
Normal file
82
2022/d25.py
Normal file
@ -0,0 +1,82 @@
|
||||
from lib import *
|
||||
|
||||
EXAMPLE = """1=-0-2
|
||||
12111
|
||||
2=0=
|
||||
21
|
||||
2=01
|
||||
111
|
||||
20012
|
||||
112
|
||||
1=-1=
|
||||
1-12
|
||||
12
|
||||
1=
|
||||
122
|
||||
"""
|
||||
|
||||
def snafu_to_dec(n: str) -> int:
|
||||
r = 0
|
||||
for i, c in enumerate(reversed(n)):
|
||||
c = "=-012".index(c) - 2
|
||||
r += c * 5**i
|
||||
return r
|
||||
|
||||
def dec_to_snafu(n: int) -> str:
|
||||
r = ""
|
||||
while n != 0:
|
||||
rem = n % 5
|
||||
n //= 5
|
||||
if rem <= 2:
|
||||
r = str(rem) + r
|
||||
else:
|
||||
r = " =-"[rem] + r
|
||||
n += 1
|
||||
return r
|
||||
|
||||
def dec_to_snafu_cs(n: int) -> str:
|
||||
import cpmpy as cp
|
||||
import numpy as np
|
||||
size = 20
|
||||
xs = cp.intvar(-2, 2, shape=size, name="xs")
|
||||
ns = np.array([5**i for i in range(size)])
|
||||
m = cp.Model(cp.sum(ns * xs) == n)
|
||||
m.solve()
|
||||
|
||||
value = xs.value()
|
||||
assert value is not None
|
||||
# print(value)
|
||||
|
||||
r = ""
|
||||
for v in value:
|
||||
if v >= 0:
|
||||
r += str(v)
|
||||
elif v == -1:
|
||||
r += "-"
|
||||
elif v == -2:
|
||||
r += "="
|
||||
else:
|
||||
assert False
|
||||
r = "".join(reversed(r))
|
||||
r = r.lstrip("0")
|
||||
return r
|
||||
|
||||
def solve(input: Input):
|
||||
res = 0
|
||||
for s in input.lines():
|
||||
d = snafu_to_dec(s)
|
||||
res += d
|
||||
try:
|
||||
assert dec_to_snafu_cs(res) == dec_to_snafu(res)
|
||||
except ModuleNotFoundError:
|
||||
print("Install 'cpmpy' to solve with constraint solver.")
|
||||
return dec_to_snafu(res)
|
||||
|
||||
def main():
|
||||
DAY_INPUT = "d25.txt"
|
||||
print("Example 1:", solve(Input(EXAMPLE)))
|
||||
print("Solution 1:", solve(Input(DAY_INPUT)))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
65
2022/d3.py
Normal file
65
2022/d3.py
Normal file
@ -0,0 +1,65 @@
|
||||
from string import ascii_lowercase, ascii_uppercase
|
||||
|
||||
EXAMPLE = """
|
||||
vJrwpWtwJgWrhcsFMMfFFhFp
|
||||
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
|
||||
PmmdzqPrVvPwwTWBwg
|
||||
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
|
||||
ttgJtRGJQctTZtZT
|
||||
CrZsJsPPZsGzwwsLwLmpwMDw
|
||||
"""
|
||||
|
||||
|
||||
def let_to_score(cin):
|
||||
d = {}
|
||||
for i, c in enumerate(ascii_lowercase):
|
||||
d[c] = i + 1
|
||||
for i, c in enumerate(ascii_uppercase):
|
||||
d[c] = i + 27
|
||||
return d[cin]
|
||||
|
||||
def clean(text: str) -> list[str]:
|
||||
return list(filter(lambda l: l.strip() != "", text.splitlines()))
|
||||
|
||||
def solve(lines: list[str]):
|
||||
s = 0
|
||||
for (i, line) in enumerate(lines):
|
||||
half = len(line) // 2
|
||||
a, b = line[:half], line[half:]
|
||||
a = set(a)
|
||||
b = set(b)
|
||||
z = a.intersection(b)
|
||||
l = list(z)[0]
|
||||
score = let_to_score(l)
|
||||
s += score
|
||||
# 8:42
|
||||
return s
|
||||
|
||||
def get_score(l):
|
||||
s = 0
|
||||
s = set(l[0]).intersection(set(l[1])).intersection(set(l[2]))
|
||||
s = list(s)[0]
|
||||
return let_to_score(s)
|
||||
|
||||
def solve2(lines: list[str]):
|
||||
s = 0
|
||||
for i in range(0, len(lines), 3):
|
||||
s += get_score(lines[i:i+3])
|
||||
return s
|
||||
|
||||
def main():
|
||||
example = clean(EXAMPLE)
|
||||
print("Example 1:", solve(example))
|
||||
|
||||
data = clean(open("d3.txt").read())
|
||||
print("Solution 1:", solve(data))
|
||||
|
||||
example = clean(EXAMPLE)
|
||||
print("Example 2:", solve2(example))
|
||||
|
||||
data = clean(open("d3.txt").read())
|
||||
print("Solution 2:", solve2(data))
|
||||
# 13:08
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
64
2022/d4.py
Normal file
64
2022/d4.py
Normal file
@ -0,0 +1,64 @@
|
||||
import re
|
||||
from string import ascii_lowercase, ascii_uppercase
|
||||
|
||||
EXAMPLE = """
|
||||
2-4,6-8
|
||||
2-3,4-5
|
||||
5-7,7-9
|
||||
2-8,3-7
|
||||
6-6,4-6
|
||||
2-6,4-8
|
||||
"""
|
||||
|
||||
def clean(text: str) -> list[str]:
|
||||
return list(filter(lambda l: l.strip() != "", text.splitlines()))
|
||||
|
||||
def solve(lines: list[str]):
|
||||
s = 0
|
||||
for (i, line) in enumerate(lines):
|
||||
s1, s2 = line.split(',')
|
||||
a, b = s1.split('-')
|
||||
c, d = s2.split('-')
|
||||
a = int(a)
|
||||
b = int(b)
|
||||
c = int(c)
|
||||
d = int(d)
|
||||
a = set(list(range(a, b + 1)))
|
||||
b = set(list(range(c, d + 1)))
|
||||
if a <= b or b <= a:
|
||||
s += 1
|
||||
return s
|
||||
|
||||
def solve2(lines: list[str]):
|
||||
s = 0
|
||||
for (i, line) in enumerate(lines):
|
||||
s1, s2 = line.split(',')
|
||||
a, b = s1.split('-')
|
||||
c, d = s2.split('-')
|
||||
a = int(a)
|
||||
b = int(b)
|
||||
c = int(c)
|
||||
d = int(d)
|
||||
a = set(list(range(a, b + 1)))
|
||||
b = set(list(range(c, d + 1)))
|
||||
c = a.intersection(b)
|
||||
if c:
|
||||
s += 1
|
||||
# 7:08
|
||||
return s
|
||||
|
||||
def main():
|
||||
example = clean(EXAMPLE)
|
||||
print("Example 1:", solve(example))
|
||||
|
||||
data = clean(open("d4.txt").read())
|
||||
print("Solution 1:", solve(data))
|
||||
|
||||
example = clean(EXAMPLE)
|
||||
print("Example 2:", solve2(example))
|
||||
|
||||
data = clean(open("d4.txt").read())
|
||||
print("Solution 2:", solve2(data))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
97
2022/d5.py
Normal file
97
2022/d5.py
Normal file
@ -0,0 +1,97 @@
|
||||
import re
|
||||
from string import ascii_lowercase, ascii_uppercase
|
||||
|
||||
EXAMPLE = """
|
||||
[D]
|
||||
[N] [C]
|
||||
[Z] [M] [P]
|
||||
1 2 3
|
||||
1 5 9
|
||||
|
||||
move 1 from 2 to 1
|
||||
move 3 from 1 to 3
|
||||
move 2 from 2 to 1
|
||||
move 1 from 1 to 2
|
||||
"""
|
||||
|
||||
def clean(text: str) -> list[str]:
|
||||
return list(filter(lambda l: l.strip() != "", text.splitlines()))
|
||||
|
||||
def solve(lines: list[str]):
|
||||
s = 0
|
||||
stacks = [[] for _ in range(10)]
|
||||
for (_, line) in enumerate(lines):
|
||||
if line.startswith("move"):
|
||||
continue
|
||||
for (j, c) in enumerate(line):
|
||||
if c in ascii_uppercase:
|
||||
i = (j - 1) // 4
|
||||
stacks[i].append(c)
|
||||
for stack in stacks:
|
||||
stack.reverse()
|
||||
|
||||
r = re.compile(r"move (\d+) from (\d+) to (\d+)")
|
||||
for line in lines:
|
||||
if not line.startswith("move"):
|
||||
continue
|
||||
if (m := r.match(line)):
|
||||
amount, fr, to = m.groups()
|
||||
amount = int(amount)
|
||||
fr = int(fr) - 1
|
||||
to = int(to) - 1
|
||||
stacks[to] += reversed(stacks[fr][-amount:])
|
||||
stacks[fr] = stacks[fr][:-amount]
|
||||
m = ""
|
||||
for s in stacks:
|
||||
if s:
|
||||
m += s[-1]
|
||||
# 10:34
|
||||
return m
|
||||
|
||||
def solve2(lines: list[str]):
|
||||
s = 0
|
||||
stacks = [[] for _ in range(10)]
|
||||
for (_, line) in enumerate(lines):
|
||||
if line.startswith("move"):
|
||||
continue
|
||||
for (j, c) in enumerate(line):
|
||||
if c in ascii_uppercase:
|
||||
i = (j - 1) // 4
|
||||
stacks[i].append(c)
|
||||
for stack in stacks:
|
||||
stack.reverse()
|
||||
|
||||
r = re.compile(r"move (\d+) from (\d+) to (\d+)")
|
||||
for line in lines:
|
||||
if not line.startswith("move"):
|
||||
continue
|
||||
if (m := r.match(line)):
|
||||
amount, fr, to = m.groups()
|
||||
amount = int(amount)
|
||||
fr = int(fr) - 1
|
||||
to = int(to) - 1
|
||||
stacks[to] += stacks[fr][-amount:]
|
||||
stacks[fr] = stacks[fr][:-amount]
|
||||
m = ""
|
||||
for s in stacks:
|
||||
if s:
|
||||
m += s[-1]
|
||||
# 11:56
|
||||
return m
|
||||
|
||||
|
||||
def main():
|
||||
example = clean(EXAMPLE)
|
||||
print("Example 1:", solve(example))
|
||||
|
||||
data = clean(open("d5.txt").read())
|
||||
print("Solution 1:", solve(data))
|
||||
|
||||
example = clean(EXAMPLE)
|
||||
print("Example 2:", solve2(example))
|
||||
|
||||
data = clean(open("d5.txt").read())
|
||||
print("Solution 2:", solve2(data))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
41
2022/d6.py
Normal file
41
2022/d6.py
Normal file
@ -0,0 +1,41 @@
|
||||
import re
|
||||
from string import ascii_lowercase, ascii_uppercase
|
||||
|
||||
EXAMPLE = """
|
||||
mjqjpqmgbljsphdztnvjfqwrcgsmlb
|
||||
"""
|
||||
|
||||
def clean(text: str) -> list[str]:
|
||||
return list(filter(lambda l: l.strip() != "", text.splitlines()))
|
||||
|
||||
def solve(lines: list[str]):
|
||||
line = lines[0]
|
||||
for i in range(len(lines[0])):
|
||||
l = line[i:i + 4]
|
||||
if len(set(l)) == len(l):
|
||||
return i + 4
|
||||
# 2:55
|
||||
|
||||
def solve2(lines: list[str]):
|
||||
line = lines[0]
|
||||
for i in range(len(lines[0])):
|
||||
l = line[i:i + 14]
|
||||
if len(set(l)) == len(l):
|
||||
return i + 14
|
||||
# 3:50
|
||||
|
||||
def main():
|
||||
example = clean(EXAMPLE)
|
||||
print("Example 1:", solve(example))
|
||||
|
||||
data = clean(open("d6.txt").read())
|
||||
print("Solution 1:", solve(data))
|
||||
|
||||
example = clean(EXAMPLE)
|
||||
print("Example 2:", solve2(example))
|
||||
|
||||
data = clean(open("d6.txt").read())
|
||||
print("Solution 2:", solve2(data))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
117
2022/d7.py
Normal file
117
2022/d7.py
Normal file
@ -0,0 +1,117 @@
|
||||
import re
|
||||
from string import ascii_lowercase, ascii_uppercase, digits
|
||||
|
||||
EXAMPLE = """
|
||||
$ cd /
|
||||
$ ls
|
||||
dir a
|
||||
14848514 b.txt
|
||||
8504156 c.dat
|
||||
dir d
|
||||
$ cd a
|
||||
$ ls
|
||||
dir e
|
||||
29116 f
|
||||
2557 g
|
||||
62596 h.lst
|
||||
$ cd e
|
||||
$ ls
|
||||
584 i
|
||||
$ cd ..
|
||||
$ cd ..
|
||||
$ cd d
|
||||
$ ls
|
||||
4060174 j
|
||||
8033020 d.log
|
||||
5626152 d.ext
|
||||
7214296 k
|
||||
"""
|
||||
|
||||
def clean(text: str) -> list[str]:
|
||||
return list(filter(lambda l: l.strip() != "", text.splitlines()))
|
||||
|
||||
def solve(lines: list[str]):
|
||||
sizes = {}
|
||||
res = 0
|
||||
|
||||
current_dir = ()
|
||||
for line in lines:
|
||||
if line.startswith("$ cd"):
|
||||
c = line.replace("$ cd ", "").strip()
|
||||
if c == "..":
|
||||
current_dir = tuple(list(current_dir)[:-1])
|
||||
else:
|
||||
current_dir = tuple(list(current_dir) + [c])
|
||||
elif line[0] in digits:
|
||||
size, _ = line.split()
|
||||
size = int(size)
|
||||
try:
|
||||
sizes[current_dir] += size
|
||||
except KeyError:
|
||||
sizes[current_dir] = size
|
||||
|
||||
for i in range(1, len(current_dir)):
|
||||
outer_dir = tuple(list(current_dir)[:-i])
|
||||
try:
|
||||
sizes[outer_dir] += size
|
||||
except KeyError:
|
||||
sizes[outer_dir] = size
|
||||
|
||||
for _, size in sizes.items():
|
||||
if size <= 100000:
|
||||
res += size
|
||||
# 23:50
|
||||
return res
|
||||
|
||||
def solve2(lines: list[str]):
|
||||
sizes = {}
|
||||
res = 0
|
||||
|
||||
current_dir = ()
|
||||
for line in lines:
|
||||
if line.startswith("$ cd"):
|
||||
c = line.replace("$ cd ", "").strip()
|
||||
if c == "..":
|
||||
current_dir = tuple(list(current_dir)[:-1])
|
||||
else:
|
||||
current_dir = tuple(list(current_dir) + [c])
|
||||
elif line[0] in digits:
|
||||
size, _ = line.split()
|
||||
size = int(size)
|
||||
try:
|
||||
sizes[current_dir] += size
|
||||
except KeyError:
|
||||
sizes[current_dir] = size
|
||||
|
||||
for i in range(1, len(current_dir)):
|
||||
outer_dir = tuple(list(current_dir)[:-i])
|
||||
try:
|
||||
sizes[outer_dir] += size
|
||||
except KeyError:
|
||||
sizes[outer_dir] = size
|
||||
total_space = 70000000
|
||||
unused_space = 30000000
|
||||
used_space = sizes[("/",)]
|
||||
|
||||
res = 2**32
|
||||
for _, size in sizes.items():
|
||||
if total_space - used_space + size >= unused_space and size < res:
|
||||
res = size
|
||||
# 27:55
|
||||
return res
|
||||
|
||||
def main():
|
||||
example = clean(EXAMPLE)
|
||||
print("Example 1:", solve(example))
|
||||
|
||||
data = clean(open("d7.txt").read())
|
||||
print("Solution 1:", solve(data))
|
||||
|
||||
example = clean(EXAMPLE)
|
||||
print("Example 2:", solve2(example))
|
||||
|
||||
data = clean(open("d7.txt").read())
|
||||
print("Solution 2:", solve2(data))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
132
2022/d8.py
Normal file
132
2022/d8.py
Normal file
@ -0,0 +1,132 @@
|
||||
import re
|
||||
from string import ascii_lowercase, ascii_uppercase
|
||||
|
||||
EXAMPLE = """
|
||||
30373
|
||||
25512
|
||||
65332
|
||||
33549
|
||||
35390
|
||||
"""
|
||||
|
||||
def clean(text: str) -> list[str]:
|
||||
return list(filter(lambda l: l.strip() != "", text.splitlines()))
|
||||
|
||||
|
||||
def is_visible(trees, y_tree, x_tree):
|
||||
y_max = len(trees)
|
||||
x_max = len(trees[0])
|
||||
tree_height = trees[y_tree][x_tree]
|
||||
|
||||
for x in range(0, x_tree):
|
||||
if trees[y_tree][x] >= tree_height:
|
||||
break
|
||||
else:
|
||||
return True
|
||||
|
||||
for x in range(x_tree + 1, x_max):
|
||||
if trees[y_tree][x] >= tree_height:
|
||||
break
|
||||
else:
|
||||
return True
|
||||
|
||||
for y in range(0, y_tree):
|
||||
if trees[y][x_tree] >= tree_height:
|
||||
break
|
||||
else:
|
||||
return True
|
||||
|
||||
for y in range(y_tree + 1, y_max):
|
||||
if trees[y][x_tree] >= tree_height:
|
||||
break
|
||||
else:
|
||||
return True
|
||||
return False
|
||||
|
||||
def solve(lines: list[str]):
|
||||
res = 0
|
||||
trees = []
|
||||
for i in range(len(lines)):
|
||||
line = lines[i]
|
||||
trees.append(list(map(int, line)))
|
||||
|
||||
for y in range(len(trees)):
|
||||
for x in range(len(trees)):
|
||||
if is_visible(trees, y, x):
|
||||
res += 1
|
||||
else:
|
||||
pass
|
||||
return res
|
||||
|
||||
|
||||
def scenic_score(trees, y_tree, x_tree):
|
||||
y_max = len(trees)
|
||||
x_max = len(trees[0])
|
||||
|
||||
if x_tree == 0 or y_tree == 0 or x_tree == x_max - 1 or y_tree == y_max - 1:
|
||||
return 0
|
||||
|
||||
tree_height = trees[y_tree][x_tree]
|
||||
left, right, up, down = 0, 0, 0, 0
|
||||
|
||||
for x in range(x_tree - 1, -1, -1):
|
||||
if trees[y_tree][x] < tree_height:
|
||||
left += 1
|
||||
else:
|
||||
left += 1
|
||||
break
|
||||
|
||||
for x in range(x_tree + 1, x_max):
|
||||
if trees[y_tree][x] < tree_height:
|
||||
right += 1
|
||||
else:
|
||||
right += 1
|
||||
break
|
||||
|
||||
for y in range(y_tree - 1, -1, -1):
|
||||
if trees[y][x_tree] < tree_height:
|
||||
up += 1
|
||||
else:
|
||||
up += 1
|
||||
break
|
||||
|
||||
for y in range(y_tree + 1, y_max):
|
||||
if trees[y][x_tree] < tree_height:
|
||||
down += 1
|
||||
else:
|
||||
down += 1
|
||||
break
|
||||
|
||||
score = up * down * left * right
|
||||
# print(f"{y_tree=} {x_tree=} {left=} {right=} {up=} {down=} {score=}")
|
||||
return score
|
||||
|
||||
def solve2(lines: list[str]):
|
||||
trees = []
|
||||
for i in range(len(lines)):
|
||||
line = lines[i]
|
||||
trees.append(list(map(int, line)))
|
||||
|
||||
max_score = 0
|
||||
for y in range(len(trees)):
|
||||
for x in range(len(trees)):
|
||||
score = scenic_score(trees, y, x)
|
||||
if score > max_score:
|
||||
max_score = score
|
||||
return max_score
|
||||
|
||||
def main():
|
||||
example = clean(EXAMPLE)
|
||||
print("Example 1:", solve(example))
|
||||
|
||||
data = clean(open("d8.txt").read())
|
||||
print("Solution 1:", solve(data))
|
||||
|
||||
example = clean(EXAMPLE)
|
||||
print("Example 2:", solve2(example))
|
||||
|
||||
data = clean(open("d8.txt").read())
|
||||
print("Solution 2:", solve2(data))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
128
2022/d9.py
Normal file
128
2022/d9.py
Normal file
@ -0,0 +1,128 @@
|
||||
EXAMPLE = """
|
||||
R 4
|
||||
U 4
|
||||
L 3
|
||||
D 1
|
||||
R 4
|
||||
D 1
|
||||
L 5
|
||||
R 2
|
||||
"""
|
||||
|
||||
def clean(text: str) -> list[str]:
|
||||
return list(filter(lambda l: l.strip() != "", text.splitlines()))
|
||||
|
||||
def new_pos(h_pos, t_pos, dir):
|
||||
if dir == "R":
|
||||
new_h_pos = (h_pos[0] + 1, h_pos[1])
|
||||
elif dir == "U":
|
||||
new_h_pos = (h_pos[0], h_pos[1] + 1)
|
||||
elif dir == "L":
|
||||
new_h_pos = (h_pos[0] - 1, h_pos[1])
|
||||
elif dir == "D":
|
||||
new_h_pos = (h_pos[0], h_pos[1] - 1)
|
||||
elif dir == "NONE":
|
||||
new_h_pos = (h_pos[0], h_pos[1])
|
||||
else:
|
||||
raise Exception("Unexpected direction.")
|
||||
|
||||
# xxxxx
|
||||
# x---x
|
||||
# x-O-x
|
||||
# x---x
|
||||
# xxxxx
|
||||
dx, dy = t_pos[0] - new_h_pos[0], t_pos[1] - new_h_pos[1]
|
||||
delta = {
|
||||
(-1, -1): (0, 0),
|
||||
(-1, 0): (0, 0),
|
||||
(-1, 1): (0, 0),
|
||||
(0, -1): (0, 0),
|
||||
(0, 0): (0, 0),
|
||||
(0, 1): (0, 0),
|
||||
(1, -1): (0, 0),
|
||||
(1, 0): (0, 0),
|
||||
(1, 1): (0, 0),
|
||||
(-2, 2): (1, -1),
|
||||
(-2, 1): (1, -1),
|
||||
(-2, 0): (1, 0),
|
||||
(-2, -1): (1, 1),
|
||||
(-2, -2): (1, 1),
|
||||
(2, 2): (-1, -1),
|
||||
(2, 1): (-1, -1),
|
||||
(2, 0): (-1, 0),
|
||||
(2, -1): (-1, 1),
|
||||
(2, -2): (-1, 1),
|
||||
(-1, 2): (1, -1),
|
||||
(-1, -2): (1, 1),
|
||||
(0, 2): (0, -1),
|
||||
(0, -2): (0, 1),
|
||||
(1, 2): (-1, -1),
|
||||
(1, -2): (-1, 1),
|
||||
}
|
||||
dx_, dy_ = delta[(dx, dy)]
|
||||
new_t_pos = t_pos[0] + dx_, t_pos[1] + dy_
|
||||
# print(f"{h_pos=} {t_pos=} {dir=}")
|
||||
# print(f"{new_h_pos=} {dx=} {dy=}")
|
||||
# print(f"{new_t_pos=}")
|
||||
# print("----")
|
||||
return new_t_pos, new_h_pos
|
||||
|
||||
def solve(lines: list[str]):
|
||||
pos = set()
|
||||
h_pos = (0, 0)
|
||||
t_pos = (0, 0)
|
||||
pos.add(t_pos)
|
||||
for i in range(len(lines)):
|
||||
dir, amount = lines[i].split()
|
||||
for _ in range(int(amount)):
|
||||
t_pos, h_pos = new_pos(h_pos, t_pos, dir)
|
||||
pos.add(t_pos)
|
||||
# 44:00
|
||||
return len(pos)
|
||||
|
||||
EXAMPLE2 = """
|
||||
R 5
|
||||
U 8
|
||||
L 8
|
||||
D 3
|
||||
R 17
|
||||
D 10
|
||||
L 25
|
||||
U 20
|
||||
"""
|
||||
|
||||
def solve2(lines: list[str]):
|
||||
vis = set()
|
||||
poss = [(0, 0) for _ in range(10)]
|
||||
vis.add((0, 0))
|
||||
for i in range(len(lines)):
|
||||
dir, amount = lines[i].split()
|
||||
for _ in range(int(amount)):
|
||||
for i in range(len(poss) - 1):
|
||||
h_pos = poss[i]
|
||||
t_pos = poss[i + 1]
|
||||
if i == 0:
|
||||
t_pos, h_pos = new_pos(h_pos, t_pos, dir)
|
||||
else:
|
||||
t_pos, h_pos = new_pos(h_pos, t_pos, "NONE")
|
||||
poss[i] = h_pos
|
||||
poss[i + 1] = t_pos
|
||||
vis.add(poss[-1])
|
||||
# 58:00
|
||||
return len(vis)
|
||||
|
||||
def main():
|
||||
example = clean(EXAMPLE)
|
||||
print("Example 1:", solve(example))
|
||||
|
||||
data = clean(open("d9.txt").read())
|
||||
print("Solution 1:", solve(data))
|
||||
|
||||
example = clean(EXAMPLE2)
|
||||
print("Example 2:", solve2(example))
|
||||
|
||||
data = clean(open("d9.txt").read())
|
||||
print("Solution 2:", solve2(data))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
1
2022/lib.py
Symbolic link
1
2022/lib.py
Symbolic link
@ -0,0 +1 @@
|
||||
../lib.py
|
30
2023/dx.py
30
2023/dx.py
@ -1,30 +0,0 @@
|
||||
from lib import *
|
||||
|
||||
EXAMPLE = """
|
||||
"""
|
||||
|
||||
def solve(input: Input, second=False):
|
||||
res = 0
|
||||
input.stats()
|
||||
# g = input.grid2()
|
||||
# ls = input.lines()
|
||||
# ps = input.paras()
|
||||
return res
|
||||
|
||||
def main():
|
||||
DAY_INPUT = "ix.txt"
|
||||
|
||||
print("Example 1:", solve(Input(EXAMPLE)))
|
||||
return
|
||||
|
||||
print("Solution 1:", solve(Input(DAY_INPUT)))
|
||||
return
|
||||
|
||||
print("Example 2:", solve(Input(EXAMPLE), True))
|
||||
return
|
||||
|
||||
print("Solution 2:", solve(Input(DAY_INPUT), True))
|
||||
return
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
45
README.md
45
README.md
@ -101,6 +101,51 @@ written in Python.
|
||||
|
||||
# 2022
|
||||
|
||||
Done with this. Overall everything is solvable. It's more about consistency
|
||||
and focus. Of course, learning more algorithms and techniques helps.
|
||||
|
||||
Possible to-dos:
|
||||
|
||||
- [ ] Optimize day 19 because it is terrible.
|
||||
|
||||
**Times:**
|
||||
|
||||
- Day 1: 7:52 ... so slow brah :/ top 100 required 2:05...
|
||||
- Day 2: 22:30 ... I mistyped the first and second was just bad top 100 would
|
||||
have been 6:16 (doable?)
|
||||
- Day 3: 13:08 actually decent but top 100 required 5:24
|
||||
- Day 4: 7:08 but top 100 required 3:33 still okay
|
||||
- Day 5: 11:56 but 7:58 for top 100... getting better?
|
||||
- Day 6: 3:50 but 2:25 for leaderboard :D
|
||||
- Day 7: 27:55 and 14:47 for leaderboard; okay, I would say
|
||||
- Day 8: 61:00 and 10:00 for leaderboard; I need template code for searching
|
||||
coordinate systems
|
||||
- Day 9: 58:00 and 7:32 for leaderboard; I need code for 2D stuff
|
||||
- Day 10: 25:20 and 12:17 for leaderboard; okay, okay
|
||||
- Day 11: 45:00 and 18:00 for leaderboard; arg, it was doable man
|
||||
- Day 12: 39:45 and 9:46 for leaderboard; the people are ready for their
|
||||
searches :D
|
||||
- Day 13: 44:00 and 12:56 for leaderboard; these people are just good,
|
||||
seriously
|
||||
- Day 14: 35:00 and 14:54; I just have to get that much quicker... 2D code!
|
||||
- Day 15: 150:00 and 27:00; I didn't use Manhattan dist initially, lot's of
|
||||
debugging
|
||||
- Day 16: 52:00 and 64:00; ARE YOU SAYING I WOULD HAVE MADE THE
|
||||
LEADERBOARD?!?!?!?!?!?!?!
|
||||
- Day 17: Second one was fun with having to detect the repetition.
|
||||
- Day 18: 12:00 and 32:00; really straightforward and of course way too slow.
|
||||
- Day 19: Slow.
|
||||
- Day 20: Struggled way too much.
|
||||
- Day 21: Straightforward and relatively fast.
|
||||
- Day 22: Very hard and wasn't able to do hands free. Even the best guys took
|
||||
over an hour.
|
||||
- Day 23: Super straightforward, but took me way longer than it should have
|
||||
because I loose focus and make silly errors. Like back in Middleschool.
|
||||
- Day 24: Easy. Should have been faster, but no crazy mistakes. Still way too
|
||||
slow for something easy like this.
|
||||
- Day 25: Quickly solved via constraint solver. Actual solution much simpler. Don't know
|
||||
if I would have been able to figure it out.
|
||||
|
||||
|
||||
# 2023
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user