Friday, September 14, 2012


;SQLSERVER2008 Configuration File
[SQLSERVER2008]

; Specify the Instance ID for the SQL Server features you have specified. SQL Server directory structure, registry structure, and service names will reflect the instance ID of the SQL Server instance.

INSTANCEID="MSSQLSERVER"

; Specifies a Setup work flow, like INSTALL, UNINSTALL, or UPGRADE. This is a required parameter.

ACTION="Install"

; Specifies features to install, uninstall, or upgrade. The list of top-level features include SQL, AS, RS, IS, and Tools. The SQL feature will install the database engine, replication, and full-text. The Tools feature will install Management Tools, Books online, Business Intelligence Development Studio, and other shared components.

FEATURES=SQLENGINE,REPLICATION,FULLTEXT,CONN,SSMS,ADV_SSMS,SNAC_SDK

; Displays the command line parameters usage

HELP="False"

; Specifies that the detailed Setup log should be piped to the console.

INDICATEPROGRESS="True"

; Setup will not display any user interface.

QUIET="False"

; Setup will display progress only without any user interaction.

QUIETSIMPLE="True"

; Specifies that Setup should install into WOW64. This command line argument is not supported on an IA64 or a 32-bit system.

X86="False"

; Detailed help for command line argument ENU has not been defined yet.

ENU="True"

; Parameter that controls the user interface behavior. Valid values are Normal for the full UI, and AutoAdvance for a simplied UI.

UIMODE="Normal"

; Specify if errors can be reported to Microsoft to improve future SQL Server releases. Specify 1 or True to enable and 0 or False to disable this feature.

ERRORREPORTING="False"

; Specify the root installation directory for native shared components.

INSTALLSHAREDDIR="C:\Program Files\Microsoft SQL Server"

; Specify the root installation directory for the WOW64 shared components.

INSTALLSHAREDWOWDIR="C:\Program Files (x86)\Microsoft SQL Server"

; Specify the installation directory.

INSTANCEDIR="C:\Program Files\Microsoft SQL Server"

; Specify that SQL Server feature usage data can be collected and sent to Microsoft. Specify 1 or True to enable and 0 or False to disable this feature.

SQMREPORTING="False"

; Specify a default or named instance. MSSQLSERVER is the default instance for non-Express editions and SQLExpress for Express editions. This parameter is required when installing the SQL Server Database Engine (SQL), Analysis Services (AS), or Reporting Services (RS).

INSTANCENAME="MSSQLSERVER"

; Agent account name

AGTSVCACCOUNT="NT AUTHORITY\SYSTEM"

; Auto-start service after installation.

AGTSVCSTARTUPTYPE="Automatic"

; Startup type for Integration Services.

ISSVCSTARTUPTYPE="Automatic"

; Account for Integration Services: Domain\User or system account.

ISSVCACCOUNT="NT AUTHORITY\NetworkService"

; Controls the service startup type setting after the service has been created.

ASSVCSTARTUPTYPE="Automatic"

; The collation to be used by Analysis Services.

ASCOLLATION="Latin1_General_CI_AS"

; The location for the Analysis Services data files.

ASDATADIR="Data"

; The location for the Analysis Services log files.

ASLOGDIR="Log"

; The location for the Analysis Services backup files.

ASBACKUPDIR="Backup"

; The location for the Analysis Services temporary files.

ASTEMPDIR="Temp"

; The location for the Analysis Services configuration files.

ASCONFIGDIR="Config"

; Specifies whether or not the MSOLAP provider is allowed to run in process.

ASPROVIDERMSOLAP="1"

; A port number used to connect to the SharePoint Central Administration web application.

FARMADMINPORT="0"

; Startup type for the SQL Server service.

SQLSVCSTARTUPTYPE="Automatic"

; Level to enable FILESTREAM feature at (0, 1, 2 or 3).

FILESTREAMLEVEL="0"

; Set to "1" to enable RANU for SQL Server Express.

ENABLERANU="False"

; Specifies a Windows collation or an SQL collation to use for the Database Engine.

SQLCOLLATION="SQL_Latin1_General_CP1_CI_AS"

; Account for SQL Server service: Domain\User or system account.

SQLSVCACCOUNT="NT AUTHORITY\SYSTEM"

; Windows account(s) to provision as SQL Server system administrators.

SQLSYSADMINACCOUNTS="VC-VM\Administrator"

; The default is Windows Authentication. Use "SQL" for Mixed Mode Authentication.

