Module:User:Cscott/Advent Of Code 2023/Day 3 Explained

return (functionlocal builders = local function register(name, f) builders[name] = fendregister('advent.compat', function return require end)

register('day3', function(myrequire)--Day 1, first part; advent of code 2023--

local compat = myrequire('advent.compat')--local inspect = require 'inspect'

--Infrastructure--

function split(str) lines = for s in string.gmatch(str, "[^\r\n]+") do table.insert(lines, s) end return linesend

function part1(frame) local s = frame:expandTemplate return day1a(split(s))end

function part2(frame) local s = frame:expandTemplate return day1b(split(s))end

--Part 1--

function make_graph(lines) local graph = for row = 1,#lines do local l = lines[row] graph[row] = for col = 1,#l do graph[row][col] = l:sub(col, col) end end return graph, #graph, #(graph[1])end

function is_symbol(c) return c:match("[0-9.]")

nilendfunction is_digit(c) return not (c:match("[0-9]")

nil)endfunction char_at(graph, row, col) if row < 1 then return "." elseif row > #graph then return "." end r = graph[row] if col < 1 then return "." elseif col > #r then return "." end return r[col]end

function symbol_around(graph, row, col) for r = row-1, row+1 do for c = col-1, col+1 do if is_symbol(char_at(graph, r, c)) then return true end end end return falseend

function day1a(lines) local graph, rows, cols = make_graph(lines) -- look for numbers local in_number = false local seen_symbol = false local seen_number = "" local sum = 0 for row = 1, rows do for col = 1, cols do local c = graph[row][col] if in_number then if is_digit(c) then -- continue our number seen_number = seen_number .. c seen_symbol = seen_symbol or symbol_around(graph, row, col) else -- finish our number --print("Found", seen_number, seen_symbol) in_number = false if seen_symbol then local n = 0 + seen_number -- coerce to int sum = sum + n end end else -- not in_number, see if we want to start one if is_digit(c) then in_number = true seen_number = c seen_symbol = symbol_around(graph, row, col) end end end end return sumend

--Part 2!--

function gears_around(graph, row, col) gears = for r = row-1, row+1 do for c = col-1, col+1 do if char_at(graph, r, c)

"*" then if gears[r]

nil then gears[r] = end gears[r][c] = true end end end return gearsend

function day1b(lines) local graph, rows, cols = make_graph(lines) -- look for numbers local in_number = false local seen_gears = local seen_number = "" local number_for_gear =

for row = 1, rows do for col = 1, cols do local c = graph[row][col] if in_number then if is_digit(c) then -- continue our number seen_number = seen_number .. c for r,row in pairs(gears_around(graph, row, col)) do for c,_ in pairs(row) do if seen_gears[r]

nil then seen_gears[r] = end seen_gears[r][c] = true end end else -- finish our number -- print("Found", seen_number, inspect(seen_gears)) in_number = false local n = 0 + seen_number -- coerce to int for r,row in pairs(seen_gears) do for c,_ in pairs(row) do if number_for_gear[r]

nil then number_for_gear[r] = end if number_for_gear[r][c]

nil then number_for_gear[r][c] = end table.insert(number_for_gear[r][c], n) end end end else -- not in_number, see if we want to start one if is_digit(c) then in_number = true seen_number = c seen_gears = gears_around(graph, row, col) end end end end -- okay, now find gears bordering exactly two numbers local sum = 0 for r,row in pairs(number_for_gear) do for c,nums in pairs(row) do if #nums > 2 then -- print("Found",#nums,":",inspect(nums),"???") elseif #nums

2 then sum = sum + (nums[1] * nums[2]) end end end return sumend

--Testing--

--print(inspect(day1a(split(io.input("day3.example"):read("a")))))--print(inspect(day1a(split(io.input("day3.input"):read("a")))))

--print(inspect(day1b(split(io.input("day3.example"):read("a")))))--print(inspect(day1b(split(io.input("day3.input"):read("a")))))

return

end)

local modules = modules['table'] = require('table')modules['string'] = require('string')modules['strict'] = local function myrequire(name) if modules[name]