Another take:
def part1(), do: solve({0, 0})
def part2(), do: solve({0, 0, 0})
defp solve(seed) do
File.stream!(@path)
|> Stream.map(&parse_line/1)
|> Enum.reduce(seed, &process_cmd/2)
|> Tuple.product()
end
defp process_cmd({:forward, n}, {h, d}), do: {h+n, d}
defp process_cmd({:up, n}, {h, d}), do: {h, d-n}
defp process_cmd({:down, n}, {h, d}), do: {h, d+n}
defp process_cmd({:forward, n}, {h, d, a}), do: {h+n, d + (n * a), a}
defp process_cmd({:up, n}, {h, d, a}), do: {h, d, a-n}
defp process_cmd({:down, n}, {h, d, a}), do: {h, d, a+n}
defp parse_line(line) do
case String.trim(line) do
"forward " <> rest -> {:forward, String.to_integer(rest)}
"up " <> rest -> {:up, String.to_integer(rest)}
"down " <> rest -> {:down, String.to_integer(rest)}
end
end






