SECURITYMODE="SQL"

SAPWD="oplAdmin123"

; Provision current user as a Database Engine system administrator for SQL Server 2008 R2 Express.

ADDCURRENTUSERASSQLADMIN="False"

; Specify 0 to disable or 1 to enable the TCP/IP protocol.

TCPENABLED="1"

; Specify 0 to disable or 1 to enable the Named Pipes protocol.

NPENABLED="1"

; Startup type for Browser Service.

BROWSERSVCSTARTUPTYPE="Disabled"

; Specifies how the startup mode of the report server NT service.  When
; Manual - Service startup is manual mode (default).
; Automatic - Service startup is automatic mode.
; Disabled - Service is disabled

RSSVCSTARTUPTYPE="Automatic"

; Specifies which mode report server is installed in.
; Default value: “FilesOnly”

RSINSTALLMODE="FilesOnlyMode"

; Add description of input argument FTSVCACCOUNT

FTSVCACCOUNT="NT AUTHORITY\LOCAL SERVICE"

Tuesday, September 11, 2012

Locking in multiuser environment


These are methodologies used to handle multi-user issues. How does one handle the fact that 2 people want to update the same record at the same time?

1. Do Nothing
- User 1 reads a record
- User 2 reads the same record
- User 1 updates that record
- User 2 updates the same record
User 2 has now over-written the changes that User 1 made. They are completely gone, as if they never happened. This is called a 'lost update'.

2. Lock the record when it is read. Pessimistic locking
- User 1 reads a record *and locks it* by putting an exclusive lock on the record (FOR UPDATE clause)
- User 2 attempts to read *and lock* the same record, but must now wait behind User 1
- User 1 updates the record (and, of course, commits)
- User 2 can now read the record *with the changes that User 1 made*
- User 2 updates the record complete with the changes from User 1
The lost update problem is solved. The problem with this approach is concurrency. User 1 is locking a record that they might not ever update. User 2 cannot even read the record because they want an exclusive lock when reading as well. This approach requires far too much exclusive locking, and the locks live far too long (often across user control - an *absolute* no-no). This approach is almost *never* implemented.

3. Use Optimistic Locking. Optimistic locking does not use exclusive locks when reading. Instead, a check is made during the update to make sure that the record has not been changed since it was read. This can be done by checking every field in the table.
ie. UPDATE Table1 SET Col2 = x WHERE COL1=:OldCol1 AND COl2=:OldCol AND Col3=:OldCol3 AND...
There are, of course, several disadvantages to this. First, you must have already SELECTed every single column from the table. Secondly, you must build and execute this massive statement. *Most* people implement this, instead, through a single column, usually called timestamp. This column is used *for no other purpose* than implementing optimistic concurrency. It can be a number or a date. The idea is that it is given a value when the row is inserted. Whenever the record is read, the timestamp column is read as well. When an update is performed, the timestamp column is checked. If it has the same value at UPDATE time as it did when it was read, then all is well, the UPDATE is performed and *the timestamp is changed!*. If the timestamp value is different at UPDATE time, then an error is returned to the user - they must re-read the record, re-make their changes, and try to update the record again.

- User 1 reads the record, including the timestamp of 21
- User 2 reads the record, including the timestamp of 21
- User 1 attempts to update the record. The timestamp in had (21) matches the timestamp in the database(21), so the update is performed and the timestamp is update (22).
- User 2 attempts to update the record. The timestamp in hand(21) *does not* match the timestamp in the database(22), so an error is returned. User 2 must now re-read the record, including the new timestamp(22) and User 1's changes, re-apply their changes and re-attempt the update.

Sunday, March 4, 2012

