package algorithms;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.IntStream;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsEqual.equalTo;
public class LevenshteinDistanceTest {
@Test
public void distanceOfTwoEqualStrings() throws Exception {
assertThat(levenshteinDistance("", ""), equalTo(0));
}
@Test
public void name() throws Exception {
assertThat(levenshteinDistance("", "abc"), equalTo(3));
assertThat(levenshteinDistance("abc", ""), equalTo(3));
}
@Test
public void replaceCostsOne() throws Exception {
assertThat(levenshteinDistance("a", "b"), equalTo(1));
}
@Test
public void longerExample() throws Exception {
assertThat(levenshteinDistance("Tier", "Tor"), equalTo(2));
assertThat(levenshteinDistance("sitting", "kitten"), equalTo(3));
assertThat(levenshteinDistance("Sunday", "Saturday"), equalTo(3));
}
private final int PriceForKeepAsIs = 0;
private final int PriceForInsert = 1;
private final int PriceForRemove = 1;
private final int PriceForReplace = 1;
private int levenshteinDistance(String one, String two) {
int[][] matrix = new int[one.length() + 1][two.length() + 1];
for (int i = 0; i <= one.length(); i = i + PriceForInsert) {
matrix[i][0] = i;
}
for (int j = 0; j <= two.length(); j = j + PriceForInsert) {
matrix[0][j] = j;
}
char[] oneArray = ("ε" + one).toCharArray();
char[] twoArray = ("ε" + two).toCharArray();
for (int i = 1; i <= one.length(); ++i) {
for (int j = 1; j <= two.length(); ++j) {
List<Integer> candidates = new ArrayList<>(3);
int i1 = matrix[i - 1][j - 1];
if (oneArray[i] == twoArray[j]) {
candidates.add(i1 + PriceForKeepAsIs);
} else {
candidates.add(i1 + PriceForReplace);
}
candidates.add(matrix[i][j - 1] + PriceForInsert);
candidates.add(matrix[i - 1][j] + PriceForRemove);
matrix[i][j] = candidates.stream().min(Comparator.naturalOrder()).get();
}
}
StringBuilder matrixString = new StringBuilder();
StringBuilder headRow = new StringBuilder();
headRow.append(" ");
for (int i = 0; i < twoArray.length; i++) {
headRow.append(twoArray[i]).append(" ");
}
matrixString.append(headRow.toString()).append("\n");
for (int i = 0; i <= one.length(); ++i) {
StringBuilder rowBuilder = new StringBuilder();
rowBuilder.append(oneArray[i]).append(" ");
for (int j = 0; j <= two.length(); ++j) {
rowBuilder.append(matrix[i][j] + " ");
}
matrixString.append(rowBuilder.toString() + "\n");
}
System.out.println(matrixString.toString());
return matrix[one.length()][two.length()];
}
}