2023 day1

This commit is contained in:
Caleb Webber 2023-12-02 02:13:16 -05:00
parent d6fce584fd
commit e07537d56d
2 changed files with 236 additions and 0 deletions

133
lib/2023_day1.ex Normal file
View file

@ -0,0 +1,133 @@
defmodule Day1_2024 do
def solve(input) do
input
|> Enum.filter(&(String.length(&1) > 0))
|> Enum.reduce(
0,
fn line, acc ->
acc + parse_number(line)
end
)
end
def parse_number(line) do
left_number = find_first_number(line)
right_number = find_first_number_from_right(line)
left_number * 10 + right_number
end
def find_first_number(l) do
1..(l |> String.length())
|> Enum.reduce_while(
0,
fn i, _ ->
int_at_pos = l |> String.at(i - 1) |> Integer.parse()
case int_at_pos do
:error ->
l
|> String.slice(0, i)
|> search_for_written_number()
|> then(fn res ->
case res do
nil -> {:cont, 0}
n -> {:halt, n}
end
end)
n ->
{:halt, n |> elem(0)}
end
end
)
end
def find_first_number_from_right(l) do
len = String.length(l)
1..len
|> Enum.reduce_while(
0,
fn i, _ ->
cur_char = l |> String.at(len - i)
IO.puts("examining ")
IO.puts(cur_char)
int_at_pos = cur_char |> Integer.parse()
case int_at_pos do
:error ->
l
|> String.slice(len - i, len)
|> search_for_written_number()
|> then(fn res ->
case res do
nil -> {:cont, 0}
n -> {:halt, n}
end
end)
{n, _} ->
{:halt, n}
end
end
)
end
def search_for_written_number(line) do
IO.puts("searching " <> line)
numbers = [
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine"
]
numbers_map = %{
"one" => 1,
"two" => 2,
"three" => 3,
"four" => 4,
"five" => 5,
"six" => 6,
"seven" => 7,
"eight" => 8,
"nine" => 9
}
if String.length(line) < 3 do
nil
else
splits =
numbers
|> Enum.map(fn number ->
split = String.split(line, number)
{number, split |> Enum.map(&(&1 |> String.length()))}
end)
|> Enum.filter(&(&1 |> elem(1) |> Enum.count() > 1))
IO.puts(inspect(splits))
number_word =
splits
|> Enum.sort_by(fn split ->
split |> elem(1) |> List.first()
end)
|> Enum.at(0)
res =
if is_tuple(number_word) do
Map.get(numbers_map, number_word |> elem(0))
else
nil
end
res
end
end
end

103
lib/2023_day1.exs Normal file
View file

@ -0,0 +1,103 @@
defmodule Day1 do
@numbers [
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine"
]
def read_calibration_values(s) do
IO.puts(s)
[scan_left_for_number(s), scan_right_for_number(s)]
end
def if_nil_cont(u) do
case u do
nil -> {:cont, nil}
o -> {:halt, o}
end
end
def index_of(haystack, needle) do
len = String.length(haystack)
haystack
|> String.split(needle)
|> Enum.at(0)
|> then(fn x ->
case x do
len -> :error
n -> n
end
end)
end
def search_number_word(s) do
@numbers
|> Enum.with_index()
|> Stream.transform(
[],
fn {number, index}, acc ->
case index_of(s, number) do
:error -> acc
n -> [{index + 1, n} | acc]
end
end
)
|> Enum.sort_by(&(&1 |> elem(1)))
|> Enum.at(0)
end
def find_number(s) do
s
|> String.last()
|> Integer.parse()
|> then(fn u ->
case u do
:error -> search_number_word(s)
{i, _} -> i
end
end)
end
def scan_left_for_number(s) do
len = String.length(s)
0..len
|> Enum.reduce_while(
0,
&(find_number(s |> String.slice(0..&1)) |> if_nil_cont())
)
|> Enum.reduce(
0,
&(&1 + &2)
)
end
defp scan_right_for_number(s) do
len = String.length(s)
0..(len - 1)
|> Enum.reduce_while(
0,
&(find_number(s |> String.slice((-1 - &1)..-1)) |> if_nil_cont())
)
|> Enum.reduce(
0,
&(&1 + &2)
)
end
end
for line <- IO.stream(), reduce: 0 do
acc ->
line |> IO.puts()
[first, last] = line |> Day1.read_calibration_values()
acc + (first * 10 + last)
end
|> IO.puts()