Add digits stored in linklist nodes.The digits are in reverse order Eg: Add 354 and 445 L1 : ->4->5->3->null L2 : ->5->4->4->null Ans : ->9->9->7->null
 class Node{  
      public int data;  
      public Node next;  
      public Node(int n){  
           this.data = n;  
           this.next = null;  
      }  
 }  
 public class LinkList{  
      public Node addNode(Node head, int n){  
           if(head == null){  
                head = new Node(n);  
                return head;  
           }  
           Node curr = head;  
           while(curr.next != null){  
                curr = curr.next;  
           }  
           curr.next= new Node(n);  
           return head;  
      }  
      public static void printLinkList(Node head){  
           if(head == null){  
                return;  
           }  
           Node curr = head;  
           while(curr != null){  
                System.out.print("->"+curr.data);  
                curr = curr.next;  
           }  
           System.out.print("->null");  
           System.out.println();  
      }  
      public static Node addLists(Node head1, Node head2){  
           if(head1==null && head2==null){  
                return null;  
           }else if(head1 == null){  
                return head2;  
           }else if(head2 == null){  
                return head1;  
           }  
           Node newHead = null;  
           Node newCurr = null;  
           Node curr1 = head1;  
           Node curr2 = head2;  
           int carry = 0;  
           while(curr1 != null && curr2 != null){  
                int newSum = curr1.data + curr2.data + carry;  
                if(newSum >= 10){  
                     carry = 1;  
                     newSum = newSum - 10;  
                }else{  
                     carry = 0;  
                }  
                if(newHead == null){//first node  
                     newHead = new Node(newSum);  
                     newCurr = newHead;  
                }else{//subsequent nodes  
                     newCurr.next = new Node(newSum);  
                     newCurr = newCurr.next;  
                }  
                curr1= curr1.next;  
                curr2= curr2.next;  
           }  
           while(curr1 != null){  
                int newSum = curr1.data + carry;  
                if(newSum >= 10){  
                     carry = 1;  
                     newSum = newSum - 10;  
                }else{  
                     carry = 0;  
                }  
                newCurr.next = new Node(newSum);  
                newCurr = newCurr.next;  
                curr1= curr1.next;  
           }  
           while(curr2 != null){  
                int newSum = curr2.data + carry;  
                if(newSum >= 10){  
                     carry = 1;  
                     newSum = newSum - 10;  
                }else{  
                     carry = 0;  
                }  
                newCurr.next = new Node(newSum);  
                newCurr = newCurr.next;  
                curr2= curr2.next;  
           }  
           if(carry == 1){  
                newCurr.next = new Node(1);  
                newCurr = newCurr.next;  
           }  
           newCurr.next = null;  
           return newHead;  
      }  
      public static void main(String args[]){  
           LinkList l1 = new LinkList();  
           Node head1 = l1.addNode(null, 1);  
           head1 = l1.addNode(head1, 2);  
           head1 = l1.addNode(head1, 6);  
           head1 = l1.addNode(head1, 9);  
           LinkList l2 = new LinkList();  
           Node head2 = l2.addNode(null, 4);  
           head2 = l2.addNode(head2, 5);  
           head2 = l2.addNode(head2, 5);  
           LinkList.printLinkList(head1);  
           LinkList.printLinkList(head2);  
           Node head3 = LinkList.addLists(head1, head2);  
           LinkList.printLinkList(head3);  
      }  
 }  

Saturday, February 25, 2012

String compression

 public class Compress {  
      public static void compressStr(String str){  
           if(str == null || str.length() < 2){  
                return;  
           }  
           if(countCompression(str) >= str.length()){  
                System.out.println("Should not compress");  
                return;  
           }  
           char[] a = str.toCharArray();  
           int src = 1;  
           int dst = 0;  
           int count = 1;  
           while(src < a.length){  
                if(a[src-1] == a[src]){  
                     count++;  
                }else{  
                     System.out.println("The prev val is "+a[src-1]+" and next val is "+a[src]);  
                     a[dst++] = a[src-1];  
                     a[dst++] = (char) (count + '0');  
                     count = 1;  
                }  
                src++;  
           }  
           System.out.println("The src val is "+src+" and next val is "+count);  
           String compStr = new String(a, 0, dst);  
           compStr = compStr + str.charAt(a.length-1) + count;  
           System.out.println("The compressed str is "+compStr);  
      }  
      public static int countCompression(String str){  
           char[] a = str.toCharArray();  
           int src = 1;  
           int count = 1;  
           int size = 0;  
           while(src < a.length){  
                if(a[src-1] == a[src]){  
                     count++;  
                }else{  
                     size += 1 + String.valueOf(count).length();  
                     count = 1;  
                }  
                src++;  
           }  
           size += 1 + String.valueOf(count).length();  
           System.out.println("The compressed size is "+size);  
           return size;  
      }  
      public static void main(String args[]){  
           compressStr("aabbccccccc");  
      }  
 }  
