Compare commits

..

3 Commits

Author SHA1 Message Date
9d2cd556b2 Add day 22 readme update. 2023-12-27 18:30:25 -05:00
65d1a85912 Do day 20. 2023-12-27 18:30:04 -05:00
9fcc902703 Update readme and clean up day 20. 2023-12-27 13:26:40 -05:00
3 changed files with 146 additions and 12 deletions

View File

@@ -2,7 +2,8 @@
- Day 1: 40:00 (I don't know what I am doing.) - Day 1: 40:00 (I don't know what I am doing.)
- Day 2: 14:15 (Okay, but far way from leaderboard.) - Day 2: 14:15 (Okay, but far way from leaderboard.)
- Day 3: 1st 20:00, 2nd 70:00... (I had a logic error that took me a while to find.) - Day 3: 1st 20:00, 2nd 70:00... (I had a logic error that took me a while to
find.)
- Day 4: 1st 9:06, 2nd 22:31; it wasn't hard but I didn't think quick enough :/ - Day 4: 1st 9:06, 2nd 22:31; it wasn't hard but I didn't think quick enough :/
- Day 5: 1st 25:00, 2nd 1:55:00; Required patience and accuracy - Day 5: 1st 25:00, 2nd 1:55:00; Required patience and accuracy
- Day 6: 13:54; I was slow because I thought it is much harder? - Day 6: 13:54; I was slow because I thought it is much harder?
@@ -10,8 +11,10 @@
- Day 8: 25:00; I was doing pretty decent here. - Day 8: 25:00; I was doing pretty decent here.
- Day 9: 57:00; my input parse function did not consider negative values... - Day 9: 57:00; my input parse function did not consider negative values...
- Day 10: 180:00; this one was hard for me. - Day 10: 180:00; this one was hard for me.
- Day 11: 68:00; okay but not elegant and way too slow ofc; x-ray solution would have been neat - Day 11: 68:00; okay but not elegant and way too slow ofc; x-ray solution
- Day 12: 52:00 and 22:00 for leaderboard; had the right idea and I am good at this type of problem would have been neat
- Day 12: 52:00 and 22:00 for leaderboard; had the right idea and I am good at
this type of problem
- Day 13: 90:00; pretty straightforward but way too slow - Day 13: 90:00; pretty straightforward but way too slow
- Day 14: 5:55 for first and then 48:00; straightforward but slow, ofc - Day 14: 5:55 for first and then 48:00; straightforward but slow, ofc
- Day 15: 4:30 and 31:20; more reading comprehension than programming - Day 15: 4:30 and 31:20; more reading comprehension than programming
@@ -22,4 +25,14 @@
but didn't realize that I have to compute the outer edges for a while and but didn't realize that I have to compute the outer edges for a while and
after I did, I still got clockwise/counter-clockwise issues. They could have after I did, I still got clockwise/counter-clockwise issues. They could have
made it meaner by using different clock directions for example and input. made it meaner by using different clock directions for example and input.
- Day 19: - Day 19: This one was pretty straightforward and required the interval
technique we applied earlier.
- Day 20: Part 2 was tough. I had the right idea of printing out the periods of
the input conjunction gate pretty early, but then messed up the
implementation and thought it wasn't gonna work. Spent a half day thinking up
something else before returning to the idea and it worked flawlessly.
- Day 21:
- Day 22: Not too hard, but definitely way too slow for leaderboard.
- Day 23:
- Day 24:
- Day 25:

16
d20.py
View File

@@ -1,5 +1,6 @@
from lib import * from lib import *
from math import lcm from math import lcm
from collections import deque
EXAMPLE = """ EXAMPLE = """
broadcaster -> a, b, c broadcaster -> a, b, c
@@ -25,10 +26,9 @@ def visualize(modules):
f.write(" " + m[1] + ' -> ' + cm + "\n") f.write(" " + m[1] + ' -> ' + cm + "\n")
f.write("}") f.write("}")
def solve(i: Input, second=False): def solve(input: Input, second=False):
res = 0
modules = {} modules = {}
for line in i.lines(): for line in input.lines():
if not line: continue if not line: continue
src, dsts = line.split(" -> ") src, dsts = line.split(" -> ")
dsts = dsts.split(", ") dsts = dsts.split(", ")
@@ -48,17 +48,17 @@ def solve(i: Input, second=False):
if second: if second:
# visualize(modules) # visualize(modules)
periods = {d: [] for d in modules["kh"][2].keys()} (feed,) = [m[1] for m in modules.values() if "rx" in m[3]]
periods = {d: [] for d in modules[feed][2].keys()}
BUTTON_PUSHES = 10000 BUTTON_PUSHES = 10000
else: else:
BUTTON_PUSHES = 1000 BUTTON_PUSHES = 1000
lo, hi = 0, 0 lo, hi = 0, 0
for i in range(BUTTON_PUSHES): for i in range(BUTTON_PUSHES):
qs = [("button module", "broadcaster", 0)] qs = deque([("button module", "broadcaster", 0)])
while qs: while qs:
src, dst, sig = qs[0] src, dst, sig = qs.popleft()
qs = qs[1:]
if sig == 0: if sig == 0:
lo += 1 lo += 1
@@ -87,7 +87,7 @@ def solve(i: Input, second=False):
if new_pulse is not None: if new_pulse is not None:
for nxtdst in m[3]: for nxtdst in m[3]:
if second and nxtdst == "kh" and new_pulse == 1: if second and nxtdst == feed and new_pulse == 1:
# print(f"{i:>4}: {dst[:4]:>4} -{new_pulse}> {nxtdst}") # print(f"{i:>4}: {dst[:4]:>4} -{new_pulse}> {nxtdst}")
periods[dst].append(i) periods[dst].append(i)
qs.append((dst, nxtdst, new_pulse)) qs.append((dst, nxtdst, new_pulse))

