Created
December 5, 2024 23:08
-
-
Save therubyhound/e5f4e106433ba9526ea1f81a8f414416 to your computer and use it in GitHub Desktop.
Advent of Code 2024, Day 4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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