This is to remove dups from a sorted int or char[]



 public class RemoveDups {  
      public static void removeDups(int[] a){  
           if(a == null || a.length < 2){  
                return;  
           }  
           int count = 1; //init to 1 to take care of last matching character  
           for(int i = 1; i < a.length; i++){  
                if(a[i-1] == a[i]){  
                     count++;  
                     if(count > a.length/2){  
                          System.out.println("The val "+a[i]);  
                          return;  
                     }  
                }else{  
                     count = 1;  
                }  
           }  
      }  
      public static void removeDupsStr(String str){  
           if(str == null || str.length() < 2){  
                return;  
           }  
           char a[] = str.toCharArray();  
           int src = 1;  
           int dst = 1;  
           while(src < a.length){  
                if(a[src-1] == a[src]){  
                     src++;  
                }else{  
                     a[dst] = a[src];  
                     dst++;  
                }  
           }  
           System.out.println("The str is "+new String(a,0,dst));  
      }  
      public static void removeDupsStringInN(String str){  
           if(str == null || str.length() < 2){  
                return;  
           }  
           char[] a= str.toCharArray();  
           boolean[] flag = new boolean[256];  
           for(int i = 0; i < flag.length; i++){  
                flag[i] = false;  
           }  
           int src = 0;  
           int dst = 0;  
           while(src < a.length){  
                if(!flag[a[src]]){  
                     a[dst] = a[src];  
                     dst++;  
                     flag[a[src]] = true;  
                }  
                src++;  
           }  
           System.out.println("The str is "+new String(a,0,dst));  
      }  
      public static void main(String args[]){  
           int a[] = { 1,1,1,1,3,3,3,3,3};  
           removeDups(a);  
           removeDupsStr("aaijsy");  
           removeDupsStringInN("sayaji");  
      }  
 }  

Wednesday, February 15, 2012

Longest Common Subsequence

 public class LCSequence {  
      public String lcs(String a, String b) {  
           int[][] lengths = new int[a.length()+1][b.length()+1];  
           // row 0 and column 0 are initialized to 0 already  
           for (int i = 0; i < a.length(); i++)  
                for (int j = 0; j < b.length(); j++)  
                     if (a.charAt(i) == b.charAt(j))  
                          lengths[i+1][j+1] = lengths[i][j] + 1;  
                     else  
                          lengths[i+1][j+1] =  
                          Math.max(lengths[i+1][j], lengths[i][j+1]);  
           // read the substring out from the matrix  
           StringBuffer sb = new StringBuffer();  
           for (int x = a.length(), y = b.length();  
                     x != 0 && y != 0; ) {  
                if (lengths[x][y] == lengths[x-1][y])  
                     x--;  
                else if (lengths[x][y] == lengths[x][y-1])  
                     y--;  
                else {  
                     if(a.charAt(x-1) == b.charAt(y-1)){  
                          sb.append(a.charAt(x-1));  
                          x--;  
                          y--;  
                     }  
                }  
           }  
           System.out.println("The DP table is: ");   
           for (int i=0; i<lengths.length; i++) {   
                for (int j=0; j<lengths[i].length; j++) {   
                     System.out.print(" " + lengths[i][j]);   
                }   
                System.out.println("");   
           }   
           return sb.reverse().toString();  
      }  
      public static void main(String args[]){   
           LCSequence m = new LCSequence();   
           System.out.println("The LCS is "+m.lcs("12","1122"));   
      }   
 }  



Sunday, February 12, 2012

Why is string immutable in Java

1) Performance (string pooling)
2) thread safety ( we can pass around strings between threads and not worry about anyone changing it)
3) Security
http://geekexplains.blogspot.com/2009/11/why-string-has-been-made-immutable-in.html?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+GeekExplains+%28Geek+Explains%29

DataBase basics

1) Whenever an aggregate function is used with other field in query, a GROUP BY clause is required
     select name, avg(price) from products GROUP BY name

      if the aggregate function is used by itself then GROUP BY is not required
     select name from products

2) Select * from tables that are joined will give columns from both tables

3) Invalid use of aggregate function

SELECT *
  FROM DEPARTMENTS WHERE BUDGET > AVG(BUDGET)

Correct use is

SELECT *
  FROM DEPARTMENTS WHERE BUDGET > (SELECT AVG(BUDGET) FROM DEPARTMENTS)


1)Heap
2)Mergesort
3)quicksort
4)b tree
5)external sort
6)BFS
7)DFS
8)Hashing - file storage

Sunday, January 29, 2012

JMS, ActiveMQ, JGroups

JMS(Java Message Service) api is a Java message oriented middleware api provided by Java Platform Enterprise Edition for sending messages between two or more clients.



