From a7eafca0a2281db3dc6c75ca7c87e29765dc76fa Mon Sep 17 00:00:00 2001 From: FrederikBaerentsen Date: Sat, 14 Dec 2024 13:07:16 +0100 Subject: [PATCH] Solved 2024/14 P2 --- 2024/14/14.md | 12 ++++-- 2024/14/solution.py | 70 +++++++++++++++++++++++++++---- __pycache__/fred.cpython-311.pyc | Bin 26403 -> 29594 bytes fred.py | 62 ++++++++++++++++++++++++++- 4 files changed, 131 insertions(+), 13 deletions(-) diff --git a/2024/14/14.md b/2024/14/14.md index c2357e1..c8374cd 100644 --- a/2024/14/14.md +++ b/2024/14/14.md @@ -156,8 +156,6 @@ after exactly 100 seconds have elapsed?* Your puzzle answer was `230686500`. -The first half of this puzzle is complete! It provides one gold star: \* - ## \-\-- Part Two \-\-- {#part2} During the bathroom break, someone notices that these robots seem @@ -170,8 +168,14 @@ picture of a Christmas tree*. *What is the fewest number of seconds that must elapse for the robots to display the Easter egg?* -Answer: +Your puzzle answer was `7672`. -Although it hasn\'t changed, you can still [get your puzzle +Both parts of this puzzle are complete! They provide two gold stars: +\*\* + +At this point, you should [return to your Advent calendar](/2024) and +try another puzzle. + +If you still want to see it, you can [get your puzzle input](14/input). diff --git a/2024/14/solution.py b/2024/14/solution.py index eb7742a..937ef74 100644 --- a/2024/14/solution.py +++ b/2024/14/solution.py @@ -1,13 +1,15 @@ #!/bin/python3 import sys,time,re from pprint import pprint +from termcolor import colored + sys.path.insert(0, '../../') -from fred import list2int,get_re,lprint,loadFile,addTuples,grid_valid +from fred import list2int,get_re,lprint,loadFile,addTuples,grid_valid,bfs,dfs,flood_fill start_time = time.time() -# input_f = 'test' -# size_r = 7 -# size_c = 11 +input_f = 'test' +size_r = 7 +size_c = 11 input_f = 'input' size_r = 103 @@ -15,13 +17,18 @@ size_c = 101 grid = [['.']*size_c]*size_r -def nprint(grid,pos,x): +def nprint(grid,pos=None,x=None,positions:list=None): for r in range(size_r): for c in range(size_c): - if (c,r) == pos: + if (c,r) == pos and positions is None: print(x,end='') + elif positions is not None: + if (c,r) in positions: + print(x,end='') + else: + print(colored(grid[r][c],'red'),end='') else: - print(grid[r][c],end='') + print(colored(grid[r][c],'red'),end='') print() ######################################### @@ -129,7 +136,54 @@ print('Part 1:',part1(), '\t\t', round((time.time() - start_time)*1000), 'ms') # # ######################################### def part2(): - return + instructions = loadFile(input_f) + cords = [] + for idx,inst in enumerate(instructions): + match = get_re(r"^p=(-?\d+),(-?\d+) v=(-?\d+),(-?\d+)",inst) + + instructions[idx] = [(int(match.group(1)),int(match.group(2))),(int(match.group(3)),int(match.group(4)))] + cords.append(instructions[idx][0]) + count = 0 + + def generate(): + coordinates = {} + for idx,inst in enumerate(instructions): + pos = inst[0] + vel = inst[1] + + pos = addTuples(pos,vel) + if pos[0] < 0: + pos = (pos[0]+size_c,pos[1]) + if pos[0] >= size_c: + pos = (pos[0]-size_c,pos[1]) + if pos[1] < 0: + pos = (pos[0],pos[1]+size_r) + if pos[1] >= size_r: + pos = (pos[0],pos[1]-size_r) + instructions[idx] = [pos,vel] + cords[idx] = pos + if pos not in coordinates: + coordinates[pos] = 0 + coordinates[pos] += 1 + return coordinates + + while True: + + coordinates = generate() + + count += 1 + + visited = [] + if 2 not in coordinates.values(): + for pos in coordinates.keys(): + if pos not in visited: + t_visited = flood_fill(coordinates.keys(),pos) + visited += t_visited + + if len(t_visited) > 10: + nprint(grid,x='*',positions=coordinates) + + return count start_time = time.time() print('Part 2:',part2(), '\t\t', round((time.time() - start_time)*1000), 'ms') \ No newline at end of file diff --git a/__pycache__/fred.cpython-311.pyc b/__pycache__/fred.cpython-311.pyc index 7a21d98d5a754bcb4d83aed72d35b57993371f11..4973a6928bc220a0dc1c41dd654ebdf9573b085e 100644 GIT binary patch delta 3350 zcmb7`duUtN8Nlzk4@tIS%W)h_a#H)Yaq1{d-MS%532BKH<9KV7RJBaPsq)MyC*N$n{Pu84g1P6ZGjiP zW44_=MGP}^_G9wi!lB`R*~t55&uG;1KGxm>G03JLVJqpUKQ(_c`n9eiR(=meRR}0b z)kf85JgL$jpjtrTMRCJCG}b}hF<%+mPwt!9u`cqid1vf6`EcQHV?8{%wa|XPA~-&P zroIOHj`{DvSi`$es7i`DnRuPvH$&t5$tMei@iyYB3X^dSCrV7wSdcg0c&erK2;sOH zZib%`X2cn3#x`TW&LxOB?`>;JKvgZ}IE9#>cX?Wad|t})IW9#Mf(x{g`Du%%alM$g zB?Qwr>N%aaC!|^%j>}0oK4-fP#@#~$St6Xy>zpp>Hr*bQ6yb^^FY1CWLP=0WC<#25 z6L2=1!#v_{%n&YNuXTq(?YCi__tw@5Q6L2*DAvo6zM|4loJQq<9E!x_iW~|@BF`xy zP1X_tnh3`xK1(fGFx$iaBTw{c3d zS7^_i#?j*;IT?mEsmj{gv~IQ@7E>&wf*6gpgs$BI&w~VrYtnVtxfB=VFYy5pI@ zpS?})T3Un`u6o{&m?ZAa(ATp)WMbK!tsj{5K#LiWw>IiGtAgoO9ggxs%8i@x3 z5$)yfnmP&-YF~$L53^jw)nxSQX+52XrzoPtU)dEZZ7&5%Pn4c`8=gCzDDejs^S$$L z%zx=;?()F_DE(rje0KPwua;jq_t9v1EcB~0`$J_%h<3y9oBWFb&HS5(%r)UUmvfZN z&)ZuvoaLv@;Yh&!ecWqZufkH(d>Xu$;-{fwilhX5r=_$A5pGY3Dd{$}xyO766&&3L zdfTIV!p-hexM2X>piiV%v1I{8=1r6)h`WR`Ak@*{plTUJl~*V{!73kvcPv;Hz@hY0 ztY*HigB%7c^S?#4&pCv4lAZATn02O#&F@5X&7kqw&G@0@K>bT5hSvglrRx(s{nrP-ItqUX^_MpEGO;B64KD}dp@>~Cwy ziz$*5lZ1*2nczbFFy0FQ^-Nv@JWC;7;StY(ZvjdILpKj0%cscJBapyZR#Q&eTno4m z1BJ)&dJC%sK&;u+=iMVKYA757E{%HWJxlE}oDt2y`10|F1emWdbV5i94Iu*H5d(yoz@T*J9!J6jF`5n#Et|--fghzuUKTJ*&rt) zC^N^{9#`wvZK8jN%4xI(_X}wWtn_fe?nAlh+3D;+#a?ghE8E-Pk9YD@`jo!yPc<;E zh(vl7#th~!M=_L z;gcS}#0PzQtAch}qgg1>d*)KG*nbnV@1gh*1^f8^1aoY&(NuO2tda4+{L^tX8ds(w v>dW*26!DWv`|-jZCCZ;TPuhrAA6enxWoYbGOt9Bh@nSn^Tj3rRY?}W9_+ERu delta 466 zcmbRBoN@6vM!w~|yj%=GAZ8hx&f+tXPl8cnqPi2K_Qb4wMxBYbbQyIgb1*71>P^;R zRAyxiX3*5%oX5D=Jy4VB<$oY3Vgl;bWGXTSQZP11sHh(z4rYTSfoecPFmW&&Dh}4$ zzq!WKjgfKg=EGj`?4pZ+N{c~y6%>j@K-!i7iOCBBWo_^ABuKnJhquF#*m3^0Z>gc%jAiSBAWx__A_(r z1oAa`i&jsTNQ&m&0_5CcO-U^%$tc=5xgkl5@$%-?Nm7iH@8^pNgWTq)seFsMxU#sY z0mvy@KAEFnhRs|Mb1R5A1|q=DxeQ`00}*;40_68!95%W6DWy57c11UUTt*-+F5djC RAeV`cL6=eW1Bd{t1^_<(dhP%K diff --git a/fred.py b/fred.py index 341f442..76ff892 100644 --- a/fred.py +++ b/fred.py @@ -601,4 +601,64 @@ def bfs(start, is_goal, get_neighbors, max_depth=float('inf')): new_path = path + [neighbor] queue.append((neighbor, new_path, depth + 1)) - return goal_nodes, paths_to_goal \ No newline at end of file + return goal_nodes, paths_to_goal + +def dfs(grid:list, pos:set) -> list: + """ + Perform a flood fill/dfs starting from the given position in the grid. + + Args: + grid (list): 2D list representing the grid. + pos (tuple): Starting position (row, col) in the grid. + + Returns: + list: List of visited positions. + """ + rows, cols = len(grid), len(grid[0]) + start_value = grid[pos[0]][pos[1]] + visited = set() + print(rows,cols,start_value) + def is_valid(r, c): + return 0 <= r < rows and 0 <= c < cols and (r, c) not in visited and grid[r][c] == start_value + + def dfs(r, c): + visited.add((r, c)) + for dr, dc in [(-1, 0), (1, 0), (0, -1), (0, 1)]: + nr, nc = r + dr, c + dc + if is_valid(nr, nc): + dfs(nr, nc) + + dfs(pos[0], pos[1]) + return list(visited) + +# Should probably be added to the regular dfs. +def flood_fill(cells, pos): + """ + Perform a flood fill starting from the given position in a grid defined by a list of occupied cells. + + Args: + cells (list): List of sets representing occupied positions in the grid. + pos (tuple): Starting position (row, col) in the grid. + + Returns: + list: List of visited positions. + """ + occupied = set(cells) # Set of all occupied positions. + if pos not in occupied: + return 0, [] + + visited = set() + + def is_valid(cell): + return cell in occupied and cell not in visited + + def dfs(cell): + visited.add(cell) + r, c = cell + for dr, dc in [(-1, 0), (1, 0), (0, -1), (0, 1)]: + neighbor = (r + dr, c + dc) + if is_valid(neighbor): + dfs(neighbor) + + dfs(pos) + return list(visited) \ No newline at end of file