2023 day1
This commit is contained in:
parent
d6fce584fd
commit
e07537d56d
2 changed files with 236 additions and 0 deletions
133
lib/2023_day1.ex
Normal file
133
lib/2023_day1.ex
Normal 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
103
lib/2023_day1.exs
Normal 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()
|
Loading…
Add table
Reference in a new issue