Day 1: Trebuchet?!
Mix.install([:kino])
input = Kino.Input.textarea("Please paste your input:")
Part 1
https://adventofcode.com/2023/day/1
data =
input
|> Kino.Input.read()
|> String.split("\n", trim: true)
data
|> Enum.map(fn calibration ->
only_number_string = Regex.replace(~r/[^\d]/, calibration, "")
"#{only_number_string |> String.at(0)}#{only_number_string |> String.at(-1)}"
|> String.to_integer()
end)
|> Enum.sum()
Part 2
https://adventofcode.com/2023/day/1#part2
defmodule Day01.Part2.Solve1 do
@number_words ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine"]
@number_strings 1..9 |> Enum.map(&Integer.to_string/1)
@number_matches (@number_words |> Enum.with_index(1)) ++ (@number_strings |> Enum.with_index(1))
def recover(calibration) do
do_recover(calibration, [])
|> Enum.reverse()
|> then(&("#{List.first(&1)}#{List.last(&1)}" |> String.to_integer()))
end
defp do_recover("", result) do
result
end
defp do_recover(string, result) do
new_result =
@number_matches
|> Enum.find_value(fn {number_match, number} ->
if string |> String.starts_with?(number_match) do
number
end
end)
|> case do
nil -> result
number -> [number | result]
end
do_recover(string |> String.slice(1..-1), new_result)
end
end
data
|> Enum.map(fn calibration ->
Day01.Part2.Solve1.recover(calibration)
end)
|> Enum.sum()
defmodule Day01.Part2.Solve2 do
@number_words ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine"]
@number_strings 1..9 |> Enum.map(&Integer.to_string/1)
@number_matches (@number_words |> Enum.with_index(1)) ++ (@number_strings |> Enum.with_index(1))
def recover(calibration) do
do_recover(calibration, [])
|> then(&("#{List.first(&1)}#{List.last(&1)}" |> String.to_integer()))
end
defp do_recover("", result) do
result
end
defp do_recover(string, result) do
new_result =
@number_matches
|> Enum.find_value(fn {number_match, number} ->
if string |> String.starts_with?(number_match) do
number
end
end)
|> case do
nil -> result
number -> (result |> Enum.slice(0..0)) ++ [number]
end
do_recover(string |> String.slice(1..-1), new_result)
end
end
data
|> Enum.map(fn calibration ->
Day01.Part2.Solve2.recover(calibration)
end)
|> Enum.sum()
defmodule Day01.Part2.Solve3 do
@number_words ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine"]
@number_strings 1..9 |> Enum.map(&Integer.to_string/1)
@number_matches (@number_words |> Enum.with_index(1)) ++ (@number_strings |> Enum.with_index(1))
def recover(calibration) do
[
{&String.starts_with?/2, 1..-1},
{&String.ends_with?/2, 0..-2}
]
|> Enum.map(fn {match_fun, range} ->
do_recover(calibration, match_fun, range)
end)
|> then(fn [first, last] -> "#{first}#{last}" |> String.to_integer() end)
end
defp do_recover(string, match_fun, range) do
@number_matches
|> Enum.find_value(fn {number_match, number} ->
if string |> match_fun.(number_match) do
number
end
end)
|> case do
nil -> do_recover(string |> String.slice(range), match_fun, range)
number -> number
end
end
end
data
|> Enum.map(fn calibration ->
Day01.Part2.Solve3.recover(calibration)
end)
|> Enum.sum()