121
d22.py Normal file
View File

@@ -0,0 +1,121 @@
from lib import *
EXAMPLE = """1,0,1~1,2,1
0,0,2~2,0,2
0,2,3~2,2,3
0,0,4~0,2,4
2,0,5~2,2,5
0,1,6~2,1,6
1,1,8~1,1,9
"""
def overlap(a, b):
# Could be made generic with for loop.
[(ax1, ax2), (ay1, ay2), (az1, az2)] = a
[(bx1, bx2), (by1, by2), (bz1, bz2)] = b
xo = (bx1 <= ax2 and bx2 >= ax1)
yo = (by1 <= ay2 and by2 >= ay1)
zo = (bz1 <= az2 and bz2 >= az1)
return xo and yo and zo
def can_overlap(a, b):
a, b = list(a), list(b)
za1, za2 = a[2]
zb1, zb2 = b[2]
zad = za1 - 1
a[2] = (za1 - zad, za2 - zad)
zbd = zb1 - 1
b[2] = (zb1 - zbd, zb2 - zbd)
return overlap(a, b)
def solve(input: Input, second=False):
bricks = []
for line in input.lines():
s = tuple(str_to_ints(line))
s = tuple([tuple(sorted([s[i], s[i + 3]])) for i in range(3)])
bricks.append(s)
# Check which bricks can overlap in general
d = {i: [] for i in range(len(bricks))}
for a in range(len(bricks)):
for b in range(a + 1, len(bricks)):
if can_overlap(bricks[a], bricks[b]):
# print(f"{bricks[a]} can overlap with {bricks[b]}")
d[a].append(b)
d[b].append(a)
# Lower bricks as much as possible
idxs = sorted(range(len(bricks)), key=lambda i: bricks[i][2][1])
for idx_active_idx, idx_active in enumerate(idxs):
b = list(bricks[idx_active])
lowest_z = 1
for idx_to_check in idxs[:idx_active_idx]:
if idx_to_check in d[idx_active]:
lowest_z = max(lowest_z, bricks[idx_to_check][2][1] + 1)
zp = list(b[2])
zp[0], zp[1] = lowest_z, zp[1] - (zp[0] - lowest_z)
b[2] = tuple(zp)
# print(f"{bricks[idx_active]} -> {b}")
bricks[idx_active] = b
# for l, b in zip(LETTERS_UPPER, bricks): print(l, b)
if second:
# Create a map that for each objects, shows what objects it is
# supported by.
supported_by = {i: set() for i in range(len(bricks))}
for i in range(len(bricks)):
b = bricks[i]
zl = b[2][0]
if zl == 1:
supported_by[i].add(-1)
for ni in d[i]:
if bricks[ni][2][1] + 1 == zl:
supported_by[i].add(ni)
res = 0
for i in range(len(bricks)):
removed = set([i])
to_process = [i]
while to_process:
ri = to_process.pop()
for ni in d[ri]:
if supported_by[ni].issubset(removed) and not ni in removed:
removed.add(ni)
to_process.append(ni)
res += len(removed) - 1
return res
else:
support_map = {i: [] for i in range(len(bricks))}
support_bricks = set()
# For all bricks, check if it would fall if a particular brick was removed.
for i in range(len(bricks)):
b = bricks[i]
zl = b[2][0]
if zl == 1:
continue # supported by floor
for ni in d[i]:
if bricks[ni][2][1] + 1 == zl:
support_map[i].append(ni)
if len(support_map[i]) == 1:
support_bricks.add(support_map[i][0])
# print(f"{bricks[i]} supported by {support_map[i]}")
return len(bricks) - len(support_bricks)
def main():
DAY_INPUT = "i22.txt"
print("Example 1:", solve(Input(EXAMPLE)))
print("Solution 1:", solve(Input(DAY_INPUT)))
assert solve(Input(DAY_INPUT)) == 428
print("Example 2:", solve(Input(EXAMPLE), True))
print("Solution 2:", solve(Input(DAY_INPUT), True))
assert solve(Input(DAY_INPUT), True) == 35654
if __name__ == "__main__":
main()