diff --git a/2024/03/notes.txt b/2024/03/notes.txt new file mode 100644 index 0000000..4dafc8c --- /dev/null +++ b/2024/03/notes.txt @@ -0,0 +1,17 @@ + # # Second attempt + + # instructions = "" + + # with open(input_f) as file: + # for line in file: + # instructions += line + # print(instructions) + + +# #(do\(\).*?mul\((\d+),{1}(\d+)\)) + + + +# (?<=do\(\))([^d]*(mul\(\d+,\d+\))[^d]*)+(?=don't\(\)) + +# (?<=do\(\))[^m]*(mul\((\d+),{1}(\d+)\)*)*[^d]*(?=don't\(\)) diff --git a/2024/03/solution.py b/2024/03/solution.py index fa5f153..c6e25a8 100644 --- a/2024/03/solution.py +++ b/2024/03/solution.py @@ -43,9 +43,6 @@ if part == 2: if do: m = get_re(r"mul\((\d+),{1}(\d+)\)",match) result += (int(m.group(1))*int(m.group(2))) -print(result) - + print(result) # Not really happy with my code. I would prefer to find all mul(x,y) between do() and don't(), -# instead of finding all the mul/do/don't and then turning calculation on/off. - -#(do\(\).*?mul\((\d+),{1}(\d+)\)) \ No newline at end of file +# instead of finding all the mul/do/don't and then turning calculation on/off. \ No newline at end of file diff --git a/2024/03/test.py b/2024/03/test.py deleted file mode 100644 index 55eae9e..0000000 --- a/2024/03/test.py +++ /dev/null @@ -1,16 +0,0 @@ -from re import findall - -total1 = total2 = 0 -enabled = True -data = open('input').read() - -for a, b, do, dont in findall(r"mul\((\d+),(\d+)\)|(do\(\))|(don't\(\))", data): - if do or dont: - enabled = bool(do) - else: - x = int(a) * int(b) - total1 += x - total2 += x * enabled - -print(total1, total2) - diff --git a/2024/04/4.md b/2024/04/4.md new file mode 100644 index 0000000..fd871f7 --- /dev/null +++ b/2024/04/4.md @@ -0,0 +1,104 @@ +## \-\-- Day 4: Ceres Search \-\-- + +\"Looks like the Chief\'s not here. Next!\" One of The Historians pulls +out a device and pushes the only button on it. After a brief flash, you +recognize the interior of the [Ceres monitoring station](/2019/day/10)! + +As the search for the Chief continues, a small Elf who lives on the +station tugs on your shirt; she\'d like to know if you could help her +with her *word search* (your puzzle input). She only has to find one +word: `XMAS`. + +This word search allows words to be horizontal, vertical, diagonal, +written backwards, or even overlapping other words. It\'s a little +unusual, though, as you don\'t merely need to find one instance of +`XMAS` - you need to find *all of them*. Here are a few ways `XMAS` +might appear, where irrelevant characters have been replaced with `.`: + + ..X... + .SAMX. + .A..A. + XMAS.S + .X.... + +The actual word search will be full of letters instead. For example: + + MMMSXXMASM + MSAMXMSMSA + AMXSXMAAMM + MSAMASMSMX + XMASAMXAMM + XXAMMXXAMA + SMSMSASXSS + SAXAMASAAA + MAMMMXMMMM + MXMXAXMASX + +In this word search, `XMAS` occurs a total of `18` times; here\'s the +same word search again, but where letters not involved in any `XMAS` +have been replaced with `.`: + + ....XXMAS. + .SAMXMS... + ...S..A... + ..A.A.MS.X + XMASAMX.MM + X.....XA.A + S.S.S.S.SS + .A.A.A.A.A + ..M.M.M.MM + .X.X.XMASX + +Take a look at the little Elf\'s word search. *How many times does +`XMAS` appear?* + +Your puzzle answer was `2378`. + +## \-\-- Part Two \-\-- {#part2} + +The Elf looks quizzically at you. Did you misunderstand the assignment? + +Looking for the instructions, you flip over the word search to find that +this isn\'t actually an `XMAS` puzzle; it\'s an +`X-MAS` +puzzle in which you\'re supposed to find two `MAS` in the shape of an +`X`. One way to achieve that is like this: + + M.S + .A. + M.S + +Irrelevant characters have again been replaced with `.` in the above +diagram. Within the `X`, each `MAS` can be written forwards or +backwards. + +Here\'s the same example from before, but this time all of the `X-MAS`es +have been kept instead: + + .M.S...... + ..A..MSMS. + .M.S.MAA.. + ..A.ASMSM. + .M.S.M.... + .......... + S.S.S.S.S. + .A.A.A.A.. + M.M.M.M.M. + .......... + +In this example, an `X-MAS` appears `9` times. + +Flip the word search from the instructions back over to the word search +side and try again. *How many times does an `X-MAS` appear?* + +Your puzzle answer was `1796`. + +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](4/input). + diff --git a/2024/04/solution.py b/2024/04/solution.py new file mode 100644 index 0000000..dee3383 --- /dev/null +++ b/2024/04/solution.py @@ -0,0 +1,66 @@ +#!/bin/python3 +import sys,re +from itertools import cycle +from pprint import pprint +sys.path.insert(0, '../../') +from fred import list2int,get_re,nprint,lprint, toGrid,grid_valid,addTuples,get_value_in_direction + +input_f = 'input' +part = 2 + +grid = toGrid(input_f) + +directions = { + 'up': (-1, 0), + 'down': (1, 0), + 'left': (0, -1), + 'right': (0, 1), + 'up-left': (-1, -1), + 'up-right': (-1, 1), + 'down-left': (1, -1), + 'down-right': (1, 1) +} + +count = 0 + +######################################### +# # +# Part 1 # +# # +######################################### + +if part == 1: + directions = { + 'up': (-1, 0), + 'down': (1, 0), + 'left': (0, -1), + 'right': (0, 1), + 'up-left': (-1, -1), + 'up-right': (-1, 1), + 'down-left': (1, -1), + 'down-right': (1, 1) + } + for r, rows in enumerate(grid): + for c, _ in enumerate(rows): + if get_value_in_direction(grid,(r,c)) == 'X': + for d in directions: + if get_value_in_direction(grid,(r,c),d,4,'str') == 'XMAS': + count += 1 + print(count) + + +######################################### +# # +# Part 2 # +# # +######################################### +if part == 2: + # Kinda ugly code, wish it would be nicer. + for r, rows in enumerate(grid): + for c, _ in enumerate(rows): + tmp = '' + if get_value_in_direction(grid,(r,c)) == 'A': + if (get_value_in_direction(grid,(r,c),'up-left') == 'M' and get_value_in_direction(grid,(r,c),'down-right') == 'S') or (get_value_in_direction(grid,(r,c),'up-left') == 'S' and get_value_in_direction(grid,(r,c),'down-right') == 'M'): + if (get_value_in_direction(grid,(r,c),'up-right') == 'M' and get_value_in_direction(grid,(r,c),'down-left') == 'S') or (get_value_in_direction(grid,(r,c),'up-right') == 'S' and get_value_in_direction(grid,(r,c),'down-left') == 'M'): + count += 1 + print(count) \ No newline at end of file diff --git a/README.md b/README.md index a3df945..b56766e 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,9 @@ .--'~ ~ ~| .-' * \ / '-. 1 ** .--'~ ,* ~ | | >o< \_\_\|_/__/ | 2 ** .---': ~ '(~), ~| | >@>O< o-_/.()__------| 3 ** + |@..@'. ~ " ' ~ | |>O>o<@< \____ .'| 4 ** + + ## 2023 . * ~~~~ /\ ' . 14 diff --git a/__pycache__/fred.cpython-311.pyc b/__pycache__/fred.cpython-311.pyc index 97648b5..067a3b1 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 e77c93d..4658d0d 100644 --- a/fred.py +++ b/fred.py @@ -12,6 +12,8 @@ def toGrid(input,parser=None): grid.append(list(line.rstrip())) return grid +def addTuples(x:tuple,y:tuple): + return (x[0]+y[0],x[1]+y[1]) def findDupes(input:list): # Returns the indicies of duplicate values in list @@ -54,6 +56,11 @@ def nprint(grid,cur:set=None,sign:str=None): def list2int(x): return list(map(int, x)) +def grid_valid(x,y,grid): + rows = len(grid) + cols = len(grid[0]) + return 0 <= x < rows and 0 <= y < cols + def get_re(pattern,str): match = re.match(pattern, str) if match: @@ -66,20 +73,22 @@ def ppprint(x): print(x[idx][jdx],end='') print() -def get_value_in_direction(grid, position, direction=None): +def get_value_in_direction(grid, position, direction=None,length=1,type:str=None): """ - Get the value in a specified direction from a given position in a grid. + Get the value(s) in a specified direction from a given position in a grid. If no direction is provided, returns the value at the current position. Parameters: - grid (list of list of int/float): The 2D grid. + grid (list of list of int/float/str): The 2D grid. position (set): A set containing x (row index) and y (column index) as integers. direction (str, optional): The direction to check. Options: 'up', 'down', 'left', 'right', 'up-left', 'up-right', 'down-left', 'down-right'. - + length (int, optional): The number of steps to check in the given direction. Default is 1. + Returns: - The value in the grid in the specified direction, or None if out of bounds. + list: A list of values in the grid for the specified direction and length. + Returns an empty list if any position is out of bounds. """ # Ensure the position is a set of two integers if len(position) != 2 or not all(isinstance(coord, int) for coord in position): @@ -111,8 +120,27 @@ def get_value_in_direction(grid, position, direction=None): dx, dy = offsets[direction] new_x, new_y = x + dx, y + dy - # Check for out-of-bounds, considering varying row lengths - if 0 <= new_x < len(grid) and 0 <= new_y < len(grid[new_x]): - return grid[new_x][new_y] + values = [] + + if length == 1: + # Check for out-of-bounds, considering varying row lengths + if 0 <= new_x < len(grid) and 0 <= new_y < len(grid[new_x]): + return grid[new_x][new_y] + else: + return None else: - return None \ No newline at end of file + for step in range(length): + print(step) + new_x, new_y = x + step * dx, y + step * dy + # Check for out-of-bounds, considering varying row lengths + if 0 <= new_x < len(grid) and 0 <= new_y < len(grid[new_x]): + values.append(grid[new_x][new_y]) + else: + return [] # Return empty list if any position is out of bounds + if type == 'list': + return values + elif type == 'str': + return ''.join(values) + else: + return values + \ No newline at end of file