The following are JMS elements:[3]
JMS provider
An implementation of the JMS interface for a Message Oriented Middleware (MOM). Providers are implemented as either a Java JMS implementation or an adapter to a non-Java MOM.
JMS client
An application or process that produces and/or receives messages.
JMS producer/publisher
A JMS client that creates and sends messages.
JMS consumer/subscriber
A JMS client that receives messages.
JMS message
An object that contains the data being transferred between JMS clients.
JMS queue
A staging area that contains messages that have been sent and are waiting to be read. Note that, contrary to what the name queue suggests, messages don't have to be delivered in the order sent. A JMS queue only guarantees that each message is processed only once.
JMS topic
A distribution mechanism for publishing messages that are delivered to multiple subscribers.

ActiveMQ is one of the implementation of the JMS provider. 
ActiveMQ topic :
By definition, a topic message remains on the topic until it is consumed by all the currently available non-durable subscribers, and all the registered durable subscribers, irrespective of whether they are currently available or not. Once a topic message is consumed by any given subscriber, it becomes pending and remains so, until it has been consumed by all of these subscribers. 

JGroups is a toolkit for reliable multicast communication.It can also use JMS as one of the
protocol.
The most powerful feature of JGroups is its flexible protocol stack, which allows developers to adapt it to exactly match their application requirements and network characteristics.
Applications are even free to write their own protocols (or extend an existing one), and add them to the configuration. It might be useful for example, to add a protocol which keeps track of all messages sent and received over a cluster, for auditing or statistics purposes.

An Example of How Things Can Go Wrong

It is tempting to believe that it suffices to use JMS in order to achieve fully reliable messaging, but this is not true.
Let's consider the following example of where things can go wrong. Assume that a message comes in on the JMS queue (say, a payment order) and we want to process the payment in the database.
  1. The message is taken off the queue
  2. The message is processed by our Java program
  3. The results are put in the database
Let's now focus on the following questions:
  • Can messages be lost?
  • Can messages be received twice?
The answer to each question will depend on the acknowledgement mode for JMS. Again, the possible values are: automatic, explicit and transactional.
With automatic acknowledgement, the JMS message is deleted from the queue as soon as it is taken off. Clearly, this allows message loss if our program crashes in step 2. In that case, the payment order is lost forever. Hence, we have message loss.
With explicit acknowledgement, the JMS message is not deleted from the queue until our program tells it to do so. When could we tell the JMS to delete the message? If done before step 2, then a crash in 2 means message loss again. If done during step 2, then a crash will also lose the message since the database has not been changed. If done after step 3, then a crash could happen between 3 and before we can delete the message. In that case, the message will be redelivered upon restart and will be re-processed and re-posted to the database. That is: duplicates.
With transactional acknowledgement, there are two possibilities: connector-level JMS and JDBC transactions or JTA/XA. When JMS is used in transactional mode, the deletion of a message is only done if and only if the transaction commits. JDBC implies that the database is updated only if the transaction commits.
For connector-level transactions, we will have two distinct transactions: one for JMS and one for JDBC. So the question is: how should the commits be ordered to avoid message loss and duplicates?
If the JMS transaction is committed first, a crash can happen before we commit the JDBC transaction. Consequence: message loss; the payment will never be in the database.
If the JDBC transaction is committed first, a crash can happen before we commit the JMS transaction. Consequence: duplicate message; the message is not deleted from the queue and will be redelivered later. The application will re-process it and re-post it in the database.
The only remaining possibility is: joint commit of both the JMS and the JDBC transaction, and this is exactly what JTA/XA do for you. For reliable, exactly-once messaging you really need JTA/XA.



Monday, January 23, 2012

Dynamic Programming: Longest common substring

Note: This is different from longest common subsequence. Longest common string is continuous while
the longest common subsequence is not.


subsequence is a sequence that can be derived from another sequence by deleting some elements without changing the order of the remaining elements. For example, the sequence  \langle A,B,D \rangle  is a subsequence of  \langle A,B,C,D,E,F \rangle .
Given two sequences X and Y, a sequence G is said to be a common subsequence of X and Y, if G is a subsequence of both X and Y. For example, if
 X = \langle A,C,B,D,E,G,C,E,D,B,G \rangle  and
 Y = \langle B,E,G,C,F,E,U,B,K \rangle
then a common subsequence of X and Y could be
 G = \langle B,E,E \rangle.
