Friday, September 19, 2014

The Ultimate Rounding Function

Your search for any requirement for rounding function is over. You need to round amount to quarter? dime? nickel? penny? a dollar? 10 dollar? Below function of single linen can provide you more than what you are looking for. for sure!
 decimal NearestOfPenny(decimal amountToRound)
 {
     return UltimateRoundingFunction(amountToRound, 0.01m, 0.5m);
 }

 decimal NearestOfNickel(decimal amountToRound)
 {
     return UltimateRoundingFunction(amountToRound, 0.05m, 0.5m);
 }

 decimal NearestOfDime(decimal amountToRound)
 {
     return UltimateRoundingFunction(amountToRound, 0.10m, 0.5m);
 }

 decimal NearestOfQuarter(decimal amountToRound)
 {
     return UltimateRoundingFunction(amountToRound, 0.25m, 0.5m);
 }

 decimal NearestOfDollar(decimal amountToRound)
 {
     return UltimateRoundingFunction(amountToRound, 1m, 0.5m);
 }

 decimal UpwardDollarOnlyIfReminderIsMoreThan70Cents(decimal amountToRound)
 {
     return UltimateRoundingFunction(amountToRound, 1m, 0.3m); 
     //i.e. 0.70 will round up. but 0.69 will be rounded to 0.. this magic is from value of 'fairness'.
 }
 
 //amountToRound => input amount
 //nearestOf => .25 if round to quater, 0.01 for rounding to 1 cent, 1 for rounding to $1
 //fairness => btween 0 to 0.9999999___. 
 //            0 means floor and 0.99999... means ceiling. But for ceiling, I would recommend, Math.Ceiling
 //            0.5 = Standard Rounding function. It will round up the border case. i.e. 1.5 to 2 and not 1.
 //            0.4999999... Non-standard rounding function. Where border case is rounded down. i.e. 1.5 to 1 and not 2.
 //            0.75 means first 75% values will be rounded down, rest 25% value will be rounded up.
 decimal UltimateRoundingFunction(decimal amountToRound, decimal nearstOf, decimal fairness)
 {
     return Math.Floor(amountToRound / nearstOf + fairness) * nearstOf;
 }

Saturday, August 30, 2014

Completely Read-Only Object as Return Value

NOTE: I am not proposing a 'secure' code. It's just to make your code dumb proof, not hack proof.
At the pinnacle of the insanity, when you have that bong affecting your normal senses, you may want to return that object from your beloved method which cannot be modified in anyway. You cannot even create a new object of the class that you are returning to have exclusive access to your return type. Anyways, whatever it can be used (?) for, it's here:
using System;
using System.Collections.ObjectModel;
using System.Security.Permissions;

public class ReadOnlyClassAsReturnValue
{
    private int sampleInt;
    // make regular property read-only by creating only 'get' call 
    public int SampleInt
    {
        get { return sampleInt; }
    }

    private bool[] sampleCollection;
    // Collections need to be made ReadOnlyCollection<T> . 
    //      NOTE: Though ReadOnlyCollection<T> can be casted as IList<T>, never 
    //          do that. It allows someone to to change collection in compilte
    //          time only to realized during runtime that it cannot be changed
    public ReadOnlyCollection<bool> SampleCollection
    {
        get { return Array.AsReadOnly(sampleCollection); } //gives ReadOnlyCollection<T>
    }

    // 'private' varialbes can only be assigned in contructor. If any variable need to be assigned after
    // object is created, it need to be made 'internal'.
    protected string sampleString = "x";
    public string SampleString
    {
        get { return sampleString; }
    }

    // Contructor is made 'protected' as this class is to be used by serious consumers only.
    // If ultimate (dumb) user is going to be outside your assembly, you can make it 
    // 'internal' instead of 'prorected' eliminating need to override this class and 
    // providing more protection than 'protected' (and 'proected internal').
    protected ReadOnlyClassAsReturnValue(int sampleInt, bool[] sampleCollection)
    {
        this.sampleInt = sampleInt;
        this.sampleCollection = sampleCollection;
    }
}

