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
|
||||
|
||||
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:]))
|
||||
def main():
|
||||
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()
|
||||
|
|
20
day02.py
20
day02.py
|
@ -1,12 +1,18 @@
|
|||
import fileinput
|
||||
|
||||
part1, part2 = 0, 0
|
||||
|
||||
for line in fileinput.input(mode='rb'):
|
||||
theirs = line[0] - ord('A')
|
||||
ours = line[2] - ord('X')
|
||||
def main():
|
||||
part1, part2 = 0, 0
|
||||
|
||||
part1 += ours + (ours - theirs + 1) % 3 * 3 + 1
|
||||
part2 += ours * 3 + (theirs + ours - 1) % 3 + 1
|
||||
for line in fileinput.input(mode="rb"):
|
||||
theirs = line[0] - ord("A")
|
||||
ours = line[2] - ord("X")
|
||||
|
||||
print(part1, part2)
|
||||
part1 += ours + (ours - theirs + 1) % 3 * 3 + 1
|
||||
part2 += ours * 3 + (theirs + ours - 1) % 3 + 1
|
||||
|
||||
print(part1, part2)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
36
day03.py
36
day03.py
|
@ -1,8 +1,5 @@
|
|||
import fileinput
|
||||
|
||||
input = [s.strip() for s in fileinput.input()]
|
||||
part1, part2 = 0, 0
|
||||
|
||||
|
||||
def prio(x):
|
||||
if x.islower():
|
||||
|
@ -11,18 +8,25 @@ def prio(x):
|
|||
return ord(x) - ord("A") + 27
|
||||
|
||||
|
||||
for line in input:
|
||||
first = set(line[: len(line) // 2])
|
||||
second = set(line[len(line) // 2 :])
|
||||
both = (first & second).pop()
|
||||
part1 += prio(both)
|
||||
def main():
|
||||
input = [s.strip() for s in fileinput.input()]
|
||||
part1, part2 = 0, 0
|
||||
|
||||
for line in input:
|
||||
first = set(line[: len(line) // 2])
|
||||
second = set(line[len(line) // 2 :])
|
||||
both = (first & second).pop()
|
||||
part1 += prio(both)
|
||||
|
||||
for i in range(0, len(input), 3):
|
||||
x = set(input[i])
|
||||
y = set(input[i + 1])
|
||||
z = set(input[i + 2])
|
||||
overlap = (x & y & z).pop()
|
||||
part2 += prio(overlap)
|
||||
|
||||
print(part1, part2)
|
||||
|
||||
|
||||
for i in range(0, len(input), 3):
|
||||
x = set(input[i])
|
||||
y = set(input[i + 1])
|
||||
z = set(input[i + 2])
|
||||
overlap = (x & y & z).pop()
|
||||
part2 += prio(overlap)
|
||||
|
||||
print(part1, part2)
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
21
day04.py
21
day04.py
|
@ -1,14 +1,19 @@
|
|||
import fileinput
|
||||
|
||||
part1, part2 = 0, 0
|
||||
|
||||
for line in fileinput.input():
|
||||
a, b = line.split(",", 1)
|
||||
a1, a2 = [int(x) for x in a.split("-", 1)]
|
||||
b1, b2 = [int(x) for x in b.split("-", 1)]
|
||||
def main():
|
||||
part1, part2 = 0, 0
|
||||
|
||||
part1 += (a1 >= b1 and b2 >= a2) or (b1 >= a1 and a2 >= b2)
|
||||
part2 += a1 <= b2 and a2 >= b1
|
||||
for line in fileinput.input():
|
||||
a, b = line.split(",", 1)
|
||||
a1, a2 = [int(x) for x in a.split("-", 1)]
|
||||
b1, b2 = [int(x) for x in b.split("-", 1)]
|
||||
|
||||
part1 += (a1 >= b1 and b2 >= a2) or (b1 >= a1 and a2 >= b2)
|
||||
part2 += a1 <= b2 and a2 >= b1
|
||||
|
||||
print(part1, part2)
|
||||
|
||||
|
||||
print(part1, part2)
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
43
day05.py
43
day05.py
|
@ -1,26 +1,35 @@
|
|||
import sys
|
||||
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)
|
||||
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)
|
||||
def main():
|
||||
inp_stacks, inp_moves = (x.split("\n") for x in sys.stdin.read().split("\n\n", 1))
|
||||
|
||||
for i, line in enumerate(inp_moves):
|
||||
if i % 10000 == 0:
|
||||
print(i, len(inp_moves), end="\r")
|
||||
if not line:
|
||||
continue
|
||||
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)
|
||||
|
||||
_, a, _, b, _, c = line.split()
|
||||
n, f, t = int(a), int(b) - 1, int(c) - 1
|
||||
for i, line in enumerate(inp_moves):
|
||||
if i % 10000 == 0:
|
||||
print(i, len(inp_moves), end="\r")
|
||||
if not line:
|
||||
continue
|
||||
|
||||
stacks1[t] = numpy.concatenate((stacks1[t], stacks1[f][-n:][::-1]))
|
||||
stacks1[f] = stacks1[f][:-n]
|
||||
_, a, _, b, _, c = line.split()
|
||||
n, f, t = int(a), int(b) - 1, int(c) - 1
|
||||
|
||||
stacks2[t] = numpy.concatenate((stacks2[t], stacks2[f][-n:]))
|
||||
stacks2[f] = stacks2[f][:-n]
|
||||
stacks1[t] = numpy.concatenate((stacks1[t], stacks1[f][-n:][::-1]))
|
||||
stacks1[f] = stacks1[f][:-n]
|
||||
|
||||
print("".join(chr(s[-1]) for s in stacks1), "".join(chr(s[-1]) for s in stacks2))
|
||||
stacks2[t] = numpy.concatenate((stacks2[t], 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))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
11
day06.py
11
day06.py
|
@ -1,3 +1,8 @@
|
|||
inp = input().strip()
|
||||
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))
|
||||
def main():
|
||||
inp = input().strip()
|
||||
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