This would not be the longest common subsequence, since G only has length 3, and the common subsequence  \langle B,E,E,B \rangle  has length 4. The longest common subsequence of X and Y is  \langle B,E,G,C,E,B \rangle .



 public class LCS{  
      public static String getLCS(String str1, String str2) {  
           StringBuilder sb = new StringBuilder();  
           if (str1 == null || str1.isEmpty() || str2 == null || str2.isEmpty())  
                return "";  
           // ignore case  
           str1 = str1.toLowerCase();  
           str2 = str2.toLowerCase();  
           // java initializes them already with 0  
           int[][] c = new int[str1.length()][str2.length()];  
           int maxlen = 0;  
           int lastSubsBegin = 0;  
           for (int i = 0; i < str1.length(); i++) {  
                for (int j = 0; j < str2.length(); j++) {  
                     if (str1.charAt(i) == str2.charAt(j)) {  
                          if ((i == 0) || (j == 0))  
                               c[i][j] = 1;  
                          else  
                               c[i][j] = 1 + c[i - 1][j - 1];  
                          if (c[i][j] > maxlen) {  
                               maxlen = c[i][j];  
                               int thisSubsBegin = i - c[i][j] + 1;  
                               if (lastSubsBegin == thisSubsBegin) {  
                                    //if the current LCS is the same as the last time this block ran  
                                    sb.append(str1.charAt(i));  
                               } else {  
                                    //this block resets the string builder if a different LCS is found  
                                    lastSubsBegin = thisSubsBegin;  
                                    sb = new StringBuilder();  
                                    sb.append(str1.substring(lastSubsBegin, i + 1));  
                               }  
                          }  
                     }  
                }  
           }  
           System.out.println("The DP table is: ");  
           for (int i=0; i<c.length; i++) {  
                for (int j=0; j<c[i].length; j++) {  
                     System.out.print(" " + c[i][j]);  
                }  
                System.out.println("");  
           }  
           return sb.toString();  
      }  
      public static void main(String args[]){  
           LCS m = new LCS();  
           System.out.println("The LCS is "+m.getLCS("complexity","xiterty"));  
      }  
 }  

Sunday, January 22, 2012

Dynamic Programming : Making coin change
1) I have  used "-1" to represent infinity. Hence I have an extra check to avoid the condition when "1 +(-1) = 0", because I want to treat "-1" as infinity and not number -1.



 public class MakeChange{  
      int[][] c;  
      public int[] a;  
      int sum;  
      int numCoins;  
      public MakeChange(int targetSum, int[] coins){  
           sum = targetSum;  
           numCoins = coins.length;  
           a = coins;  
           c = new int[numCoins][sum + 1];  
      }  
      public int getMinCoins(){  
           c[0][0] = 0;
           for(int i = 1; i <= sum; i++){  
                c[0][i] = -1; //This indicates infinite value, bcoz one cannot make sum of n using coin of value "0"  
           }  
           for(int i = 1; i < numCoins; i++){  
                for(int j = 1; j <= sum; j++){  
                     System.out.println("Trying to make change for "+j+" using coin "+a[i]);  
                     if(j < a[i]){ //sum to be made is less than coin value  
                          System.out.println("Assign value of coin "+c[i-1][j]+" which is "+c[i-1][j]);  
                          c[i][j] = c[i-1][j];  
                     }else{ //Make sum j using coin i or without using coin i and select the one with min coins  
                          int n = c[i][j-a[i]];  
                          if(n < 0){ //This check is required as I am using -1 for infinity  
                               c[i][j] = c[i-1][j];  
                          }else{  
                               System.out.println("Min of "+c[i-1][j]+" and "+(1+n));  
                               int min = findMin(c[i-1][j],1+n);  
                               c[i][j] = min;  
                          }  
                     }  
                }  
           }  
           System.out.println("The DP table is: ");  
           for (int i=0; i<c.length; i++) {  
                for (int j=0; j<c[i].length; j++) {  
                     System.out.print(" " + c[i][j]);  
                }  
                System.out.println("");  
           }  
           return c[numCoins - 1][sum];  
      }  
      private int findMin(int i, int j){  
           if(i < 0 && j < 0) {  
                return -1; //return infinity  
           }else if(i < 0 && j >=0){  
                return j;  
           }else if(j < 0 && i >=0){  
                return i;  
           }else if(i < j){  
                return i;  
           }else{  
                return j;  
           }  
      }  
      public static void main(String args[]){  
           int[] a = {1,2,4,8};  
           MakeChange m = new MakeChange(8,a);  
           System.out.println("The min # of coins are "+m.getMinCoins());  
      }  
 }