whole bunch of days
This commit is contained in:
parent
e1a4d88b80
commit
8ffef89b6f
13 changed files with 446 additions and 55 deletions
14
day01.py
14
day01.py
|
@ -1,7 +1,13 @@
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
input = sys.stdin.read().strip().split("\n\n")
|
|
||||||
elves = sorted(sum(int(i) for i in elf.split("\n")) for elf in input)
|
|
||||||
|
|
||||||
print("Part 1:", elves[-1])
|
def main():
|
||||||
print("Part 2:", sum(elves[-3:]))
|
input = sys.stdin.read().strip().split("\n\n")
|
||||||
|
elves = sorted(sum(int(i) for i in elf.split("\n")) for elf in input)
|
||||||
|
|
||||||
|
print("Part 1:", elves[-1])
|
||||||
|
print("Part 2:", sum(elves[-3:]))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
16
day02.py
16
day02.py
|
@ -1,12 +1,18 @@
|
||||||
import fileinput
|
import fileinput
|
||||||
|
|
||||||
part1, part2 = 0, 0
|
|
||||||
|
|
||||||
for line in fileinput.input(mode='rb'):
|
def main():
|
||||||
theirs = line[0] - ord('A')
|
part1, part2 = 0, 0
|
||||||
ours = line[2] - ord('X')
|
|
||||||
|
for line in fileinput.input(mode="rb"):
|
||||||
|
theirs = line[0] - ord("A")
|
||||||
|
ours = line[2] - ord("X")
|
||||||
|
|
||||||
part1 += ours + (ours - theirs + 1) % 3 * 3 + 1
|
part1 += ours + (ours - theirs + 1) % 3 * 3 + 1
|
||||||
part2 += ours * 3 + (theirs + ours - 1) % 3 + 1
|
part2 += ours * 3 + (theirs + ours - 1) % 3 + 1
|
||||||
|
|
||||||
print(part1, part2)
|
print(part1, part2)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
18
day03.py
18
day03.py
|
@ -1,8 +1,5 @@
|
||||||
import fileinput
|
import fileinput
|
||||||
|
|
||||||
input = [s.strip() for s in fileinput.input()]
|
|
||||||
part1, part2 = 0, 0
|
|
||||||
|
|
||||||
|
|
||||||
def prio(x):
|
def prio(x):
|
||||||
if x.islower():
|
if x.islower():
|
||||||
|
@ -11,18 +8,25 @@ def prio(x):
|
||||||
return ord(x) - ord("A") + 27
|
return ord(x) - ord("A") + 27
|
||||||
|
|
||||||
|
|
||||||
for line in input:
|
def main():
|
||||||
|
input = [s.strip() for s in fileinput.input()]
|
||||||
|
part1, part2 = 0, 0
|
||||||
|
|
||||||
|
for line in input:
|
||||||
first = set(line[: len(line) // 2])
|
first = set(line[: len(line) // 2])
|
||||||
second = set(line[len(line) // 2 :])
|
second = set(line[len(line) // 2 :])
|
||||||
both = (first & second).pop()
|
both = (first & second).pop()
|
||||||
part1 += prio(both)
|
part1 += prio(both)
|
||||||
|
|
||||||
|
for i in range(0, len(input), 3):
|
||||||
for i in range(0, len(input), 3):
|
|
||||||
x = set(input[i])
|
x = set(input[i])
|
||||||
y = set(input[i + 1])
|
y = set(input[i + 1])
|
||||||
z = set(input[i + 2])
|
z = set(input[i + 2])
|
||||||
overlap = (x & y & z).pop()
|
overlap = (x & y & z).pop()
|
||||||
part2 += prio(overlap)
|
part2 += prio(overlap)
|
||||||
|
|
||||||
print(part1, part2)
|
print(part1, part2)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
11
day04.py
11
day04.py
|
@ -1,8 +1,10 @@
|
||||||
import fileinput
|
import fileinput
|
||||||
|
|
||||||
part1, part2 = 0, 0
|
|
||||||
|
|
||||||
for line in fileinput.input():
|
def main():
|
||||||
|
part1, part2 = 0, 0
|
||||||
|
|
||||||
|
for line in fileinput.input():
|
||||||
a, b = line.split(",", 1)
|
a, b = line.split(",", 1)
|
||||||
a1, a2 = [int(x) for x in a.split("-", 1)]
|
a1, a2 = [int(x) for x in a.split("-", 1)]
|
||||||
b1, b2 = [int(x) for x in b.split("-", 1)]
|
b1, b2 = [int(x) for x in b.split("-", 1)]
|
||||||
|
@ -10,5 +12,8 @@ for line in fileinput.input():
|
||||||
part1 += (a1 >= b1 and b2 >= a2) or (b1 >= a1 and a2 >= b2)
|
part1 += (a1 >= b1 and b2 >= a2) or (b1 >= a1 and a2 >= b2)
|
||||||
part2 += a1 <= b2 and a2 >= b1
|
part2 += a1 <= b2 and a2 >= b1
|
||||||
|
|
||||||
|
print(part1, part2)
|
||||||
|
|
||||||
print(part1, part2)
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
23
day05.py
23
day05.py
|
@ -1,14 +1,19 @@
|
||||||
import sys
|
import sys
|
||||||
import numpy
|
import numpy
|
||||||
|
|
||||||
inp_stacks, inp_moves = (x.split("\n") for x in sys.stdin.read().split("\n\n", 1))
|
|
||||||
|
|
||||||
rows = (line[1::4] for line in inp_stacks[::-1] if "[" in line)
|
def main():
|
||||||
stacks = [numpy.array([ord(c) for c in x if c != ' '], dtype=numpy.int8) for x in zip(*rows)]
|
inp_stacks, inp_moves = (x.split("\n") for x in sys.stdin.read().split("\n\n", 1))
|
||||||
stacks1 = numpy.array(stacks)
|
|
||||||
stacks2 = numpy.ndarray.copy(stacks1)
|
|
||||||
|
|
||||||
for i, line in enumerate(inp_moves):
|
rows = (line[1::4] for line in inp_stacks[::-1] if "[" in line)
|
||||||
|
stacks = [
|
||||||
|
numpy.array([ord(c) for c in x if c != " "], dtype=numpy.int8)
|
||||||
|
for x in zip(*rows)
|
||||||
|
]
|
||||||
|
stacks1 = numpy.array(stacks)
|
||||||
|
stacks2 = numpy.ndarray.copy(stacks1)
|
||||||
|
|
||||||
|
for i, line in enumerate(inp_moves):
|
||||||
if i % 10000 == 0:
|
if i % 10000 == 0:
|
||||||
print(i, len(inp_moves), end="\r")
|
print(i, len(inp_moves), end="\r")
|
||||||
if not line:
|
if not line:
|
||||||
|
@ -23,4 +28,8 @@ for i, line in enumerate(inp_moves):
|
||||||
stacks2[t] = numpy.concatenate((stacks2[t], stacks2[f][-n:]))
|
stacks2[t] = numpy.concatenate((stacks2[t], stacks2[f][-n:]))
|
||||||
stacks2[f] = stacks2[f][:-n]
|
stacks2[f] = stacks2[f][:-n]
|
||||||
|
|
||||||
print("".join(chr(s[-1]) for s in stacks1), "".join(chr(s[-1]) for s in stacks2))
|
print("".join(chr(s[-1]) for s in stacks1), "".join(chr(s[-1]) for s in stacks2))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
11
day06.py
11
day06.py
|
@ -1,3 +1,8 @@
|
||||||
inp = input().strip()
|
def main():
|
||||||
print(next(i + 4 for i in range(len(inp)) if len(set(inp[i : i + 4])) == 4))
|
inp = input().strip()
|
||||||
print(next(i + 14 for i in range(len(inp)) if len(set(inp[i : i + 14])) == 14))
|
print(next(i + 4 for i in range(len(inp)) if len(set(inp[i : i + 4])) == 4))
|
||||||
|
print(next(i + 14 for i in range(len(inp)) if len(set(inp[i : i + 14])) == 14))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
43
day07.py
Normal file
43
day07.py
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import fileinput
|
||||||
|
from collections import defaultdict
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
cwd: list[str] = []
|
||||||
|
folders: defaultdict[tuple[str, ...], int] = defaultdict(int)
|
||||||
|
subdirs: defaultdict[tuple[str, ...], list[str]] = defaultdict(list)
|
||||||
|
|
||||||
|
for line in fileinput.input():
|
||||||
|
s = line.split()
|
||||||
|
|
||||||
|
if s[0] == "$":
|
||||||
|
if s[1] == "cd":
|
||||||
|
if s[2] == "..":
|
||||||
|
cwd.pop()
|
||||||
|
elif s[2] == "/":
|
||||||
|
cwd.clear()
|
||||||
|
else:
|
||||||
|
cwd.append(s[2])
|
||||||
|
else:
|
||||||
|
if s[0].isdigit():
|
||||||
|
folders[tuple(cwd)] += int(s[0])
|
||||||
|
elif s[0] == "dir":
|
||||||
|
subdirs[tuple(cwd)].append(s[1])
|
||||||
|
|
||||||
|
|
||||||
|
def recur(path: tuple[str, ...]) -> int:
|
||||||
|
# size = folders[path]
|
||||||
|
for subdir in subdirs[path]:
|
||||||
|
folders[path] += recur(path + (subdir,))
|
||||||
|
return folders[path]
|
||||||
|
|
||||||
|
|
||||||
|
recur(())
|
||||||
|
pprint(folders)
|
||||||
|
|
||||||
|
part1 = sum(x for x in folders.values() if x <= 100_000)
|
||||||
|
print(part1)
|
||||||
|
|
||||||
|
used = folders[()]
|
||||||
|
free = 70_000_000 - used
|
||||||
|
need_freed = 30_000_000 - free
|
||||||
|
print(min(x for x in folders.values() if x > 30_000_000 - free))
|
45
day08.py
Normal file
45
day08.py
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import fileinput
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
inp = [[int(y) for y in x.strip()] for x in fileinput.input()]
|
||||||
|
inp_ = list(zip(*inp))
|
||||||
|
|
||||||
|
part1 = 0
|
||||||
|
|
||||||
|
for y in range(1, len(inp) - 1):
|
||||||
|
for x in range(1, len(inp[0]) - 1):
|
||||||
|
x_min_max = max(inp_[x][:y])
|
||||||
|
y_min_max = max(inp[y][:x])
|
||||||
|
x_max_max = max(inp_[x][y + 1 :])
|
||||||
|
y_max_max = max(inp[y][x + 1 :])
|
||||||
|
n = inp[y][x]
|
||||||
|
if n > x_min_max or n > y_min_max or n > x_max_max or n > y_max_max:
|
||||||
|
part1 += 1
|
||||||
|
|
||||||
|
part1 += (len(inp) - 1) * 4
|
||||||
|
|
||||||
|
|
||||||
|
def viewing_dist(x: int, y: int, dx: int, dy: int) -> int:
|
||||||
|
dist = 0
|
||||||
|
n = inp[y][x]
|
||||||
|
m = 0
|
||||||
|
while n > m:
|
||||||
|
x += dx
|
||||||
|
y += dy
|
||||||
|
if x < 0 or y < 0 or y >= len(inp) or x >= len(inp[0]):
|
||||||
|
break
|
||||||
|
dist += 1
|
||||||
|
m = inp[y][x]
|
||||||
|
return dist
|
||||||
|
|
||||||
|
|
||||||
|
scores = []
|
||||||
|
for y in range(1, len(inp) - 1):
|
||||||
|
for x in range(1, len(inp[0]) - 1):
|
||||||
|
a = viewing_dist(x, y, 0, -1)
|
||||||
|
b = viewing_dist(x, y, -1, 0)
|
||||||
|
c = viewing_dist(x, y, 1, 0)
|
||||||
|
d = viewing_dist(x, y, 0, 1)
|
||||||
|
scores.append(a * b * c * d)
|
||||||
|
|
||||||
|
print(part1, max(scores))
|
55
day09.py
Normal file
55
day09.py
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
import fileinput
|
||||||
|
|
||||||
|
tx, ty, hx, hy = 0, 0, 0, 0
|
||||||
|
|
||||||
|
tail_positions = set()
|
||||||
|
|
||||||
|
for line in fileinput.input():
|
||||||
|
dir_, steps = line.split()
|
||||||
|
|
||||||
|
dx, dy = 0, 0
|
||||||
|
match dir_:
|
||||||
|
case "U":
|
||||||
|
dx, dy = 0, 1
|
||||||
|
case "D":
|
||||||
|
dx, dy = 0, -1
|
||||||
|
case "L":
|
||||||
|
dx, dy = -1, 0
|
||||||
|
case "R":
|
||||||
|
dx, dy = 1, 0
|
||||||
|
case _:
|
||||||
|
assert False
|
||||||
|
|
||||||
|
for _ in range(int(steps)):
|
||||||
|
hx_, hy_ = hx, hy
|
||||||
|
hx += dx
|
||||||
|
hy += dy
|
||||||
|
if abs(tx - hx) > 1 or abs(ty - hy) > 1:
|
||||||
|
tx = hx_
|
||||||
|
ty = hy_
|
||||||
|
# for y in range(6, -1, -1):
|
||||||
|
# for x in range(6):
|
||||||
|
# if (x, y) == (hx, hy):
|
||||||
|
# print("H", end="")
|
||||||
|
# elif (x, y) == (tx, ty):
|
||||||
|
# print("T", end="")
|
||||||
|
# elif (x, y) == (0, 0):
|
||||||
|
# print("s", end="")
|
||||||
|
# else:
|
||||||
|
# print(".", end="")
|
||||||
|
# print()
|
||||||
|
# print()
|
||||||
|
tail_positions.add((tx, ty))
|
||||||
|
print("========")
|
||||||
|
|
||||||
|
print(len(tail_positions))
|
||||||
|
|
||||||
|
for y in range(10, -1, -1):
|
||||||
|
for x in range(20):
|
||||||
|
if (x, y) == (0, 0):
|
||||||
|
print("s", end="")
|
||||||
|
elif (x, y) in tail_positions:
|
||||||
|
print("#", end="")
|
||||||
|
else:
|
||||||
|
print(".", end="")
|
||||||
|
print()
|
33
day10.py
Normal file
33
day10.py
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import fileinput
|
||||||
|
|
||||||
|
reg_x = 1
|
||||||
|
cyc = 0
|
||||||
|
|
||||||
|
DURATIONS = {"noop": 1, "addx": 2}
|
||||||
|
|
||||||
|
part1 = 0
|
||||||
|
screen = [0] * 240
|
||||||
|
|
||||||
|
for line in fileinput.input():
|
||||||
|
mnem, *args = line.strip().split()
|
||||||
|
d = 0
|
||||||
|
|
||||||
|
for _ in range(DURATIONS[mnem]):
|
||||||
|
cyc += 1
|
||||||
|
if (cyc - 20) % 40 == 0:
|
||||||
|
part1 += cyc * reg_x
|
||||||
|
|
||||||
|
c = (cyc - 1) % 40 + 1
|
||||||
|
if reg_x == c or reg_x + 1 == c or reg_x + 2 == c:
|
||||||
|
screen[cyc - 1] = reg_x
|
||||||
|
|
||||||
|
match mnem:
|
||||||
|
case "noop":
|
||||||
|
pass
|
||||||
|
|
||||||
|
case "addx":
|
||||||
|
reg_x += int(args[0])
|
||||||
|
|
||||||
|
print(part1)
|
||||||
|
for i in range(0, 240, 40):
|
||||||
|
print("".join("#" if h else " " for h in screen[i : i + 40]))
|
76
day11.py
Normal file
76
day11.py
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
import sys
|
||||||
|
from pprint import pprint
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from functools import reduce
|
||||||
|
from typing import List
|
||||||
|
import operator
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Monke:
|
||||||
|
operation: str
|
||||||
|
param: str
|
||||||
|
divisible_by: int
|
||||||
|
if_true: int
|
||||||
|
if_false: int
|
||||||
|
|
||||||
|
|
||||||
|
inputs = [l.split("\n") for l in sys.stdin.read().split("\n\n")]
|
||||||
|
monkeys: List[Monke] = []
|
||||||
|
|
||||||
|
items = []
|
||||||
|
inspections = []
|
||||||
|
visited = []
|
||||||
|
|
||||||
|
for monkey in inputs:
|
||||||
|
items.append(tuple(int(x) for x in monkey[1][18:].split(", ")))
|
||||||
|
inspections.append(0)
|
||||||
|
visited.append({})
|
||||||
|
|
||||||
|
op, param = monkey[2].split()[4:]
|
||||||
|
divisible_by = int(monkey[3].split()[-1])
|
||||||
|
if_true = int(monkey[4].split()[-1])
|
||||||
|
if_false = int(monkey[5].split()[-1])
|
||||||
|
|
||||||
|
monkeys.append(Monke(op, param, divisible_by, if_true, if_false))
|
||||||
|
|
||||||
|
|
||||||
|
def do_round():
|
||||||
|
for m, monke in enumerate(monkeys):
|
||||||
|
# print("Monke", m, monke.items)
|
||||||
|
for item in items[m]:
|
||||||
|
inspections[m] += 1
|
||||||
|
|
||||||
|
# print(" W :=", item)
|
||||||
|
|
||||||
|
param = item if monke.param == "old" else int(monke.param)
|
||||||
|
if monke.operation == "*":
|
||||||
|
item *= param
|
||||||
|
# print(" W *", param, "=", item)
|
||||||
|
elif monke.operation == "+":
|
||||||
|
item += param
|
||||||
|
# print(" W +", param, "=", item)
|
||||||
|
else:
|
||||||
|
assert False
|
||||||
|
|
||||||
|
item //= 3
|
||||||
|
# print(" W / 3 =", item)
|
||||||
|
|
||||||
|
divisible = item % monke.divisible_by == 0
|
||||||
|
# print(" W %", monke.divisible_by, "== 0 =", divisible)
|
||||||
|
|
||||||
|
target = monke.if_true if divisible else monke.if_false
|
||||||
|
# print(" Thrown to", target)
|
||||||
|
items[target] = (*items[target], item)
|
||||||
|
|
||||||
|
items[m] = ()
|
||||||
|
|
||||||
|
|
||||||
|
for i in range(20):
|
||||||
|
do_round()
|
||||||
|
print(reduce(operator.mul, sorted(inspections)[-2:]))
|
||||||
|
|
||||||
|
# for i in range(20, 10_000):
|
||||||
|
# if i % 100 == 0: print(i)
|
||||||
|
# do_round()
|
||||||
|
print(reduce(operator.mul, sorted(inspections)[-2:]))
|
60
day12.py
Normal file
60
day12.py
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
import fileinput
|
||||||
|
from collections import deque
|
||||||
|
|
||||||
|
map = []
|
||||||
|
start_pos = None
|
||||||
|
end_pos = None
|
||||||
|
|
||||||
|
for y, row in enumerate(fileinput.input(mode="rb")):
|
||||||
|
row = row.strip()
|
||||||
|
if not row:
|
||||||
|
continue
|
||||||
|
|
||||||
|
r = []
|
||||||
|
for x, col in enumerate(row):
|
||||||
|
match col:
|
||||||
|
case 83:
|
||||||
|
start_pos = (x, y)
|
||||||
|
r.append(0)
|
||||||
|
case 69:
|
||||||
|
end_pos = (x, y)
|
||||||
|
r.append(25)
|
||||||
|
case _:
|
||||||
|
r.append(col - 97)
|
||||||
|
map.append(r)
|
||||||
|
|
||||||
|
assert start_pos is not None
|
||||||
|
assert end_pos is not None
|
||||||
|
|
||||||
|
part1, part2 = None, None
|
||||||
|
|
||||||
|
trace: tuple[tuple[int, int], ...] = ()
|
||||||
|
stack = deque([(0, end_pos, trace)])
|
||||||
|
visited = set()
|
||||||
|
while stack:
|
||||||
|
h_, (x, y), trace = stack.popleft()
|
||||||
|
if x < 0 or x >= len(map[0]) or y < 0 or y >= len(map) or (x, y) in visited:
|
||||||
|
continue
|
||||||
|
|
||||||
|
h = map[y][x]
|
||||||
|
if h - h_ < -1:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if part1 is None and (x, y) == start_pos:
|
||||||
|
part1 = len(trace)
|
||||||
|
if part2 is None and h == 0:
|
||||||
|
part2 = len(trace)
|
||||||
|
if part1 is not None and part2 is not None:
|
||||||
|
break
|
||||||
|
|
||||||
|
visited.add((x, y))
|
||||||
|
|
||||||
|
trace = trace + ((x, y, h),)
|
||||||
|
stack.append((h, (x - 1, y + 0), trace))
|
||||||
|
stack.append((h, (x + 1, y + 0), trace))
|
||||||
|
stack.append((h, (x + 0, y - 1), trace))
|
||||||
|
stack.append((h, (x + 0, y + 1), trace))
|
||||||
|
else:
|
||||||
|
assert False
|
||||||
|
|
||||||
|
print(part1, part2)
|
44
day13.py
Normal file
44
day13.py
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
import fileinput
|
||||||
|
import json
|
||||||
|
from functools import cmp_to_key
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
pairs = []
|
||||||
|
pair: list[list[Any]] = []
|
||||||
|
packets = [[[2]], [[6]]]
|
||||||
|
|
||||||
|
for line in fileinput.input():
|
||||||
|
if not line.strip():
|
||||||
|
pairs.append(pair)
|
||||||
|
pair = []
|
||||||
|
else:
|
||||||
|
obj = json.loads(line)
|
||||||
|
pair.append(obj)
|
||||||
|
packets.append(obj)
|
||||||
|
|
||||||
|
pairs.append(pair)
|
||||||
|
|
||||||
|
def cmp(xs: list[Any] | int, ys: list[Any] | int) -> int:
|
||||||
|
if isinstance(xs, int) and isinstance(ys, int):
|
||||||
|
return (xs > ys) - (xs < ys)
|
||||||
|
|
||||||
|
if isinstance(xs, int):
|
||||||
|
xs = [xs]
|
||||||
|
if isinstance(ys, int):
|
||||||
|
ys = [ys]
|
||||||
|
|
||||||
|
for x, y in zip(xs, ys):
|
||||||
|
if result := cmp(x, y):
|
||||||
|
return result
|
||||||
|
|
||||||
|
return (len(xs) > len(ys)) - (len(xs) < len(ys))
|
||||||
|
|
||||||
|
print(sum(i + 1 for i, (xs, ys) in enumerate(pairs) if cmp(xs, ys) == -1))
|
||||||
|
|
||||||
|
packets.sort(key=cmp_to_key(cmp))
|
||||||
|
print((packets.index([[2]]) + 1) * (packets.index([[6]]) + 1))
|
||||||
|
|
||||||
|
|
||||||
|
main()
|
Loading…
Reference in a new issue