-- see if the file exists local function file_exists(file) local f = io.open(file, "rb") if f then f:close() end return f ~= nil end -- get all lines from a file, returns an empty -- list/table if the file does not exist local function lines_from(file) if not file_exists(file) then return {} end local lines = {} for line in io.lines(file) do lines[#lines + 1] = line end return lines end -- tests the functions above local file = "input" local lines = lines_from(file) -- Solution Starts here local target = "XMAS" ---@diagnostic disable-next-line: redefined-local local function count_xmas_at_index(lines, line_idx, char_idx) local count = 0 local line = lines[line_idx] local test_words = {} -- Forward test_words[#test_words + 1] = line:sub(char_idx, char_idx + 3) -- Backward test_words[#test_words + 1] = line:sub(char_idx - 3, char_idx):reverse() local up_right = "" local down_right = "" local up_left = "" local down_left = "" local up = "" local down = "" for offset = 0, 3 do local up_idx = line_idx - offset local down_idx = line_idx + offset local right_idx = char_idx + offset local left_idx = char_idx - offset if up_idx >= 1 then up = up .. lines[up_idx]:sub(char_idx, char_idx) up_right = up_right .. lines[up_idx]:sub(right_idx, right_idx) up_left = up_left .. lines[up_idx]:sub(left_idx, left_idx) end if down_idx <= #lines then down = down .. lines[down_idx]:sub(char_idx, char_idx) down_right = down_right .. lines[down_idx]:sub(right_idx, right_idx) down_left = down_left .. lines[down_idx]:sub(left_idx, left_idx) end end test_words[#test_words + 1] = up_right test_words[#test_words + 1] = down_right test_words[#test_words + 1] = up_left test_words[#test_words + 1] = down_left test_words[#test_words + 1] = up test_words[#test_words + 1] = down for _, v in ipairs(test_words) do if v == target then count = count + 1 end end return count end local xmas_count = 0 -- print all line numbers and their contents ---@diagnostic disable-next-line: unused-local for line_idx, line in ipairs(lines) do for char_idx in line:gmatch("()X") do xmas_count = xmas_count + count_xmas_at_index(lines, line_idx, char_idx) end end io.output():write(xmas_count)