Advent of Code - Day 1
Mix.install([
{:kino_aoc, "~> 0.1"}
])
Introduction
–> Content
Puzzle
{:ok, puzzle_input} =
KinoAOC.download_puzzle("2023", "1", System.fetch_env!("LB_AOC_SESSION"))
Parser
Code - Parser
defmodule Parser do
def parse(input) do
end
end
Tests - Parser
ExUnit.start(autorun: false)
defmodule ParserTest do
use ExUnit.Case, async: true
import Parser
@input ""
@expected nil
test "parse test" do
actual = parse(@input)
assert actual == @expected
end
end
ExUnit.run()
Part One
Code - Part 1
defmodule PartOne do
def solve(input) do
IO.puts("--- Part One ---")
IO.puts("Result: #{run(input)}")
end
def run(input) do
input_list = String.split(input, "\n", trim: true)
Enum.map(input_list, fn string ->
extract_value(string)
end)
|> Enum.sum()
end
defp extract_value(string) do
digits = Regex.scan(~r/\d/, string)
first = hd(digits) |> hd()
last = List.last(digits) |> hd()
(first <> last) |> String.to_integer()
end
end
Tests - Part 1
ExUnit.start(autorun: false)
defmodule PartOneTest do
use ExUnit.Case, async: true
import PartOne
@input """
1abc2
pqr3stu8vwx
a1b2c3d4e5f
treb7uchet
"""
@expected 142
test "simple example" do
actual = run(@input)
assert actual == @expected
end
end
ExUnit.run()
Solution - Part 1
PartOne.solve(puzzle_input)
String.split(puzzle_input, "\n", trim: true)
Part Two
Code - Part 2
defmodule PartTwo do
def solve(input) do
IO.puts("--- Part Two ---")
IO.puts("Result: #{run(input)}")
end
def run(input) do
input_list = String.split(input, "\n", trim: true)
Enum.map(input_list, fn string ->
IO.puts(string <> " : " <> Integer.to_string(extract_value(string)))
extract_value(string)
end)
|> Enum.sum()
end
defp extract_value(string) do
matches = Regex.scan(~r/(?=(\d|zero|one|two|three|four|five|six|seven|eight|nine))/, string)
first = hd(matches) |> List.last() |> convert_word_to_digit()
last = List.last(matches) |> List.last() |> convert_word_to_digit()
(first <> last) |> String.to_integer()
end
@word_to_digit %{
"zero" => "0",
"one" => "1",
"two" => "2",
"three" => "3",
"four" => "4",
"five" => "5",
"six" => "6",
"seven" => "7",
"eight" => "8",
"nine" => "9"
}
defp convert_word_to_digit(string) do
@word_to_digit[string] || string
end
end
Tests - Part 2
ExUnit.start(autorun: false)
defmodule PartTwoTest do
use ExUnit.Case, async: true
import PartTwo
@input """
two1nine
eightwothree
abcone2threexyz
xtwone3four
4nineeightseven2
zoneight234
7pqrstsixteen
"""
@expected 281
test "part two" do
actual = run(@input)
assert actual == @expected
end
test "overlapping strings" do
actual = run("sevenine")
assert actual == 79
end
end
ExUnit.run()
Solution - Part 2
PartTwo.solve(puzzle_input)