HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMajor

PI Calculator, Interview Challenge

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
interviewcalculatorchallenge

Problem

Greg Beech says here that he asks C# candidates to produce a formula that calculates PI Given that Pi can be estimated using the function \$4 * (1 - \frac{1}{3} + \frac{1}{5} - \frac{1}{7} + \dots)\$.

I'm far from C# interview ready, but I like the challenge. Here is my attempt at the formula. Let me know if there is a better way to do it.

using System;

class MainApp 
{
    static void Main () 
    {
        double number = 0;
        double pi;
        int i = 1;

        do 
        {
            if ((i/2) % 2 == 0)
            {
                number += (double)(1) / i;
            }
            else
            {
                number -= (double)(1) / i;
            }
            pi = 4 * number;
            i += 2;
        } while (Math.Round(pi,5) != 3.14159);

        Console.Clear();
        Console.WriteLine("Pi can be found using the formula 4 * (1 - 1/3 + 1/5 - 1/7 + ...) with {0} iterations.\n" +
        "At this point 4 is multiplied by: {1} to get {2}\n" +
        "This Rounds up to: {3}",i,number,pi,Math.Round(pi,5));
        Console.ReadKey();
    }
}

Solution

In an interview it usually doesn't matter if you actually solve the problem. What is most important is the way you (try to) solve it. If they don't tell you it should be the possibly fastest solution ever you should not optimize it prematurely but instead show that you know how to write SOLID code like encapsulate propertly, make the code testable etc. show that you know the techniques.

Here you could split the logic up into multiple methods for example you could have one generating the alternating sequence [1, -3, 5, -7, 9, -11, ...] that you can validate with a test:

public static IEnumerable AlternatingSequence()
{
    var i = 1;
    yield return i;
    var b = false;
    while (true) yield return ((b = !b) ? -1 : 1) * (i = i + 2);
}


then you can work on the PI itself and use it for the actual calculation which is then as simple as a LINQ expression:

public static double EstimatePI(int sumLength) 
{
    return (4 * AlternatingSequence().Take(sumLength).Sum(x => 1.0 / x));
}

var pi = EstimatePI(500_000).Dump(); // 3,14159065358969


There's all kind of stuff you can show you are familiar with in this simple task like DI or strategy pattern:

public static double EstimatePI(int sumLength, IEnumerable sequenceGenerator) 
{
    return (4 * sequenceGenerator.Take(sumLength).Sum(x => 1.0 / x));
}

var pi = EstimatePI(500_000, AlternatingSequence);


or even more advanced DI and encapsulation

class PiCalculator
{ 
    private readonly IEnumerable _sequenceGenerator;

    public PiCalculator(IEnumerable sequenceGenerator)
    {
        _sequenceGenerator = sequenceGenerator;
    }

    public double EstimatePi(int sumLength)
    {
        ...
    }
}


or you can add an interface to show you know what abstraction means:

interface IPiCalculator
{ 
    double EstimatePi(int sumLength);
}


Is this an overkill? It might be but it shows me that you are able to write modular and testable code. Writing short code is a good thing too but if you write only five lines inside a Main in a job interview, you'll go home without any prospects of getting the job. Again, in an inteview you should sell your coding skills and not show how smart you are in solving something with a fewest possible lines of code that no one can verify.

Code Snippets

public static IEnumerable<int> AlternatingSequence()
{
    var i = 1;
    yield return i;
    var b = false;
    while (true) yield return ((b = !b) ? -1 : 1) * (i = i + 2);
}
public static double EstimatePI(int sumLength) 
{
    return (4 * AlternatingSequence().Take(sumLength).Sum(x => 1.0 / x));
}

var pi = EstimatePI(500_000).Dump(); // 3,14159065358969
public static double EstimatePI(int sumLength, IEnumerable<int> sequenceGenerator) 
{
    return (4 * sequenceGenerator.Take(sumLength).Sum(x => 1.0 / x));
}

var pi = EstimatePI(500_000, AlternatingSequence);
class PiCalculator
{ 
    private readonly IEnumerable<int> _sequenceGenerator;

    public PiCalculator(IEnumerable<int> sequenceGenerator)
    {
        _sequenceGenerator = sequenceGenerator;
    }

    public double EstimatePi(int sumLength)
    {
        ...
    }
}
interface IPiCalculator
{ 
    double EstimatePi(int sumLength);
}

Context

StackExchange Code Review Q#158541, answer score: 37

Revisions (0)

No revisions yet.