Day 1
Section
Mix.install([
{:kino, "~> 0.11.3"}
])
Data
input = Kino.Input.textarea("Please paste your input file:")
Solutions
Part 1
Example data:
1abc2
pqr3stu8vwx
a1b2c3d4e5f
treb7uchet
In this example, the calibration values of these four lines are 12, 38, 15, and 77. Adding these together produces 142
.
input = Kino.Input.read(input)
defmodule Advent2023.Day01.Part1 do
@text_digits Enum.map(0..9, &{Integer.to_string(&1), &1}) |> Enum.into(%{})
def get_first_and_last_digit(text) do
text
|> String.split("", trim: true)
|> Enum.reduce({nil, 0}, &process_character/2)
end
def process_character(character, {nil, last}) do
maybe_digit = @text_digits[character]
if maybe_digit, do: {maybe_digit, maybe_digit}, else: {nil, last}
end
def process_character(character, {first, last}) do
maybe_digit = @text_digits[character]
if maybe_digit, do: {first, maybe_digit}, else: {first, last}
end
def add({nil, last}), do: last
def add({first, last}), do: first * 10 + last
def single_calibration(calibration) do
calibration
|> get_first_and_last_digit()
|> add()
end
def multiple_calibrations(calibration_list) do
calibration_list
|> Enum.reduce(0, fn sum, acc -> single_calibration(sum) + acc end)
end
end
input
|> String.splitter("\n", trim: true)
|> Advent2023.Day01.Part1.multiple_calibrations()
Part 2
Example:
two1nine
eightwothree
abcone2threexyz
xtwone3four
4nineeightseven2
zoneight234
7pqrstsixteen
In this example, the calibration values are 29, 83, 13, 24, 42, 14, and 76. Adding these together produces 281
.
defmodule Advent2023.Day01.Part2 do
@number_lookup %{
"one" => "1",
"two" => "2",
"three" => "3",
"four" => "4",
"five" => "5",
"six" => "6",
"seven" => "7",
"eight" => "8",
"nine" => "9",
"zero" => "0"
}
@text_digits Enum.map(0..9, &{Integer.to_string(&1), &1}) |> Enum.into(%{})
def get_matched_numbers(text) do
list_of_all_digits = Map.keys(@number_lookup) ++ Map.values(@number_lookup)
pattern = ~r/(?=(#{Enum.join(list_of_all_digits, "|")}))/i
Regex.scan(pattern, text)
end
def get_first_and_last_digit([]), do: {0, 0}
def get_first_and_last_digit(list) do
[_, first] = List.first(list)
[_, last] = List.last(list)
{numberize(first), numberize(last)}
end
def numberize(number_string) do
Map.get(@number_lookup, number_string, number_string)
|> String.to_integer()
end
def add({first, last}), do: first * 10 + last
def single_calibration(calibration) do
calibration
|> get_matched_numbers()
|> get_first_and_last_digit()
|> add()
end
def multiple_calibrations(calibration_list) do
calibration_list
|> Enum.reduce(0, fn sum, acc -> single_calibration(sum) + acc end)
end
end
# Advent2023.Day01.Part2.single_calibration("eightwothree")
input
|> String.splitter("\n", trim: true)
|> Advent2023.Day01.Part2.multiple_calibrations()