package cd;

// NOTE: This code was adapted from the code found at 
//    http://www.cs.princeton.edu/introcs/96optimization/Diff.java.html

/*************************************************************************
 *  Compilation:  javac Diff
 *  Execution:    java Diff filename1 filename2
 *  Dependencies: In.java
 *  
 *  Reads in two files and compute their diff.
 *  A bare bones version.
 * 
 *  % java Diff input1.txt input2.txt
 * 
 *
 *  Limitations
 *  -----------
 *   - Could hash the lines to avoid potentially more expensive 
 *     string comparisons.
 *
 *************************************************************************/

public class Diff {
	
	public static String computeDiff(String in0, String in1) {
		StringBuffer out = new StringBuffer();
		
        // break into lines of each file
        String[] x = in0.split("\\n");
        String[] y = in1.split("\\n");

        // number of lines of each file
        int M = x.length;
        int N = y.length;

        // opt[i][j] = length of LCS of x[i..M] and y[j..N]
        int[][] opt = new int[M+1][N+1];

        // compute length of LCS and all subproblems via dynamic programming
        for (int i = M-1; i >= 0; i--) {
            for (int j = N-1; j >= 0; j--) {
                if (x[i].equals(y[j]))
                    opt[i][j] = opt[i+1][j+1] + 1;
                else 
                    opt[i][j] = Math.max(opt[i+1][j], opt[i][j+1]);
            }
        }

        // recover LCS itself and print out non-matching lines to standard output
        boolean lineNumber = false;
        int i = 0, j = 0;
        while(i < M && j < N) {
            if (x[i].equals(y[j])) {
                i++;
                j++;
                lineNumber = false;
            }
            else {
            	if (!lineNumber) {
            		out.append(String.format(
            				"At line %3d / %3d:\n", i+1, j+1));
            		lineNumber = true;
            	}
            	assert lineNumber;
            	if (opt[i+1][j] >= opt[i][j+1]) 
            		out.append("< " + x[i++] + "\n");
            	else                                 
            		out.append("> " + y[j++] + "\n");
            }
        }

        // dump out one remainder of one string if the other is exhausted
    	if (!lineNumber) {
    		out.append(String.format("Line %3d / %3d:\n", i+1, j+1));
    	}
        while(i < M || j < N) {
            if      (i == M) 
            	out.append("> " + y[j++] + "\n");
            else if (j == N) 
            	out.append("< " + x[i++] + "\n");
        }
        
        return out.toString();
    }

}
