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