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 7a21d98..4973a69 100644 Binary files a/__pycache__/fred.cpython-311.pyc and b/__pycache__/fred.cpython-311.pyc differ 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