Thursday, May 26, 2011

Windows cmd script to convert a string to upper case

@echo off
setlocal enableextensions enabledelayedexpansion
set myvar=Jack_and-Jill_went-uP-the_hill.
echo/'myvar' is initially as follows:
echo/[%myvar%]
set UCase=ABCDEFGHIJKLMNOPQRSTUVWXYZ
set LCase=abcdefghijklmnopqrstuvwxyz
for /L %%A in (0,1,24) do Call :ToUpper !LCase:~%%A,1! !UCase:~%%A,1!
echo/
echo/And now that we're done, 'myvar' is as follows:
echo/[%myvar%]
goto :EOF
:ToUpper Low Up
set myvar=!myvar:%1=%2!

Wednesday, May 4, 2011

C# program to sort number strings

using System;
using System.Collections.Generic;
namespace SortStrings
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] inputArray = {"324", "1", "9001", "-23", "99", "324", "800", "801", "802", "888" };
            Console.WriteLine("Input array is :");
            DisplayArray(ref inputArray);
            QuickSort(ref inputArray, 0, inputArray.Length-1);
            Console.WriteLine("Sorted array is :");
            DisplayArray(ref inputArray);
            Console.ReadKey();
        }
        private static void DisplayArray(ref string[] inputArray)
        {
            foreach (string s in inputArray)
            {
                Console.WriteLine(s);
            }
        }
        private static int Partition(ref string[] inputArray, int startIndex, int endIndex)
        {
            int loopIndex = startIndex;
            int lastIndex = startIndex;
            CompareNumberString c = new CompareNumberString();
            IComparer<string> comparer = (IComparer<string>)c;
            while (loopIndex < endIndex)
            {
                if (comparer.Compare(inputArray[loopIndex], inputArray[endIndex]) < 0)
                {
                    swap(ref inputArray, loopIndex, lastIndex);
                    lastIndex++;
                }
                loopIndex++;
            }
            swap(ref inputArray, endIndex, lastIndex);
            return lastIndex;
        }
        private static void QuickSort(ref string[] inputArray, int startIndex, int endIndex)
        {
            if (startIndex >= endIndex)
            {
                return;
            }       
            int pivotIndex = Partition(ref inputArray, startIndex, endIndex);
            QuickSort(ref inputArray, startIndex, pivotIndex - 1);
            QuickSort(ref inputArray, pivotIndex + 1, endIndex);
            return;
        }
        private static void swap(ref string[] inputArray, int index1, int index2)
        {
            string temp = inputArray[index1];
            inputArray[index1] = inputArray[index2];
            inputArray[index2] = temp;
        }
    }
}

Friday, April 8, 2011

String comparison in C#

Comparing programmatic strings (these are never exposed to the end user)
String.Compare(string1, string2, StringComparison.OrdinalIgnoreCase)

Comparing strings that end user can see:
String.Compare(string1, string2, StringComparison.CurrentCultureIgnoreCase)

Wednesday, April 6, 2011

Reverse a string in C#

        static void way1(string testString)
        {
            Console.WriteLine("Way 1 ------------>");
            StringBuilder reverseString = new StringBuilder(testString.Length);
            for (int i = testString.Length - 1; i >= 0; i--)
            {
                reverseString.Append(testString[i]);
            }
            Console.WriteLine(reverseString.ToString());
        }

        static void way2(string testString)
        {
            Console.WriteLine("Way 2 ------------>");
            char []temp = testString.ToCharArray();
            Array.Reverse(temp);
            string reverseString = new string(temp);
            Console.WriteLine(reverseString);
        }

        static void way3(string testString)
        {
            Console.WriteLine("Way 3 ------------>");
            String reverseString = String.Empty;
            for (int i = testString.Length - 1; i >= 0; i--)
            {
                reverseString += testString[i];
            }
            Console.WriteLine(reverseString);
        }

Wednesday, March 16, 2011

DataBase Caching

Recently I went to interview for a Software Developer position. I was asked this interesting question:

Given a database and an API to fetch a record from a database, design a datastructure to implement the cache. Also, design and implement the API used to fetch record from the cache.

My Solution:
Access source code here
You need Visual Studio 2010 to open the solution
The solution is coded in C
Data Structures
All records are stored in a Hash Table for fast access
At any point in time if the cache is full, Least Recently Used record is kicked out to give space to the new record. To keep track of the records in the order of their last access time, the records are also maintained as double linked list.
// represents cache record
struct cacheRec
{
    struct rec * databaseRec;
    struct cacheRec * prevRec;
    struct cacheRec * nextRec;
    bool valid;
};

struct cacheRec HashTable[CACHESIZE];

// pointer to the oldest record in the linked list
struct cacheRec * oldestCacheRec;

// pointer to the newest record in the linked list
struct cacheRec * newestCacheRec;

Time Complexity
Hash table provides lookup in O(1) time. If record is not present in the cache, reading it from database and inserting it in the end of the linked list (thereby making it the newest record) can be done in constant time. If cache is full, deleting record from cache, before inserting the new record, is also achieved in constant time. If record is present in the cache, deleting it from its current location in the linked list and inserting it in the end of the list, can also be done in O(1) time. Thus total time taken by FetchRecord() API is O(1).

Space complexity
If size of cache is n, algorithm takes O(n) space for hash tables and O(n) space for linked list pointers. Thus total space complexity is O(n)

Test Cases
The console app invokes following test cases. Each test case displays PASS/FAIL based on the number of expected Cache and Database hits

1.       Call FetchRecord() with invalid key
2.       Fetch records while re-fetching oldest record in the cache
3.       Fetch records while re-fetching newest record in the cache
4.       Fetch records while re-fetching a record in the middle of the cache linked list
5.       Fetch higher than cache-size number of unique records
6.       Fetch higher than cache-size number of non-unique records