package jetbrains.mps.util;
/*Generated by MPS */
import java.util.List;
import jetbrains.mps.baseLanguage.tuples.runtime.Tuples;
import org.jetbrains.annotations.NotNull;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import java.util.ArrayList;
import jetbrains.mps.baseLanguage.tuples.runtime.MultiTuple;
import jetbrains.mps.internal.collections.runtime.Sequence;
import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes;
import java.util.Iterator;
import jetbrains.mps.baseLanguage.closures.runtime.YieldingIterator;
import jetbrains.mps.internal.collections.runtime.ISelector;
public class LongestCommonSubsequenceFinder<E> {
private List<E> myA;
private List<E> myB;
private int[][] myCommonLengths;
private List<Tuples._2<Integer, Integer>> myCommonIndices;
private List<Tuples._2<Tuples._2<Integer, Integer>, Tuples._2<Integer, Integer>>> myDifferentIndices;
private List<Tuples._2<Iterable<E>, Iterable<E>>> myDifferentSubsequences;
public LongestCommonSubsequenceFinder(@NotNull List<E> a, @NotNull List<E> b) {
myA = a;
myB = b;
}
@NotNull
public int[][] getCommonLengths() {
// This method finds lengths of longest common subsequence for each
// i first elements of a and j first elements of b. This lengths are in result
// two-dimensional array at [i][j] position
if (myCommonLengths == null) {
myCommonLengths = new int[ListSequence.fromList(myA).count() + 1][ListSequence.fromList(myB).count() + 1];
for (int i = 1; i < ListSequence.fromList(myA).count() + 1; i++) {
for (int j = 1; j < ListSequence.fromList(myB).count() + 1; j++) {
if (EqualUtil.equals(ListSequence.fromList(myA).getElement(i - 1), ListSequence.fromList(myB).getElement(j - 1))) {
myCommonLengths[i][j] = myCommonLengths[i - 1][j - 1] + 1;
} else {
myCommonLengths[i][j] = Math.max(myCommonLengths[i - 1][j], myCommonLengths[i][j - 1]);
}
}
}
}
return myCommonLengths;
}
@NotNull
public List<Tuples._2<Integer, Integer>> getCommonIndices() {
// This method finds pairs of indices in a and b lists which are
// elements of longest common subsequence
if (myCommonIndices == null) {
getCommonLengths();
List<Tuples._2<Integer, Integer>> indices = ListSequence.fromList(new ArrayList<Tuples._2<Integer, Integer>>());
int i = ListSequence.fromList(myA).count();
int j = ListSequence.fromList(myB).count();
while (i > 0 && j > 0) {
if (EqualUtil.equals(ListSequence.fromList(myA).getElement(i - 1), ListSequence.fromList(myB).getElement(j - 1))) {
ListSequence.fromList(indices).addElement(MultiTuple.<Integer,Integer>from(i - 1, j - 1));
i--;
j--;
} else {
if (myCommonLengths[i][j - 1] == myCommonLengths[i][j]) {
j--;
} else {
i--;
}
}
}
myCommonIndices = ListSequence.fromList(indices).reversedList();
}
return myCommonIndices;
}
@NotNull
public List<Tuples._2<Tuples._2<Integer, Integer>, Tuples._2<Integer, Integer>>> getDifferentIndices() {
// This methods finds pairs of begin-end pairs of original lists a and b
// which are not included into longest common subsequence
if (myDifferentIndices == null) {
myDifferentIndices = ListSequence.fromList(new ArrayList<Tuples._2<Tuples._2<Integer, Integer>, Tuples._2<Integer, Integer>>>());
int i = 0;
int j = 0;
for (Tuples._2<Integer, Integer> f : ListSequence.fromList(getCommonIndices()).concat(Sequence.fromIterable(new _FunctionTypes._return_P0_E0<Iterable<Tuples._2<Integer, Integer>>>() {
public Iterable<Tuples._2<Integer, Integer>> invoke() {
return new Iterable<Tuples._2<Integer, Integer>>() {
public Iterator<Tuples._2<Integer, Integer>> iterator() {
return new YieldingIterator<Tuples._2<Integer, Integer>>() {
private int __CP__ = 0;
protected boolean moveToNext() {
__loop__:
do {
__switch__:
switch (this.__CP__) {
case -1:
assert false : "Internal error";
return false;
case 2:
this.__CP__ = 1;
this.yield(MultiTuple.<Integer,Integer>from(ListSequence.fromList(myA).count(), ListSequence.fromList(myB).count()));
return true;
case 0:
this.__CP__ = 2;
break;
default:
break __loop__;
}
} while (true);
return false;
}
};
}
};
}
}.invoke()))) {
if (!((i == (int) f._0() && j == (int) f._1()))) {
ListSequence.fromList(myDifferentIndices).addElement(MultiTuple.<Tuples._2<Integer, Integer>,Tuples._2<Integer, Integer>>from(MultiTuple.<Integer,Integer>from(i, (int) f._0()), MultiTuple.<Integer,Integer>from(j, (int) f._1())));
}
i = (int) f._0() + 1;
j = (int) f._1() + 1;
}
}
return myDifferentIndices;
}
@NotNull
public List<Tuples._2<Iterable<E>, Iterable<E>>> getDifferentSubsequences() {
// This methods finds pairs of subsequences of original lists a and b
// which are not included into longest common subsequence
if (myDifferentSubsequences == null) {
myDifferentSubsequences = ListSequence.fromList(getDifferentIndices()).select(new ISelector<Tuples._2<Tuples._2<Integer, Integer>, Tuples._2<Integer, Integer>>, Tuples._2<Iterable<E>, Iterable<E>>>() {
public Tuples._2<Iterable<E>, Iterable<E>> select(Tuples._2<Tuples._2<Integer, Integer>, Tuples._2<Integer, Integer>> pair) {
return MultiTuple.<Iterable<E>,Iterable<E>>from(ListSequence.fromList(myA).page((int) pair._0()._0(), (int) pair._0()._1()), ListSequence.fromList(myB).page((int) pair._1()._0(), (int) pair._1()._1()));
}
}).toListSequence();
}
return myDifferentSubsequences;
}
}