82 lines
1.8 KiB
Markdown
82 lines
1.8 KiB
Markdown
# Project Euler 18 and 67
|
|
|
|
## Section
|
|
|
|
```elixir
|
|
defmodule PathSum do
|
|
defstruct data: %{}, depth: 0
|
|
def parse(input) do
|
|
data = input
|
|
|> String.trim()
|
|
|> String.split("\n")
|
|
|> Stream.with_index()
|
|
|> Stream.flat_map(fn {line, j} ->
|
|
line
|
|
|> String.split(" ")
|
|
|> Stream.map(&String.to_integer/1)
|
|
|> Stream.with_index()
|
|
|> Stream.map(fn {n, i} -> {{j, i}, n} end)
|
|
end)
|
|
|> Enum.into(%{})
|
|
|
|
%__MODULE__{
|
|
data: data,
|
|
depth: data |> Enum.max_by(fn {{x, _}, _} -> x end) |> elem(0) |> elem(0)
|
|
}
|
|
end
|
|
|
|
defmacro with_val(coord, tree) do
|
|
quote do
|
|
{ unquote(coord), Map.get(unquote(tree).data, unquote(coord)) }
|
|
end
|
|
end
|
|
|
|
def above({0, 0}, _), do: nil
|
|
def above({1, _}, tree), do: {0, 0} |> with_val(tree)
|
|
def above({n, 0}, tree), do: {n - 1, 0} |> with_val(tree)
|
|
def above({n, n}, tree), do: {n - 1, n - 1} |> with_val(tree)
|
|
def above({n, m}, tree), do: [{n - 1, m - 1} |> with_val(tree), {n - 1, m} |> with_val(tree)]
|
|
|
|
def best_path_to(tree, loc) do
|
|
case Process.get({tree, loc}) do
|
|
nil ->
|
|
best = case above(loc, tree) do
|
|
nil -> 0
|
|
{c, n} -> n + best_path_to(tree, c)
|
|
[{lloc, left}, {rloc, right}] ->
|
|
ll = left + best_path_to(tree, lloc)
|
|
rr = right + best_path_to(tree, rloc)
|
|
if ll > rr do
|
|
ll
|
|
else
|
|
rr
|
|
end
|
|
end
|
|
Process.put({tree, loc}, best)
|
|
best
|
|
n -> n
|
|
end
|
|
end
|
|
|
|
@doc """
|
|
|
|
## Example
|
|
iex> """
|
|
...> 3
|
|
...> 7 4
|
|
...> 2 4 6
|
|
...> 8 5 9 3
|
|
...> """ |>
|
|
...> PathSum.parse() |> PathSum.best_path()
|
|
23
|
|
"""
|
|
def best_path(tree) do
|
|
for {{x, _} = coord, n} <- tree.data,
|
|
x == tree.depth,
|
|
reduce: 0 do
|
|
best ->
|
|
max(best, n + best_path_to(tree, coord))
|
|
end
|
|
end
|
|
end
|
|
```
|