comparison src/goodjava/util/LineDiff.java @ 1807:ffa28e2155bb

add line_diff
author Franklin Schmidt <fschmidt@gmail.com>
date Sun, 12 May 2024 15:25:29 -0600
parents
children 69623c62aa34
comparison
equal deleted inserted replaced
1806:3b7a8f1cc887 1807:ffa28e2155bb
1 package goodjava.util;
2
3 import java.util.List;
4 import java.util.ArrayList;
5 import java.io.BufferedReader;
6 import java.io.StringReader;
7 import java.io.IOException;
8
9
10 public final class LineDiff {
11 public static final char DELETE = '<';
12 public static final char INSERT = '>';
13
14 public static class Diff {
15 public final char operation;
16 public final int line;
17 public final String text;
18
19 private Diff(char operation,int line,String text) {
20 this.operation = operation;
21 this.line = line;
22 this.text = text;
23 }
24 }
25
26 public static String[] stringToLines(String s) {
27 List<String> list = new ArrayList<String>();
28 BufferedReader br = new BufferedReader(new StringReader(s));
29 String line;
30 try {
31 while( (line = br.readLine()) != null ) {
32 list.add(line);
33 }
34 } catch(IOException e) {
35 throw new RuntimeException(e);
36 }
37 return list.toArray(new String[list.size()]);
38 }
39
40 public static List<Diff> diff(String oldStr,String newStr) {
41 return diff( stringToLines(oldStr), stringToLines(newStr) );
42 }
43
44 // https://introcs.cs.princeton.edu/java/23recursion/Diff.java.html
45 public static List<Diff> diff(String[] oldLines,String[] newLines) {
46 List<Diff> diffs = new ArrayList<Diff>();
47
48 int nOld = oldLines.length;
49 int nNew = newLines.length;
50
51 // opt[iOld][iNew] = length of LCS of x[iOld..nOld] and y[iNew..nNew]
52 int[][] opt = new int[nOld+1][nNew+1];
53
54 // compute length of LCS and all subproblems via dynamic programming
55 for (int iOld = nOld-1; iOld >= 0; iOld--) {
56 for (int iNew = nNew-1; iNew >= 0; iNew--) {
57 if (oldLines[iOld].equals(newLines[iNew]))
58 opt[iOld][iNew] = opt[iOld+1][iNew+1] + 1;
59 else
60 opt[iOld][iNew] = Math.max(opt[iOld+1][iNew], opt[iOld][iNew+1]);
61 }
62 }
63
64 int iOld = 0, iNew = 0;
65 while (iOld < nOld && iNew < nNew) {
66 if (oldLines[iOld].equals(newLines[iNew])) {
67 iOld++;
68 iNew++;
69 } else if (opt[iOld+1][iNew] >= opt[iOld][iNew+1]) {
70 diffs.add( new Diff( DELETE, iOld+1, oldLines[iOld] ) );
71 iOld++;
72 } else {
73 diffs.add( new Diff( INSERT, iOld+1, newLines[iNew] ) );
74 iNew++;
75 }
76 }
77
78 // dump out one remainder of one string if the other is exhausted
79 while( iOld < nOld ) {
80 diffs.add( new Diff( DELETE, iOld+1, oldLines[iOld] ) );
81 iOld++;
82 }
83 while( iNew < nNew ) {
84 diffs.add( new Diff( INSERT, nOld+1, newLines[iNew] ) );
85 iNew++;
86 }
87
88 return diffs;
89 }
90 }