Monday, December 24, 2012

Perl how to find a exact word from all files under current directory (One level search only)

# Find out where all you see hello word in files
use warnings;
use strict;

my @files = <*.*>;

foreach my $file(@files) {
    if(-e -f $file) {
        open my $file_handler, '<, $file;
        while(<$file_handler>)  {
            if(/\A(hello)\z / ) {
                print $1;
            }
        }
       close $file_handle;
    }
}

Saturday, November 3, 2012

How to implement your own Map

This post is to show how you can implement a simple Map with only Put, Get and Size operations. This map implementation does not take care of any thread safety and just here to illustrate what all may needed to implement a map kind of data structure.

What all needed - 
  1. eclispe -Juno
  2. JDK 1.7
  3. Junit 4.5
  4. Hamcrest-all-1.1.jar

Test First -


package com.chatar.practice;

import org.junit.Assert;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.*;

import com.chatar.pratice.MyMap;

public class MyMapTest {
   
    @Test(expected=NullPointerException.class)
    public void shouldThrowExceptionIfInsertingNullKey() {
        MyMap myMap = new MyMap();
        myMap.put(null, "some_value");
    }
   
    @Test(expected=NullPointerException.class)
    public void shouldThrowExceptionIfGetingValueForNullKey() {
        MyMap myMap = new MyMap();
        myMap.get(null);
    }
   
    @Test
    public void shouldAbleToPutValues() {
        MyMap myMap = new MyMap();
        myMap.put("key1", "value1");
        myMap.put("key2", "value2");       
        Assert.assertThat(myMap.size(), is(2));
    }
   
    @Test
    public void shouldReturnNullIfKeyNotFound() {
        MyMap myMap = new MyMap();       
        Assert.assertThat(myMap.get("key1"), nullValue());
    }
   
    @Test
    public void shouldOverrideValueIfKeyIsUnique() {
        MyMap myMap = new MyMap();
        myMap.put("key1", "value1");
        Assert.assertThat(myMap.size(), is(1));
        Assert.assertThat(myMap.get("key1"), is("value1"));
        myMap.put("key1", "value2");       
        Assert.assertThat(myMap.size(), is(1));
        Assert.assertThat(myMap.get("key1"), is("value2"));
       
    }
   
    @Test
    public void shouldGetValueByPassingKey() {
        MyMap myMap = new MyMap();
        myMap.put("key1", "value1");
        myMap.put("key2", "value2");       
        Assert.assertThat(myMap.size(), is(2));
        Assert.assertThat(myMap.get("key1"), is("value1"));
        Assert.assertThat(myMap.get("key2"), is("value2"));
    }
}


And Implementation -



package com.chatar.pratice;

public class MyMap {
   
    private Entry[] backets;
    private int size = 0;
   
    public MyMap() {}{
        backets = new Entry[128];
    }
   
    public void put(K key, V value) {
        validate(key);
        Entry entry = backets[backet(key)];
        if(entry != null) {
            addTo(entry, key, value);
        } else {
            backets[backet(key)] = new Entry(key, value);
        }
        size++;
    }

    public V get(K key) {
        validate(key);
        Entry entry = backets[backet(key)];
        while(entry != null && !key.equals(entry.key)) {
            entry = entry.next;
        }
        return entry != null ? entry.value : null;
    }
   
    public int size() {
        return size;
    }

    private void validate(K key) {
        if(key == null) {
            throw new NullPointerException("Key can't be null");   
        }
    }
   
    private void addTo(Entry entry, K key, V value) {
        boolean notFound = true;
        while(notFound) {
            if(entry.hasNext()) {
                if(entry.key.equals(key)) {
                    entry.value = value;
                    notFound = false;
                    size--;
                }
            }
            else if (entry.key.equals(key)) {
                entry.value = value;
                notFound = false;
                size--;
            }
        }
    }

    private int backet(K key) {
        return key.hashCode() % backets.length;
    }
   
    static class Entry {
        K key;
        V value;
        Entry next;
       
        public Entry(K key, V value) {
            this.key = key;
            this.value = value;
        }
       
        public Entry next() {
            return next;
        }
       
        public boolean hasNext() {
            return next != null;
        }
    }
}



Sunday, August 5, 2012

After long time I am back to my blog.

It took me almost two years to realized how important is the blog post and more important is how to keep it going.. I always had hard time in writing specially how to express my self. To make thing easy I promised my self to write a small post about bi-weekly basis on what I have learned

I have read recently clean coder - A handbook of  Agile software craftsmanship written by Robert C. Martin and now I know what it takes to become a professional programmer.

The earlier book Clean code was all about code and clean coder was all about about profession. I felt both the books are two side of a coin and a professional programmer is who write clean code and a professional at the same time.

I recommended the book to two of my colleagues also and I would recommend to everyone who care about professionalism. Thanks to uncle bob for such a simple yet powerful book on professionalism. 

Sunday, December 27, 2009

Design Patterns - WWW (What/ When / Why)

  • What is a design pattern? - Someone has already solved your problem - (Head First Design Pattern).
  • When should we use it? - Depend upon what kind of problem you want to solve .. there might be already a mature solution (in design) for the problem.. so that means you need to spend some time understanding existing design patterns and where you should apply them.. if you think none of the existing design pattern suits to your problem then you can share your experience with the community and you never know .. might be the next design pattern belongs to you..
  • Why should we use it? As already said - Someone has already solved your problem.. and when you apply it your code it make self explanatory . so that if some one else is looking to your code can easily make what kind of problem you are trying to solve.. ah you got free documentation...

