From 3b0cc79dee76244da55d2326cc4244a384d85e44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20Herg=C3=A8s?= Date: Sun, 9 Nov 2025 13:23:05 +0100 Subject: feat(calc)): supports factorial --- lib/elixir_math_parser.ex | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'lib/elixir_math_parser.ex') diff --git a/lib/elixir_math_parser.ex b/lib/elixir_math_parser.ex index f7f916f..863ecd8 100644 --- a/lib/elixir_math_parser.ex +++ b/lib/elixir_math_parser.ex @@ -10,9 +10,9 @@ defmodule ElixirMathParser do {:ok, value <~> 1} end - defp reduce_to_value({:var, _line, var}, state) do + defp reduce_to_value({:var, line, var}, state) do if !Map.has_key?(state, var) do - {:error, "value not found for " <> to_string(var)} + {:error, line, "value not found for " <> to_string(var)} else {:ok, state[var]} end @@ -46,9 +46,25 @@ defmodule ElixirMathParser do end end - defp evaluate_tree([{:assign, {:var, _line, lhs}, rhs} | tail], state) do + defp reduce_to_value({:factor_op, lhs}, state) do + with {:ok, op} <- reduce_to_value(lhs, state), + true <- Ratio.denominator(op) == 1, + true <- Ratio.numerator(op) >= 0 do + {:ok, factor(Ratio.numerator(op), 1)} + else + {:error, line, reason} -> {:error, line, reason} + false -> {:error, "must have a positive integer for the factorial"} + end + end + + defp factor(n, acc) when n > 0, do: factor(n - 1, acc * n) + defp factor(0, acc), do: acc + + defp evaluate_tree([{:assign, {:var, line, lhs}, rhs} | tail], state) do with {:ok, val} <- reduce_to_value(rhs, state) do evaluate_tree(tail, Map.merge(state, %{lhs => val})) + else + {:error, reason} -> {:error, line, reason} end end -- cgit v1.2.3