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

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?
# Read the input data from the file
input_text = File.read("input.txt").split("\n")

num_rows = input_text.length
num_cols = input_text[0].length
total = 0

# Helper function to count the occurrences of "XMAS"
def count_xmas_in_direction(str)
  str.scan(/XMAS/).length
end

# Check Rows (left to right and right to left)
input_text.each do |row|
  total += count_xmas_in_direction(row)
  total += count_xmas_in_direction(row.reverse)
end

# Check Columns (top to bottom and bottom to top)
(0...num_cols).each do |col_idx|
  col = input_text.map { |row| row[col_idx] }.join
  total += count_xmas_in_direction(col)
  total += count_xmas_in_direction(col.reverse)
end

# Check NE/SW Diagonals
(0...(num_rows + num_cols - 1)).each do |idx_sum|
  diagonal = (0...[num_rows, num_cols].min).map do |row_idx|
    if (idx_sum - row_idx).between?(0, num_cols - 1) && (row_idx).between?(0, num_rows - 1)
      input_text[row_idx][idx_sum - row_idx]
    else
      nil
    end
  end.join
  total += count_xmas_in_direction(diagonal)
  total += count_xmas_in_direction(diagonal.reverse)
end

# Check NW/SE Diagonals
(-num_cols + 1...(num_rows)).each do |idx_diff|
  diagonal = (0...[num_rows, num_cols].min).map do |row_idx|
    if (row_idx).between?(0, num_rows - 1) && (row_idx - idx_diff).between?(0, num_cols - 1)
      input_text[row_idx][row_idx - idx_diff]
    else
      nil
    end
  end.join
  total += count_xmas_in_direction(diagonal)
  total += count_xmas_in_direction(diagonal.reverse)
end

# Print the total number of occurrences
puts total