Skip to content

Commit

Permalink
Add 2023 solutions
Browse files Browse the repository at this point in the history
  • Loading branch information
NoahMollerstuen committed Dec 5, 2023
1 parent b5ccff0 commit 1efde4f
Show file tree
Hide file tree
Showing 20 changed files with 1,153 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.idea/
web_secrets.py
puzzle_inputs
**/part1_attempts.json
**/part2_attempts.json
51 changes: 51 additions & 0 deletions solutions/2022_day15/part1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from util import *
from util import Grid as g
import itertools as it
import re

h = Helper(test_mode=False, test_input="""
""")

inp = h.get_input_list()

sensors = []
beacons = []
dists = []
for line in inp:
m = re.findall(r"\d+", line)
sensors.append((int(m[0]), int(m[1])))
beacons.append((int(m[2]), int(m[3])))
dists.append(abs(sensors[-1][0] - beacons[-1][0]) + abs(sensors[-1][1] - beacons[-1][1]))


def merge_if_needed(seg1, seg2):
if seg1[1] < seg2[0] or seg2[1] < seg1[0]:
return None
return min(seg1[0], seg2[0]), max(seg1[1], seg2[1])


segments = []
for i, s in enumerate(sensors):
print(s)
b = beacons[i]
d = dists[i]
dist_from_line = abs(s[1] - 2000000)
if dist_from_line > d:
continue
seg = (s[0] - (d - dist_from_line), s[0] + (d - dist_from_line) + 1)

new_segments = []
for old_seg in segments:
merge = merge_if_needed(old_seg, seg)
if merge is None:
new_segments.append(old_seg)
else:
seg = merge
new_segments.append(seg)
segments = new_segments

tot = sum(s[1] - s[0] for s in segments)
tot -= len(set(b for b in beacons if b[1] == 2000000))

h.submit(tot)
54 changes: 54 additions & 0 deletions solutions/2022_day15/part2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
from util import *
from util import Grid as g
import itertools as it
import re

h = Helper(test_mode=False, test_input="""
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
""")

inp = h.get_input_list()

sensors = []
beacons = []
dists = []
for line in inp:
m = re.findall(r"[\d|-]+", line)
sensors.append((int(m[0]), int(m[1])))
beacons.append((int(m[2]), int(m[3])))
dists.append(abs(sensors[-1][0] - beacons[-1][0]) + abs(sensors[-1][1] - beacons[-1][1]))


def check_cell(x, y):
for i, s in enumerate(sensors):
d = dists[i]
if abs(s[0] - x) + abs(s[1] - y) <= d:
return
h.submit(x * 4000000 + y)


for i, s in enumerate(sensors):
d = dists[i]
print(d)
for x in range(s[0] - d - 1, s[0] + d + 2):
if not 0 <= x <= 4000000:
continue
y1 = s[1] - (d - abs(s[0] - x) + 1)
y2 = s[1] - (d - abs(s[0] - x) + 1)
if 0 <= y1 <= 4000000:
check_cell(x, y1)
if 0 <= y2 <= 4000000:
check_cell(x, y2)
58 changes: 58 additions & 0 deletions solutions/2022_day16/part1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from util import *
from util import Grid as g
import itertools as it
import re


h = Helper(test_mode=False, test_input="""
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
""")

inp = h.get_input_list()

adj_list = {}
flow_rates = {}
for line in inp:
m = re.match(r"Valve (\w\w) has flow rate=(\d+); tunnels? leads? to valves? ([\w, ]+)", line)
flow_rates[m[1]] = int(m[2])
adj_list[m[1]] = m[3].split(", ") or m[3]

print(adj_list)

q = [('AA', {k: False for k in adj_list.keys()}, 0, 0)]
final_states = []
while len(q) > 0:
room, valve_states, tick, score = q.pop(0)
if tick == 30:
final_states.append((room, valve_states, tick, score))
continue

new_states = []
if not valve_states[room] and flow_rates[room] > 0:
new_valves = {k: True if k == room else v for k, v in valve_states.items()}
new_states.append((room, new_valves, tick + 1, score + (29 - tick) * flow_rates[room]))
for neighbor in adj_list[room]:
new_states.append((neighbor, valve_states, tick + 1, score))

for state in new_states:
redundant = False

for s in q:
if state[0] == s[0] and state[3] <= s[3]:
redundant = True
break

if not redundant:
q.append(state)

print(final_states)
h.submit(max(s[3] for s in final_states))
63 changes: 63 additions & 0 deletions solutions/2022_day17/part1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from util import *
from util import Grid as g
import itertools as it
import re

h = Helper(test_mode=False, test_input="""
>>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>
""")

inp = h.get_input_raw()

