Code Challenge: basic arithmic operations using only incrementation operator
public enum Operation
{
    Addition,
    Multiplication,
    Exponentation
}



If you gave these explicit values:

  public enum Operation
  {
    Addition = 1,
    Multiplication = 2,
    Exponentation = 3
  }


... you could avoid the + 1 for the operation:

  return Hyper(left, (int)operation, right);




Because Hyper(...) is private, and you are supposed to know how to use it, there is no need for checking the input values in there. It is safe to leave it to Evaluate(...) to do that:

public static int Evaluate(int left, int right, Operation operation)
{
  if (left &lt; 0) throw new ArgumentOutOfRangeException(nameof(left));
  if (right &lt; 0) throw new ArgumentOutOfRangeException(nameof(right));
  if (!Enum.IsDefined(typeof(Operation), operation)) throw new ArgumentOutOfRangeException(nameof(operation));

  return Hyper(left, (int)operation, right);
}


it is safe because:

  if (n == 0) return b + 1;
  if (b == 0) return n == 1 ? a : n == 2 ? 0 : 1;


will catch zeros for n and b while a never changes so no arguments will never be lesser than zero - as you can only decrement by one.



Personally I would change the order of b and n to be the same as for Evaluate(...):

static int Hyper(int a, int b, int n) {...}




All in all in my writing it would look like:

  public enum Operation
  {
    Addition = 1,
    Multiplication = 2,
    Exponentation = 3
  }

  public static class Expression
  {
    public static int Evaluate(int left, int right, Operation operation)
    {
      if (left &lt; 0) throw new ArgumentOutOfRangeException(nameof(left));
      if (right &lt; 0) throw new ArgumentOutOfRangeException(nameof(right));
      if (!Enum.IsDefined(typeof(Operation), operation)) throw new ArgumentOutOfRangeException(nameof(operation));

      return Hyper(left, right, (int)operation);
    }

    static int Hyper(int a, int b, int n)
    {
      if (n == 0) return b + 1;
      if (b == 0) return n == 1 ? a : n == 2 ? 0 : 1;

      return Hyper(a, Hyper(a, b - 1, n), n - 1);
    }
  }




More edge/test cases?



BtW Hyper() stack overflows relatively quickly: for instance for a == 8 and b == 5 for Exponentation.

An alternative algorithm could be the below "semi-recurs-iterative":

It has a recursive depth of max 3:

public static int HyperIter(int a, int b, int n)
{
  if (n == 1)
  {
    while (b &gt; 0)
    {
      a++;
      b--;
    }

    return a;
  }
  else
  {
    int res = n - 1;
    res--;
    while (b &gt; 0)
    {
      res = HyperIter(res, a, n - 1);
      b--;
    }

    return res;
  }
}


I'm though not sure if it completely satisfies the criteria of only using + 1, because it uses a local variable (res) and -- - but the original also uses - 1 in the recursive calls, so...?