Skip to content

Instantly share code, notes, and snippets.

@therubyhound
Created December 5, 2024 23:08
Show Gist options
  • Save therubyhound/e5f4e106433ba9526ea1f81a8f414416 to your computer and use it in GitHub Desktop.
Save therubyhound/e5f4e106433ba9526ea1f81a8f414416 to your computer and use it in GitHub Desktop.
Advent of Code 2024, Day 4
require "minitest/autorun"
INPUT = DATA.read
class WordSearch
attr_reader :grid
def initialize(input)
@grid = parse input
@max_row = grid.count - 1
@max_col = grid[0].count - 1
end
def xmas_count
grid.each_index.sum do |row|
grid[row].each_index.sum do |col|
grid[row][col] == "X" ? find_words_around(row, col) : 0
end
end
end
def mas_count
count = 0
(1..@max_row - 1).each do |row|
(1..@max_col - 1).each do |col|
next unless grid[row][col] == "A"
count += 1 if x_positions(row, col).all? { |line| line == "MAS" || line.reverse == "MAS" }
end
end
count
end
private
def parse(input)
input.split("\n").map { |letters| letters.split("") }
end
def find_words_around(row, column)
directions.count { |row_dir, col_dir| found?(row, column, row_dir, col_dir) }
end
def found?(row, column, row_dir, col_dir)
substring = ""
letter = Enumerator.new { |yielder| "XMAS".each_char { |char| yielder << char } }
while valid_position?(row, column) && letter.next == grid[row][column]
substring += grid[row][column]
return true if substring == "XMAS"
row += row_dir
column += col_dir
end
return false
end
def directions
[[-1, -1], [0, -1], [1, -1], [-1, 0], [1, 0], [-1, 1], [0, 1], [1, 1]]
end
def x_positions(row, col)
[
[grid[row - 1][col - 1], "A", grid[row + 1][col + 1]].join,
[grid[row - 1][col + 1], "A", grid[row + 1][col - 1]].join
]
end
def valid_position?(row, column)
row.between?(0, @max_row) && column.between?(0, @max_col)
end
end
BLUE = "\e[34m"
YELLOW = "\e[33m"
RESET = "\e[0m"
word_search = WordSearch.new(File.read(ARGV[0]))
puts "#{BLUE}XMAS Count:#{RESET} #{YELLOW}#{word_search.xmas_count}#{RESET}"
puts "#{BLUE}MAS Count:#{RESET} #{YELLOW}#{word_search.mas_count}#{RESET}"
class WordSearchTest < Minitest::Test
def setup
@word_search = WordSearch.new(INPUT)
end
def test_xmas_count
assert_equal 18, @word_search.xmas_count
end
def test_mas_count
assert_equal 9, @word_search.mas_count
end
def test_grid
expected = [
%w(M M M S X X M A S M),
%w(M S A M X M S M S A),
%w(A M X S X M A A M M),
%w(M S A M A S M S M X),
%w(X M A S A M X A M M),
%w(X X A M M X X A M A),
%w(S M S M S A S X S S),
%w(S A X A M A S A A A),
%w(M A M M M X M M M M),
%w(M X M X A X M A S X),
]
assert_equal expected, @word_search.grid
end
end
__END__
MMMSXXMASM
MSAMXMSMSA
AMXSXMAAMM
MSAMASMSMX
XMASAMXAMM
XXAMMXXAMA
SMSMSASXSS
SAXAMASAAA
MAMMMXMMMM
MXMXAXMASX
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment