2024-12-04
— 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?
Ruby:
# # 3 3 3 # 2 2 2 # 1 1 1 # 3 2 1 X 1 2 3 # 1 1 1 # 2 2 2 # 3 3 3 sum = 0 class Node attr_accessor :x, :y, :value def initialize(x,y,value) self.x = x self.y = y self.value = value end def to_s self.value end end def up(nodes, x,y) return "" if y < 3 nodes[y - 1][x].to_s + nodes[y - 2][x].to_s + nodes[y - 3][x].to_s end def down(nodes, x,y) return "" if y >= nodes.size - 3 nodes[y + 1][x].to_s + nodes[y + 2][x].to_s + nodes[y + 3][x].to_s end def left(nodes, x,y) return "" if x < 3 nodes[y][x - 1].to_s + nodes[y][x - 2].to_s + nodes[y][x - 3].to_s end def right(nodes, x,y) return "" if x >= nodes[0].size - 3 nodes[y][x + 1].to_s + nodes[y][x + 2].to_s + nodes[y][x + 3].to_s end def top_left(nodes, x,y) return "" if y < 3 || x < 3 nodes[y - 1][x - 1].to_s + nodes[y - 2][x - 2].to_s + nodes[y - 3][x - 3].to_s end def top_right(nodes, x,y) return "" if x >= nodes[0].size - 3 || y < 3 nodes[y - 1][x + 1].to_s + nodes[y - 2][x + 2].to_s + nodes[y - 3][x + 3].to_s end def bottom_right(nodes, x,y) return "" if x >= nodes[0].size - 3 || y >= nodes.size - 3 nodes[y + 1][x + 1].to_s + nodes[y + 2][x + 2].to_s + nodes[y + 3][x + 3].to_s end def bottom_left(nodes, x,y) return "" if x < 3 || y >= nodes.size - 3 nodes[y + 1][x - 1].to_s + nodes[y + 2][x - 2].to_s + nodes[y + 3][x - 3].to_s end nodes = [] x_nodes = [] y = 0 File.readlines("input.txt").each do |line| tmp = [] line.chop.split("").each_with_index do |val, i| new_node = Node.new(i, y, val) x_nodes << new_node if new_node.value == "X" tmp << new_node end nodes << tmp y += 1 end p x_nodes x_nodes.each do |x| sum += 1 if up(nodes, x.x, x.y) == "MAS" sum += 1 if down(nodes, x.x, x.y) == "MAS" sum += 1 if left(nodes, x.x, x.y) == "MAS" sum += 1 if right(nodes, x.x, x.y) == "MAS" sum += 1 if top_left(nodes, x.x, x.y) == "MAS" sum += 1 if top_right(nodes, x.x, x.y) == "MAS" sum += 1 if bottom_left(nodes, x.x, x.y) == "MAS" sum += 1 if bottom_right(nodes, x.x, x.y) == "MAS" end p sum
— Part Two —
The Elf looks quizzically at you. Did you misunderstand the assignment?
Looking for the instructions, you flip over the word search to find that this isn't actually an XMAS puzzle; it's an X-MAS puzzle in which you're supposed to find two MAS in the shape of an X. One way to achieve that is like this:
M.S .A. M.S
Irrelevant characters have again been replaced with . in the above diagram. Within the X, each MAS can be written forwards or backwards.
Here's the same example from before, but this time all of the X-MASes have been kept instead:
.M.S...... ..A..MSMS. .M.S.MAA.. ..A.ASMSM. .M.S.M.... .......... S.S.S.S.S. .A.A.A.A.. M.M.M.M.M. ..........
In this example, an X-MAS appears 9 times.
Flip the word search from the instructions back over to the word search side and try again. How many times does an X-MAS appear?
sum = 0 class Node attr_accessor :x, :y, :value def initialize(x,y,value) self.x = x self.y = y self.value = value end def to_s self.value end end def top_left(nodes, x,y) return "" if y < 1 || x < 1 nodes[y - 1][x - 1].to_s end def top_right(nodes, x,y) return "" if x >= nodes[0].size - 1 || y < 1 nodes[y - 1][x + 1].to_s end def bottom_right(nodes, x,y) return "" if x >= nodes[0].size - 1 || y >= nodes.size - 1 nodes[y + 1][x + 1].to_s end def bottom_left(nodes, x,y) return "" if x < 1 || y >= nodes.size - 1 nodes[y + 1][x - 1].to_s end nodes = [] a_nodes = [] y = 0 File.readlines("input.txt").each do |line| tmp = [] line.chop.split("").each_with_index do |val, i| new_node = Node.new(i, y, val) a_nodes << new_node if new_node.value == "A" tmp << new_node end nodes << tmp y += 1 end p a_nodes a_nodes.each do |x| d1 = false d2 = false tmp = "" tmp += top_left(nodes, x.x, x.y) tmp += "A" tmp += bottom_right(nodes, x.x, x.y) d1 = (tmp == "MAS" or tmp == "SAM") tmp = "" tmp += top_right(nodes, x.x, x.y) tmp += "A" tmp += bottom_left(nodes, x.x, x.y) d2 = (tmp == "MAS" or tmp == "SAM") sum += 1 if d1 && d2 end p sum