103 lines
1.7 KiB
Elixir
103 lines
1.7 KiB
Elixir
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()
|