Source code for ATM Client

1.
package com.cp.exercise.atm;

import java.util.HashMap;
import java.util.Map;

import com.cp.exercise.atm.exception.InsufficientBalanceException;
import com.cp.exercise.atm.exception.InvalidAccountExcetion;
import com.cp.exercise.atm.exception.InvalidDenominationException;
import com.cp.exercise.atm.exception.InvalidUserAccountExcetion;

public class ATMClient {

private static ATMClient client;

private ATMClient() {
}

public static ATMClient instanceOf() {
if(client == null) {
client = new ATMClient();
} return client;
}

private final Map userToAvailableBalance = new HashMap();

public synchronized void filledUserAccountWithInitialBalance(UserAccount userAccount, int initialBalance) {
validateAccount(userAccount);
userToAvailableBalance.put(userAccount, initialBalance);
}

public synchronized Integer checkBalance(UserAccount userAccount) {
return getBalance(userAccount);
}

public synchronized Map withdrawThisMuchAmount(UserAccount userAccount, int withDrawAmount) {
userHaveEnoughMoney(userAccount, withDrawAmount);
denominationIsCorrect(withDrawAmount);
reAdjustAccountBalance(userAccount, withDrawAmount);
return getTotalNotesForThisAmount(withDrawAmount);
}

private Integer getBalance(UserAccount userAccount) {
if(userToAvailableBalance.containsKey(userAccount)) {
return userToAvailableBalance.get(userAccount);
}
throw new InvalidUserAccountExcetion(String.format("Account [%s] does not exist.", userAccount));
}

private void validateAccount(UserAccount userAccount) {
if(!userAccount.isValidAccount()) {
throw new InvalidAccountExcetion(String.format("Account [%s] is not valid", userAccount));
}
}

private void reAdjustAccountBalance(UserAccount userAccount, int withDrawAmount) {
final int balance = getBalance(userAccount) - withDrawAmount;
userToAvailableBalance.put(userAccount, balance);
}

private Map getTotalNotesForThisAmount(int withDrawAmount) {
return Denomination.totalNoOfNotes(withDrawAmount);
}

private void denominationIsCorrect(int withDrawAmount) {
if(!Denomination.isCorrect(withDrawAmount)) {
throw new InvalidDenominationException(String.format("This amount [%s] is not valid. Please enter multilier of [%s]", withDrawAmount,Denomination.names()));
}
}

private void userHaveEnoughMoney(UserAccount userAccount, int withDrawAmount) {
if(getBalance(userAccount) <> getBalance(userAccount)) {
throw new InsufficientBalanceException(String.format("Account [%s] has insufficient balance [%s].Requested amount [%s]",
userAccount, getBalance(userAccount), withDrawAmount));
}
}
}

Test case for ATM Client

package com.cp.exercise.atm;

import java.util.Map;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import com.cp.exercise.atm.exception.InsufficientBalanceException;
import com.cp.exercise.atm.exception.InvalidDenominationException;
import com.cp.exercise.atm.exception.InvalidUserAccountExcetion;

public class TestATMClient {

private ATMClient client;
private UserAccount userAccount;

@Before
public void filledUserAccountWithBalance() {
client = ATMClient.instanceOf();
userAccount = new UserAccount("123455632", "pin");
final int tenThousand = Denomination.FIVE_HUNDRED.getNote() * 20;
client.filledUserAccountWithInitialBalance(userAccount, tenThousand);
}

@Test(expected=InvalidUserAccountExcetion.class)
public void shouldThrowAnExceptionIfAccountDoesNotExist() {
final UserAccount invalidUserAccount = new UserAccount("", "");
Assert.assertEquals(10000, client.checkBalance(invalidUserAccount));
}

@Test
public void userShouldAbleSeeTotalAvailableBalance() {
Assert.assertEquals(10000, client.checkBalance(userAccount));
}

@Test
public void userShouldAbleToWithdrawAmountWithCorrectDenomination() {
final Map denominationToCount = client.withdrawThisMuchAmount(userAccount, 2200);

Assert.assertEquals(4, denominationToCount.get(Denomination.FIVE_HUNDRED));
Assert.assertEquals(2, denominationToCount.get(Denomination.HUNDRED));
Assert.assertEquals(null, denominationToCount.get(Denomination.FIFTY));
Assert.assertEquals(7800, client.checkBalance(userAccount));
}

@Test(expected=InvalidDenominationException.class)
public void userShouldGetAnErrorMessageIfTheWithdrawelAmountIsNotMultilierOfAvailableDenomination() {
client.withdrawThisMuchAmount(userAccount, 1999);
}

@Test(expected=InsufficientBalanceException.class)
public void userShouldGetAnErrorMessageIfMinimumBalanceFallBelowMinimumDenomination() {
client.withdrawThisMuchAmount(userAccount, 11000);
}
}

Some problems and solution using - TDD

1. ATM Client -
Today I was thinking of writing a sample program which can be used as an ATM client.

Problem - Write a simple java program which act as an ATM client and do following :-
a) User should able to populate their account with some initial amount .. sound funny? latter one we will change this. so that only admin can do that
b) Support for 50, 100 and 500 denomination.
c) Error handling for invalid account, denomination, over flow requested amount.
d) User should able to check account balance.
e) User should able to withdraw valid amount.. in return ATM machine should return the total no of notes for each denomination.

Ok.. enough writing about the problem .. Let us write some code.. code?
or test cases .. I vote for test cases..

What all you need -
1. JDK 5
2. Eclipse
3. Junit 4