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