Spaces:
Running
Running
def read_grid(filename): | |
with open(filename, 'r') as f: | |
return [line.strip() for line in f.readlines()] | |
def get_word_at(grid, x, y, dx, dy, length): | |
if not (0 <= x + (length-1)*dx < len(grid[0]) and 0 <= y + (length-1)*dy < len(grid)): | |
return "" | |
return ''.join(grid[y + i*dy][x + i*dx] for i in range(length)) | |
def count_xmas(grid): | |
directions = [ | |
(1,0), (0,1), (1,1), (-1,1), # right, down, diagonal-right, diagonal-left | |
(-1,0), (0,-1), (-1,-1), (1,-1) # left, up, diagonal-left-up, diagonal-right-up | |
] | |
count = 0 | |
for y in range(len(grid)): | |
for x in range(len(grid[0])): | |
for dx, dy in directions: | |
if get_word_at(grid, x, y, dx, dy, 4) == "XMAS": | |
count += 1 | |
return count | |
def check_xmas_pattern(grid, x, y): | |
# Check both diagonals for MAS or SAM | |
patterns = 0 | |
diagonals = [ | |
[(x-1, y-1), (x, y), (x+1, y+1)], # top-left to bottom-right | |
[(x+1, y-1), (x, y), (x-1, y+1)] # top-right to bottom-left | |
] | |
def is_valid_pos(pos): | |
return 0 <= pos[0] < len(grid[0]) and 0 <= pos[1] < len(grid) | |
def get_string(positions): | |
if not all(is_valid_pos(pos) for pos in positions): | |
return "" | |
return ''.join(grid[y][x] for x, y in positions) | |
for d1 in diagonals: | |
for d2 in diagonals: | |
if d1 == d2: | |
continue | |
s1 = get_string(d1) | |
s2 = get_string(d2) | |
if ((s1 == "MAS" or s1 == "SAM") and | |
(s2 == "MAS" or s2 == "SAM")): | |
patterns += 1 | |
return patterns // 2 # Each valid pattern is counted twice due to diagonal combinations | |
def count_xmas_patterns(grid): | |
total = 0 | |
for y in range(len(grid)): | |
for x in range(len(grid[0])): | |
total += check_xmas_pattern(grid, x, y) | |
return total | |
# Read input and solve both parts | |
grid = read_grid("input.txt") | |
# Part 1 | |
print(str(count_xmas(grid))) | |
# Part 2 | |
print(str(count_xmas_patterns(grid))) |