Solved 2024/04 P1 + P2

This commit is contained in:
FrederikBaerentsen 2024-12-04 20:53:21 +01:00
parent 0d35287000
commit 68d3e12001
8 changed files with 229 additions and 30 deletions

17
2024/03/notes.txt Normal file
View File

@ -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\(\))

View File

@ -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+)\))
# instead of finding all the mul/do/don't and then turning calculation on/off.

View File

@ -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)

104
2024/04/4.md Normal file
View File

@ -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).

66
2024/04/solution.py Normal file
View File

@ -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)

View File

@ -5,6 +5,9 @@
.--'~ ~ ~| .-' * \ / '-. 1 **
.--'~ ,* ~ | | >o< \_\_\|_/__/ | 2 **
.---': ~ '(~), ~| | >@>O< o-_/.()__------| 3 **
|@..@'. ~ " ' ~ | |>O>o<@< \____ .'| 4 **
## 2023
. * ~~~~ /\ ' . 14

Binary file not shown.

46
fred.py
View File

@ -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
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