94 lines
2.2 KiB
Lua
94 lines
2.2 KiB
Lua
-- 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)
|