euler_ex/problems/18/solution.livemd

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
```