public class PrimaryUserClass
{
    // Inherit ReadOnlyClassAsReturnValue so internal methods/properties/variables can be assigned
    private class ReadOnlyObjectMaker : ReadOnlyClassAsReturnValue
    {
        public ReadOnlyObjectMaker(int sampleInt, bool[] sampleCollection)
            : base(sampleInt, sampleCollection)
        { }

        public string SampleString
        {
            set
            {
                this.sampleString = value;
            }
        }
    }

    //NO ONE CAN CHANGE THIS RETURN VALUE
    public ReadOnlyClassAsReturnValue ReadOnlyClassReturner()
    {
        ReadOnlyObjectMaker returnValue = new ReadOnlyObjectMaker(10, new bool[] { true, false });
        returnValue.SampleString = "I can assign this";
        return returnValue;
    }
}

class Program
{
    static void Main(string[] args)
    {
        var returnValue = new PrimaryUserClass().ReadOnlyClassReturner();
        //returnValue cannot be modified. Why? Just for fun. Someone has to hack it to change anythingin returnValue.
    }
}

Tuesday, February 18, 2014

Counting Number of REAL lines in Your C# Code

If you are here, it means one (or more) of the three things: 1. You are the boss, 2. Your boss told you to count number of lines 3. You are a serious programmer.
Anyways, let's come to the point. Each programer is different.  Problem with just literally counting the line has many issues which this piece of code attempts to resolve as mentioned below:
0. Comments of // and /* kind are ignored.
1. A statement written in multiple line is considered single line.
2. brackets are (i.e. '{') not considered lines.
3. 'using namespace' line are ignored.


        private int CountNumberOfLinesInCSFilesOfDirectory(string dirPath)
        {
            FileInfo[] csFiles = new DirectoryInfo(txtPath.Text.Trim())
                                        .GetFiles("*.cs", SearchOption.AllDirectories);

            int totalNumberOfLines = 0;
            Parallel.ForEach(csFiles, fo =>
            {
                Interlocked.Add(ref totalNumberOfLines, CountNumberOfLine(fo));
            });
            return totalNumberOfLines;
        }

        private int CountNumberOfLine(Object tc)
        {
            FileInfo fo = (FileInfo)tc;
            int count = 0;
            int inComment = 0;
            using (StreamReader sr = fo.OpenText())
            {
                string line;
                while ((line = sr.ReadLine()) != null)
                {
                    if (IsRealCode(line.Trim(), ref inComment))
                        count++;
                }
            }
            return count;
        }

        private bool IsRealCode(string trimmed, ref int inComment)
        {
            if (trimmed.StartsWith("/*") && trimmed.EndsWith("*/"))
                return false;
            else if (trimmed.StartsWith("/*"))
            {
                inComment++;
                return false;
            }
            else if (trimmed.EndsWith("*/"))
            {
                inComment--;
                return false;
            }

            return
                   inComment == 0
                && !trimmed.StartsWith("//")
                && (trimmed.StartsWith("if")
                    || trimmed.StartsWith("else if")
                    || trimmed.StartsWith("using (")
                    || trimmed.StartsWith("else  if")
                    || trimmed.Contains(";")
                    || trimmed.StartsWith("public") //method signature
                    || trimmed.StartsWith("private") //method signature
                    || trimmed.StartsWith("protected") //method signature
                    );
        }


There is (literally) no solution for below (un)kind of programers:
1. Write multiple statements in single line.
2. Who declare useless variables.
3.Whose every other line is debug.write
4. Inappropriate use of compiler directive (directive itself is not considered as line btw)
5. Bulk copy programmers who suffer from schizophrenia and lives only in their set of classes. Don't trust or reuse anything else.
6. Who still likes to reinvent the wheel.

Apart from above six non-solvable issues, if you can improve my code, it will be helpful to everyone.