shapes = [
((0, 0), (0, 1), (0, 2), (0, 3)),
((0, 1), (1, 0), (1, 1), (1, 2), (2, 1)),
((2, 2), (1, 2), (0, 0), (0, 1), (0, 2)),
((0, 0), (1, 0), (2, 0), (3, 0)),
((0, 0), (0, 1), (1, 0), (1, 1)),
]

heights = {shape: max([p[0] for p in shape]) + 1 for shape in shapes}
widths = {shape: max([p[1] for p in shape]) + 1 for shape in shapes}

shapes_iter = it.cycle(shapes)
jets_iter = it.cycle(inp)

grid = []
max_height = -1


def verify_pos(shape, pos):
for point in shape:
if g.get(grid, (pos[0] + point[0], pos[1] + point[1]), default="#") == "#":
return False
return True


for i in range(2022):
shape = next(shapes_iter)

shape_pos = (max_height + 4, 2)

for _ in range(shape_pos[0] + heights[shape] - len(grid)):
grid.append(["."] * 7)

while True:
new_pos = (shape_pos[0], shape_pos[1] + (1 if next(jets_iter) == '>' else -1))
if verify_pos(shape, new_pos):
shape_pos = new_pos

new_pos = (shape_pos[0] - 1, shape_pos[1])
if verify_pos(shape, new_pos):
shape_pos = new_pos
else:
for point in shape:
y = shape_pos[0] + point[0]
x = shape_pos[1] + point[1]
grid[y][x] = "#"
max_height = max(max_height, y)
break

# g.print(list(reversed(grid)), f"Tick {i}")

h.submit(max_height + 1)
90 changes: 90 additions & 0 deletions solutions/2022_day17/part2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import math

from util import *
from util import Grid as g
import itertools as it
import re

h = Helper(test_mode=False, test_input="""
>>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>
""")

inp = h.get_input_raw()

shapes = [
((0, 0), (0, 1), (0, 2), (0, 3)),
((0, 1), (1, 0), (1, 1), (1, 2), (2, 1)),
((2, 2), (1, 2), (0, 0), (0, 1), (0, 2)),
((0, 0), (1, 0), (2, 0), (3, 0)),
((0, 0), (0, 1), (1, 0), (1, 1)),
]

heights = {shape: max([p[0] for p in shape]) + 1 for shape in shapes}
widths = {shape: max([p[1] for p in shape]) + 1 for shape in shapes}

shapes_indx = 0
jets_indx = 0

grid = []
max_height = -1


def verify_pos(shape, pos):
for point in shape:
if g.get(grid, (pos[0] + point[0], pos[1] + point[1]), default="#") == "#":
return False
return True


indicies = []
last_10s = []
height_skipped = None

tick = 0
while tick < 1000000000000:
shape = shapes[shapes_indx]
shapes_indx = (shapes_indx + 1) % len(shapes)

shape_pos = (max_height + 4, 2)

for _ in range(shape_pos[0] + heights[shape] - len(grid)):
grid.append(["."] * 7)

while True:
new_pos = (shape_pos[0], shape_pos[1] + (1 if inp[jets_indx] == '>' else -1))
jets_indx = (jets_indx + 1) % len(inp)
if verify_pos(shape, new_pos):
shape_pos = new_pos

new_pos = (shape_pos[0] - 1, shape_pos[1])
if verify_pos(shape, new_pos):
shape_pos = new_pos
else:
for point in shape:
y = shape_pos[0] + point[0]
x = shape_pos[1] + point[1]
grid[y][x] = "#"
max_height = max(max_height, y)

if height_skipped is None and len(indicies) > 0 and jets_indx < indicies[-1][1]:
# Jet rollover
if indicies[-10:] in [l[0] for l in last_10s]:
# Pattern found
ticks_diff = tick - last_10s[-1][1]
height_diff = max_height - last_10s[-1][2]

cycles_skipped = (1000000000000 - tick) // ticks_diff
print(height_diff, ticks_diff, cycles_skipped)
tick += cycles_skipped * ticks_diff
print(tick)
height_skipped = cycles_skipped * height_diff

last_10s.append((indicies[-10:], tick, max_height))

indicies.append((shapes_indx, jets_indx))
break

tick += 1
# g.print(list(reversed(grid)))

h.submit(max_height + height_skipped + 1)
36 changes: 36 additions & 0 deletions solutions/2022_day18/part1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from util import *
from util import Grid as g
import itertools as it
import re

h = Helper(test_mode=False, test_input="""
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
""")

inp = h.get_input_list()

points = [tuple(int(n) for n in p.split(",")) for p in inp]

ADJ = ((0, 0, 1), (0, 0, -1), (0, 1, 0), (0, -1, 0), (1, 0, 0), (-1, 0, 0),)

surface = 0
for p in points:
print(p)
for side in ADJ:
side_coord = (p[0] + side[0], p[1] + side[1], p[2] + side[2])
if side_coord not in points:
surface += 1

h.submit(surface)
Loading

0 comments on commit 1efde4f

Please sign in to comment.