Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How could I use linq when calculating a answer from a symbol and two numbers

Tags:

c#

linq

Recently I had an interview which asked to write a method to calculate the answer from a prefix formatted string.

The feedback from the interview was that I should have used Linq

I am a bit confused where I should have used linq and was wondering if anyone could help me.

The Problem

The signature method should be:

int Calculate(string expression)

I didn't need to validate the input but was given some examples of

  • "+ 3 4" should give 7
  • "- 2 10" should give -8
  • "* 10 -20" should give -200
  • "/ 6 2" should give 3

My Solution - from memory

So I created unit tests and developed the code in a TDD manor

[TestFixture]
public class UnitTest1
{
    [Test]
    public void TestMethod_Add()
    {
        var calculator = new Calculator();
        var result = calculator.Calculate("+ 4 2");
        var expected = 6;

        Assert.AreEqual(expected, result);
    }

    [Test]
    public void TestMethod_Sub()
    {
        var calculator = new Calculator();
        var result = calculator.Calculate("- 2 10");
        var expected = -8;

        Assert.AreEqual(expected, result);
    }

    [Test]
    public void TestMethod1_mult()
    {

        var calculator = new Calculator();
        var result = calculator.Calculate("* 10 -20");
        var expected = -200;

        Assert.AreEqual(expected, result);
    }

    [Test]
    public void TestMethod1_div()
    {
        var calculator = new Calculator();
        var result = calculator.Calculate("/ 6 2");
        var expected = 3;

        Assert.AreEqual(expected, result);
    }

and created the follow code something like this:

public class Calculator
{
    public int Calculate(string expression)
    {
        var tokens = expression.Split(' ');

        var symbol = tokens[0];
        var num1 = int.Parse(tokens[1]);
        var num2 = int.Parse(tokens[2]);

        switch (symbol)
        {
            case "+":
                return num1 + num2;

            case "-":
                return num1 - num2;

            case "*":
                return num1 * num2;

            case "/":
                return num1 / num2;
            default:
                throw new NotImplementedException("Symbol has not been implemented");
        }

    }
}
like image 515
I Bowyer Avatar asked Dec 11 '22 17:12

I Bowyer


2 Answers

This is as much LINQ as I can stuff into it:

int Calculate(string expression) {
    var operations = new Dictionary<char, Func<int, int, int>> {
        { '+', (a, b) => a + b },
        { '-', (a, b) => a - b },
        { '*', (a, b) => a * b },
        { '/', (a, b) => a / b },
    };
    return expression
        .Substring(2)
        .Split(' ')
        .Select(o => int.Parse(o))
        .Aggregate(operations[expression[0]])
    ;
}

As an added bonus, this can effortlessly handle such expressions as "* 1 2 3 4 5" (5!, which as we all know is 120) or "/ 1729 7 13 19" (in case you like to do your factoring in reverse).

This is half in jest. I would not consider this an appropriate implementation in production for a Calculate method that explicitly has to handle only two values. If your interviewer was just looking for how clever you could make something, though, this could have scored you points. (And if they were just looking for how clever you could make something for a trivial problem, be glad you didn't get the job -- maintenance at that company could be a bad thing.)

(Note to self: figure out some really neat way to split the string using SelectMany somehow.)

like image 97
Jeroen Mostert Avatar answered May 13 '23 13:05

Jeroen Mostert


Maybe they wanted to see something like this (but I like your answer ;-) )

int Calculate(string expression)
    {
        char symbol = expression.First();
        int[] numbers = Array.ConvertAll(expression.Substring(2).Split(' '), p => int.Parse(p)); 

        switch (symbol)
        {
            case '+':
                return numbers.Aggregate((a, b) => a + b);
            case '-':
                return numbers.Aggregate((a, b) => a - b);
            case '*':
                return numbers.Aggregate((a, b) => a * b);
            case '/':
                return numbers.Aggregate((a, b) => a / b);
            default:
                return 0;
        }
    }
like image 23
schlonzo Avatar answered May 13 '23 14:05

schlonzo