14 Dec 2023
Solución Advent of Code 2023 día 1
El problema puede encontrarse aquí: Advent of Code 2023 día 1.
Yo estoy resolviendo los ejercicios con Lua 5.4 actualmente, por lo que las soluciones estarán explicadas sobre ese lenguaje de programación.
Parte 1
Para resolver este ejercicio se necesita iterar a través de cada línea de la entrada del rompecabezas. En cada iteración hay que buscar 2 números, lo que yo hice fue buscar el primer dígito buscando caracter por caracter de izquierda a derecha, y luego el segundo dígito buscando caracter por caracter de derecha a izquierda.
Dicho esto, comenzamos declarando una función que obtenga la entrada del rompecabezas y convierta cada línea en un elemento de un array.
require "utils"
-- utils: Es una librería que contiene algunos pocas funciones útiles que no trae Lua por defecto
local function getInput()
local input = readFile("01input.txt") -- Obtenemos el string de la entrada
return splitString(input, lineDelimiter) -- Dividimos el string por la cantidad de líneas
end
Ahora solo se realiza la busca de los números de una línea para eso declaro una función foundCalibrationValue()
local function foundCalibrationValue(line, readWords)
local firstDigit = "" -- los digitos serían strings cuando los encontramos
local lastDigit = ""
-- Buscamos de izquierda a derecha el primer dígito
for i = 1, #line do
local char = line:sub(i, i)
if tonumber(char) ~= nil then
firstDigit = char
break
end
end
-- Buscamos de derecha a izquierda el segundo dígito
for i = #line, 1, -1 do
local char = line:sub(i, i)
if tonumber(char) ~= nil then
lastDigit = char
break
end
end
-- Devolvemos los dígitos concatenando primero y luego convirtiendolo a número
return tonumber(firstDigit .. lastDigit)
end
Ahora solo se itera por cada línea y se suman los números
local function answer1()
local lines = getInput()
local result = 0
for _, line in ipairs(lines) do
result = result + foundCalibrationValue(line)
end
return result
end
Parte 2
En la parte dos nos piden encontrar además de digitos números escritos, a esto solo le agregamos una condición a la función foundCalibrationValue para indicar que busque también esos números.
Para lograr esto, lo que pensé fue simplemente agregar los dígitos en caso de existir un número en palabra, debido a que los números se mezclan entre sí, para evitar inconvenientes se puede duplicar la palabra e insertar el dígito en medio, por ejemplo, si se encuentra la palabra “one”, cambiar esa palabra por “one1one” y se aplicaría luego lo mismo que la primera parte.
-- Declaramos una lista de las palabras a buscar
local numbers<const> = {"one", "two", "three", "four", "five", "six", "seven", "eight", "nine"}
local function foundCalibrationValue(line, readWords)
-- se agregaría lo siguiente:
local x, y = 0, 0 -- index de la primer letra y última letra de la palabra
if readWords then -- si se permite leer palabras
for i = 1, #numbers do -- iteramos a través de la lista de números
x, y = string.find(line, numbers[i]) -- Lua tiene una función que permite encontrar coincidencias
if x ~= nil and y ~= nil then
-- si se encuentra una palabra, se sustituye la palabra por "palabra#palabra"
line = line:gsub(numbers[i], string.sub(numbers[i], 1, 1) .. i .. string.sub(numbers[i], -1))
end
end
end
-- la búsqueda continúa como en la primera parte
return tonumber(firstDigit .. lastDigit)
end
Listo, ya solo adaptamos la solución 1 agregando false a la función y creamos la función para obtener la segunda parte.
local function answer1()
local lines = getInput()
local result = 0
for _, line in ipairs(lines) do
result = result + foundCalibrationValue(line, false)
end
return result
end
local function answer2()
local lines = getInput()
local result = 0
for _, line in ipairs(lines) do
result = result + foundCalibrationValue(line, true)
end
return result
end
print("Parte 1:", answer1())
print("Parte 2:", answer2())
Puede encontrar mi código completo aquí: Github.