Implement RecursiveFullyUsedArrayProcessor
This commit is contained in:
		
							parent
							
								
									ab87b2e964
								
							
						
					
					
						commit
						7f5707b9c0
					
				
					 4 changed files with 618 additions and 44 deletions
				
			
		|  | @ -1,5 +1,6 @@ | ||||||
| package aud.exam.prep.array; | package aud.exam.prep.array; | ||||||
| 
 | 
 | ||||||
|  | import aud.exam.prep.Pair; | ||||||
| import aud.exam.prep.SequenceProcessor; | import aud.exam.prep.SequenceProcessor; | ||||||
| 
 | 
 | ||||||
| abstract class FullyUsedArrayProcessor<T> implements SequenceProcessor<T, FullyUsedArray<T>> { | abstract class FullyUsedArrayProcessor<T> implements SequenceProcessor<T, FullyUsedArray<T>> { | ||||||
|  | @ -24,4 +25,34 @@ abstract class FullyUsedArrayProcessor<T> implements SequenceProcessor<T, FullyU | ||||||
|         return () -> |         return () -> | ||||||
|             new ArrayIterator<>(array.theArray, 0, array.theArray.length); |             new ArrayIterator<>(array.theArray, 0, array.theArray.length); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     protected Pair<FullyUsedArray<T>, FullyUsedArray<T>> createPairForDivideAlternating(FullyUsedArray<T> array) { | ||||||
|  |         var p = new Pair<FullyUsedArray<T>, FullyUsedArray<T>>(); | ||||||
|  |         p.fst = new FullyUsedArray<>(); | ||||||
|  |         p.snd = new FullyUsedArray<>(); | ||||||
|  | 
 | ||||||
|  |         p.snd.theArray = Arrays.newArray(array.theArray.length / 2); | ||||||
|  |         p.fst.theArray = Arrays.newArray(array.theArray.length - p.snd.theArray.length); | ||||||
|  |         return p; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected Pair<FullyUsedArray<T>, FullyUsedArray<T>> createPairForDivideByPivot(int less, int greater) { | ||||||
|  |         var p = new Pair<FullyUsedArray<T>, FullyUsedArray<T>>(); | ||||||
|  |         p.fst = new FullyUsedArray<>(); | ||||||
|  |         p.snd = new FullyUsedArray<>(); | ||||||
|  | 
 | ||||||
|  |         p.fst.theArray = Arrays.newArray(less); | ||||||
|  |         p.snd.theArray = Arrays.newArray(greater); | ||||||
|  |         return p; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected Pair<FullyUsedArray<T>, FullyUsedArray<T>> createPairForDivideAlternatingByRuns(FullyUsedArray<T> array, int elementsInFst) { | ||||||
|  |         var p = new Pair<FullyUsedArray<T>, FullyUsedArray<T>>(); | ||||||
|  |         p.fst = new FullyUsedArray<>(); | ||||||
|  |         p.snd = new FullyUsedArray<>(); | ||||||
|  | 
 | ||||||
|  |         p.fst.theArray = Arrays.newArray(elementsInFst); | ||||||
|  |         p.snd.theArray = Arrays.newArray(array.theArray.length - elementsInFst); | ||||||
|  |         return p; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -195,6 +195,7 @@ public class IterativeFullyUsedArrayProcessor<T> extends FullyUsedArrayProcessor | ||||||
|         if (b.theArray.length < a.theArray.length) { |         if (b.theArray.length < a.theArray.length) { | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|         for (int i = 0; i < a.theArray.length; i++) { |         for (int i = 0; i < a.theArray.length; i++) { | ||||||
|             if (cmp.compare(a.theArray[i], b.theArray[i]) > 0) { |             if (cmp.compare(a.theArray[i], b.theArray[i]) > 0) { | ||||||
|                 return false; |                 return false; | ||||||
|  | @ -416,12 +417,7 @@ public class IterativeFullyUsedArrayProcessor<T> extends FullyUsedArrayProcessor | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public Pair<FullyUsedArray<T>, FullyUsedArray<T>> divideAlternating(FullyUsedArray<T> array) { |     public Pair<FullyUsedArray<T>, FullyUsedArray<T>> divideAlternating(FullyUsedArray<T> array) { | ||||||
|         var p = new Pair<FullyUsedArray<T>, FullyUsedArray<T>>(); |         var p = createPairForDivideAlternating(array); | ||||||
|         p.fst = new FullyUsedArray<>(); |  | ||||||
|         p.snd = new FullyUsedArray<>(); |  | ||||||
| 
 |  | ||||||
|         p.snd.theArray = Arrays.newArray(array.theArray.length / 2); |  | ||||||
|         p.fst.theArray = Arrays.newArray(array.theArray.length - p.snd.theArray.length); |  | ||||||
| 
 | 
 | ||||||
|         for (int i = 0; i < array.theArray.length; i++) { |         for (int i = 0; i < array.theArray.length; i++) { | ||||||
|             if (i % 2 == 0) { |             if (i % 2 == 0) { | ||||||
|  | @ -436,10 +432,6 @@ public class IterativeFullyUsedArrayProcessor<T> extends FullyUsedArrayProcessor | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public Pair<FullyUsedArray<T>, FullyUsedArray<T>> divideAlternatingByRuns(FullyUsedArray<T> array, Comparator<T> cmp) { |     public Pair<FullyUsedArray<T>, FullyUsedArray<T>> divideAlternatingByRuns(FullyUsedArray<T> array, Comparator<T> cmp) { | ||||||
|         var p = new Pair<FullyUsedArray<T>, FullyUsedArray<T>>(); |  | ||||||
|         p.fst = new FullyUsedArray<>(); |  | ||||||
|         p.snd = new FullyUsedArray<>(); |  | ||||||
| 
 |  | ||||||
|         var runInFst = true; |         var runInFst = true; | ||||||
|         var elementsInFst = 0; |         var elementsInFst = 0; | ||||||
| 
 | 
 | ||||||
|  | @ -453,8 +445,7 @@ public class IterativeFullyUsedArrayProcessor<T> extends FullyUsedArrayProcessor | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         p.fst.theArray = Arrays.newArray(elementsInFst); |         var p = createPairForDivideAlternatingByRuns(array, elementsInFst); | ||||||
|         p.snd.theArray = Arrays.newArray(array.theArray.length - elementsInFst); |  | ||||||
| 
 | 
 | ||||||
|         runInFst = true; |         runInFst = true; | ||||||
|         var indexA = 0; |         var indexA = 0; | ||||||
|  | @ -477,10 +468,6 @@ public class IterativeFullyUsedArrayProcessor<T> extends FullyUsedArrayProcessor | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public Pair<FullyUsedArray<T>, FullyUsedArray<T>> divideByPivot(FullyUsedArray<T> array, T pivot, Comparator<T> cmp) { |     public Pair<FullyUsedArray<T>, FullyUsedArray<T>> divideByPivot(FullyUsedArray<T> array, T pivot, Comparator<T> cmp) { | ||||||
|         var p = new Pair<FullyUsedArray<T>, FullyUsedArray<T>>(); |  | ||||||
|         p.fst = new FullyUsedArray<>(); |  | ||||||
|         p.snd = new FullyUsedArray<>(); |  | ||||||
| 
 |  | ||||||
|         var less = 0; |         var less = 0; | ||||||
|         var greater = 0; |         var greater = 0; | ||||||
| 
 | 
 | ||||||
|  | @ -494,8 +481,7 @@ public class IterativeFullyUsedArrayProcessor<T> extends FullyUsedArrayProcessor | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         p.fst.theArray = Arrays.newArray(less); |         var p = createPairForDivideByPivot(less, greater); | ||||||
|         p.snd.theArray = Arrays.newArray(greater); |  | ||||||
| 
 | 
 | ||||||
|         var indexA = 0; |         var indexA = 0; | ||||||
|         var indexB = 0; |         var indexB = 0; | ||||||
|  |  | ||||||
|  | @ -4,142 +4,698 @@ import aud.exam.prep.Pair; | ||||||
| 
 | 
 | ||||||
| import java.util.Comparator; | import java.util.Comparator; | ||||||
| import java.util.Iterator; | import java.util.Iterator; | ||||||
|  | import java.util.Objects; | ||||||
| 
 | 
 | ||||||
| public class RecursiveFullyUsedArrayProcessor<T> extends FullyUsedArrayProcessor<T> { | public class RecursiveFullyUsedArrayProcessor<T> extends FullyUsedArrayProcessor<T> { | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public boolean find(FullyUsedArray<T> array, T t) { |     public boolean find(FullyUsedArray<T> array, T t) { | ||||||
|         return false; |         return findRec(array, t, 0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private boolean findRec(FullyUsedArray<T> array, T t, int index) { | ||||||
|  |         if (index >= array.theArray.length) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         if (Objects.equals(array.theArray[index], t)) { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         return findRec(array, t, index+1); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public boolean findBinary(FullyUsedArray<T> array, T t, Comparator<T> cmp) { |     public boolean findBinary(FullyUsedArray<T> array, T t, Comparator<T> cmp) { | ||||||
|         return false; |         return findBinaryRec(array, t, cmp, 0, array.theArray.length-1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private boolean findBinaryRec(FullyUsedArray<T> array, T t, Comparator<T> cmp, int start, int end) { | ||||||
|  |         if (start > end) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         var index = (start+end) / 2; | ||||||
|  |         var c = cmp.compare(t, array.theArray[index]); | ||||||
|  | 
 | ||||||
|  |         if (c == 0) { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         if (c > 0) { | ||||||
|  |             return findBinaryRec(array, t, cmp, index+1, end); | ||||||
|  |         } | ||||||
|  |         return findBinaryRec(array, t, cmp, start, index-1); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public boolean override(FullyUsedArray<T> array, T from, T to) { |     public boolean override(FullyUsedArray<T> array, T from, T to) { | ||||||
|         return false; |         return overrideRec(array, from, to, 0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private boolean overrideRec(FullyUsedArray<T> array, T from, T to, int index) { | ||||||
|  |         if (index >= array.theArray.length) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         if (Objects.equals(array.theArray[index], from)) { | ||||||
|  |             array.theArray[index] = to; | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         return overrideRec(array, from, to, index+1); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public boolean overrideAll(FullyUsedArray<T> array, T from, T to) { |     public boolean overrideAll(FullyUsedArray<T> array, T from, T to) { | ||||||
|         return false; |         return overrideAllRec(array, from, to, 0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private boolean overrideAllRec(FullyUsedArray<T> array, T from, T to, int index) { | ||||||
|  |         if (index >= array.theArray.length) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         var modified = false; | ||||||
|  |         if (Objects.equals(array.theArray[index], from)) { | ||||||
|  |             array.theArray[index] = to; | ||||||
|  |             modified = true; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return overrideAllRec(array, from, to, index+1) || modified; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public void insertInOrder(FullyUsedArray<T> array, T t, Comparator<T> cmp) { |     public void insertInOrder(FullyUsedArray<T> array, T t, Comparator<T> cmp) { | ||||||
|  |         T[] newArray = Arrays.newArray(array.theArray.length+1); | ||||||
|  |         insertElementsInOrder(array.theArray, newArray, t, cmp, 0); | ||||||
|  |         array.theArray = newArray; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|  |     private void insertElementsInOrder(T[] oldArray, T[] newArray, T t, Comparator<T> cmp, int index) { | ||||||
|  |         if (index == oldArray.length) { | ||||||
|  |             newArray[index] = t; | ||||||
|  |         } else if (cmp.compare(t, oldArray[index]) < 0) { | ||||||
|  |             newArray[index] = t; | ||||||
|  |             insertRestOfElements(oldArray, newArray, index); | ||||||
|  |         } else { | ||||||
|  |             newArray[index] = oldArray[index]; | ||||||
|  |             insertElementsInOrder(oldArray, newArray, t, cmp, index+1); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void insertRestOfElements(T[] oldArray, T[] newArray, int index) { | ||||||
|  |         if (index >= oldArray.length) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         newArray[index+1] = oldArray[index]; | ||||||
|  |         insertRestOfElements(oldArray, newArray, index+1); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public boolean remove(FullyUsedArray<T> array, T t) { |     public boolean remove(FullyUsedArray<T> array, T t) { | ||||||
|         return false; |         if (!find(array, t)) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         T[] newArray = Arrays.newArray(array.theArray.length-1); | ||||||
|  |         removeRec(array.theArray, newArray, t, 0); | ||||||
|  | 
 | ||||||
|  |         array.theArray = newArray; | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void removeRec(T[] oldArray, T[] newArray, T t, int index) { | ||||||
|  |         if (Objects.equals(oldArray[index], t)) { | ||||||
|  |             copyRestOfElementsForRemove(oldArray, newArray, index+1); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         newArray[index] = oldArray[index]; | ||||||
|  |         removeRec(oldArray, newArray, t, index+1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void copyRestOfElementsForRemove(T[] oldArray, T[] newArray, int index) { | ||||||
|  |         if (index >= oldArray.length) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         newArray[index-1] = oldArray[index]; | ||||||
|  |         copyRestOfElementsForRemove(oldArray, newArray, index+1); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public boolean removeAll(FullyUsedArray<T> array, T t) { |     public boolean removeAll(FullyUsedArray<T> array, T t) { | ||||||
|         return false; |         var size = countRemainingElementsForRemoveAll(array.theArray, t, 0); | ||||||
|  |         if (size == array.theArray.length) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         T[] newArray = Arrays.newArray(size); | ||||||
|  | 
 | ||||||
|  |         removeAllRec(array.theArray, 0, newArray, 0, t); | ||||||
|  | 
 | ||||||
|  |         array.theArray = newArray; | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void removeAllRec(T[] src, int indexSrc, T[] dst, int indexDst, T t) { | ||||||
|  |         if (indexSrc >= src.length) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (!Objects.equals(t, src[indexSrc])) { | ||||||
|  |             dst[indexDst] = src[indexSrc]; | ||||||
|  |             indexDst++; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         removeAllRec(src, indexSrc+1, dst, indexDst, t); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private int countRemainingElementsForRemoveAll(T[] array, T t, int index) { | ||||||
|  |         if (index >= array.length) { | ||||||
|  |             return 0; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         var current = 0; | ||||||
|  |         if (!Objects.equals(t, array[index])) { | ||||||
|  |             current++; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return current + countRemainingElementsForRemoveAll(array, t, index+1); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public boolean isAscending(FullyUsedArray<T> array, Comparator<T> cmp) { |     public boolean isAscending(FullyUsedArray<T> array, Comparator<T> cmp) { | ||||||
|         return false; |         if (array.theArray.length < 2) { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return isAscendingRec(array.theArray, cmp, 0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private boolean isAscendingRec(T[] array, Comparator<T> cmp, int index) { | ||||||
|  |         if (index >= array.length-1) { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (cmp.compare(array[index], array[index+1]) > 0) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return isAscendingRec(array, cmp, index+1); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public T max(FullyUsedArray<T> array, Comparator<T> cmp) { |     public T max(FullyUsedArray<T> array, Comparator<T> cmp) { | ||||||
|         return null; |         if (array.theArray.length == 0) { | ||||||
|  |             throw new IllegalArgumentException("The sequence may not be empty"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return maxRec(array.theArray, cmp, 1, array.theArray[0]); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private T maxRec(T[] array, Comparator<T> cmp, int index, T max) { | ||||||
|  |         if (index >= array.length) { | ||||||
|  |             return max; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (cmp.compare(max, array[index]) < 0) { | ||||||
|  |             max = array[index]; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return maxRec(array, cmp, index+1, max); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public T secondMax(FullyUsedArray<T> array, Comparator<T> cmp) { |     public T secondMax(FullyUsedArray<T> array, Comparator<T> cmp) { | ||||||
|         return null; |         if (array.theArray.length < 2) { | ||||||
|  |             throw new IllegalArgumentException("The sequence must contains at least 2 elements"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         T secondMax, max; | ||||||
|  |         if (cmp.compare(array.theArray[0], array.theArray[1]) < 0) { | ||||||
|  |             secondMax = array.theArray[0]; | ||||||
|  |             max = array.theArray[1]; | ||||||
|  |         } else { | ||||||
|  |             secondMax = array.theArray[1]; | ||||||
|  |             max = array.theArray[0]; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         return secondMaxRec(array.theArray, cmp, 2, max, secondMax); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private T secondMaxRec(T[] array, Comparator<T> cmp, int index, T max, T secondMax) { | ||||||
|  |         if (index >= array.length) { | ||||||
|  |             return secondMax; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (cmp.compare(max, array[index]) < 0) { | ||||||
|  |             secondMax = max; | ||||||
|  |             max = array[index]; | ||||||
|  |         } else if (cmp.compare(secondMax, array[index]) < 0) { | ||||||
|  |             secondMax = array[index]; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return secondMaxRec(array, cmp, index+1, max, secondMax); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public boolean isItemWiseLessOrEqual(FullyUsedArray<T> a, FullyUsedArray<T> b, Comparator<T> cmp) { |     public boolean isItemWiseLessOrEqual(FullyUsedArray<T> a, FullyUsedArray<T> b, Comparator<T> cmp) { | ||||||
|         return false; |         if (b.theArray.length < a.theArray.length) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return isItemWiseLessOrEqualRec(a.theArray, b.theArray, 0, cmp); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private boolean isItemWiseLessOrEqualRec(T[] a, T[] b, int index, Comparator<T> cmp) { | ||||||
|  |         if (index >= a.length) { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (cmp.compare(a[index], b[index]) > 0) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return isItemWiseLessOrEqualRec(a, b, index+1, cmp); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public boolean isItemWiseLess(FullyUsedArray<T> a, FullyUsedArray<T> b, Comparator<T> cmp) { |     public boolean isItemWiseLess(FullyUsedArray<T> a, FullyUsedArray<T> b, Comparator<T> cmp) { | ||||||
|         return false; |         if (b.theArray.length < a.theArray.length) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return isItemWiseLessRec(a.theArray, b.theArray, 0, cmp); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private boolean isItemWiseLessRec(T[] a, T[] b, int index, Comparator<T> cmp) { | ||||||
|  |         if (index >= a.length) { | ||||||
|  |             return index < b.length; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         var c = cmp.compare(a[index], b[index]); | ||||||
|  | 
 | ||||||
|  |         if (c > 0) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (c < 0) { | ||||||
|  |             return isItemWiseLessOrEqualRec(a, b, index+1, cmp); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return isItemWiseLessRec(a, b, index+1, cmp); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public boolean isLexSmaller(FullyUsedArray<T> a, FullyUsedArray<T> b, Comparator<T> cmp) { |     public boolean isLexSmaller(FullyUsedArray<T> a, FullyUsedArray<T> b, Comparator<T> cmp) { | ||||||
|         return false; |         return isLexSmallerRec(a.theArray, 0, b.theArray, 0, cmp); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private boolean isLexSmallerRec(T[] a, int indexA, T[] b, int indexB, Comparator<T> cmp) { | ||||||
|  |         if (indexA >= a.length) { | ||||||
|  |             return indexB < b.length; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (indexB >= b.length) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         var c = cmp.compare(a[indexA], b[indexB]); | ||||||
|  | 
 | ||||||
|  |         if (c > 0) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (c < 0) { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return isLexSmallerRec(a, indexA+1, b, indexB+1, cmp); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public void exchangePairs(FullyUsedArray<T> array) { |     public void exchangePairs(FullyUsedArray<T> array) { | ||||||
|  |         exchangePairsRec(array.theArray, 1); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|  |     private void exchangePairsRec(T[] array, int index) { | ||||||
|  |         if (index >= array.length-1) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         T t = array[index]; | ||||||
|  |         array[index] = array[index +1]; | ||||||
|  |         array[index +1] = t; | ||||||
|  | 
 | ||||||
|  |         exchangePairsRec(array, index+2); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public void rotateTriples(FullyUsedArray<T> array) { |     public void rotateTriples(FullyUsedArray<T> array) { | ||||||
|  |         rotateTriplesRec(array.theArray, 1); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|  |     private void rotateTriplesRec(T[] array, int index) { | ||||||
|  |         if (index >= array.length - 2) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         T t = array[index+2]; | ||||||
|  |         array[index+2] = array[index+1]; | ||||||
|  |         array[index+1] = array[index]; | ||||||
|  |         array[index] = t; | ||||||
|  | 
 | ||||||
|  |         rotateTriplesRec(array, index+3); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public void removeEverySecond(FullyUsedArray<T> array) { |     public void removeEverySecond(FullyUsedArray<T> array) { | ||||||
|  |         T[] newArray = Arrays.newArray(array.theArray.length - array.theArray.length / 2); | ||||||
| 
 | 
 | ||||||
|  |         removeEverySecondRec(array.theArray, newArray, 0); | ||||||
|  | 
 | ||||||
|  |         array.theArray = newArray; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void removeEverySecondRec(T[] oldArray, T[] newArray, int index) { | ||||||
|  |         if (index >= newArray.length) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         newArray[index] = oldArray[index*2]; | ||||||
|  |         removeEverySecondRec(oldArray, newArray, index+1); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public void doubleAllKeys(FullyUsedArray<T> array) { |     public void doubleAllKeys(FullyUsedArray<T> array) { | ||||||
|  |         T[] newArray = Arrays.newArray(array.theArray.length * 2); | ||||||
| 
 | 
 | ||||||
|  |         doubleAllKeysRec(array.theArray, newArray, 0); | ||||||
|  | 
 | ||||||
|  |         array.theArray = newArray; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void doubleAllKeysRec(T[] array, T[] newArray, int index) { | ||||||
|  |         if (index >= array.length) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         newArray[index * 2] = array[index]; | ||||||
|  |         newArray[index * 2 + 1] = array[index]; | ||||||
|  | 
 | ||||||
|  |         doubleAllKeysRec(array, newArray, index+1); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public FullyUsedArray<T> rotateRight(FullyUsedArray<T> array) { |     public FullyUsedArray<T> rotateRight(FullyUsedArray<T> array) { | ||||||
|         return null; |         if (array.theArray.length == 0) { | ||||||
|  |             return array; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         T t = array.theArray[array.theArray.length-1]; | ||||||
|  | 
 | ||||||
|  |         rotateRightRec(array.theArray, array.theArray.length-1); | ||||||
|  | 
 | ||||||
|  |         array.theArray[0] = t; | ||||||
|  |         return array; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void rotateRightRec(T[] array, int index) { | ||||||
|  |         if (index < 1) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         array[index] = array[index-1]; | ||||||
|  |         rotateRightRec(array, index-1); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public FullyUsedArray<T> rotateLeft(FullyUsedArray<T> array) { |     public FullyUsedArray<T> rotateLeft(FullyUsedArray<T> array) { | ||||||
|         return null; |         if (array.theArray.length == 0) { | ||||||
|  |             return array; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         T t = array.theArray[0]; | ||||||
|  | 
 | ||||||
|  |         rotateLeftRec(array.theArray, 0); | ||||||
|  | 
 | ||||||
|  |         array.theArray[array.theArray.length-1] = t; | ||||||
|  |         return array; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void rotateLeftRec(T[] array, int index) { | ||||||
|  |         if (index >= array.length-1) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         array[index] = array[index+1]; | ||||||
|  |         rotateLeftRec(array, index+1); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public void removeDuplicates(FullyUsedArray<T> array) { |     public void removeDuplicates(FullyUsedArray<T> array) { | ||||||
|  |         if (array.theArray.length < 2) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|  |         var count = 1 + countRemainingElementsForRemoveDuplicates(array.theArray, 1); | ||||||
|  | 
 | ||||||
|  |         T[] newArray = Arrays.newArray(count); | ||||||
|  |         newArray[0] = array.theArray[0]; | ||||||
|  | 
 | ||||||
|  |         removeDuplicatesRec(array.theArray, newArray, 1, 1); | ||||||
|  | 
 | ||||||
|  |         array.theArray = newArray; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void removeDuplicatesRec(T[] array, T[] newArray, int src, int dst) { | ||||||
|  |         if (src >= array.length) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (!Objects.equals(array[src], array[src-1])) { | ||||||
|  |             newArray[dst] = array[src]; | ||||||
|  |             dst++; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         removeDuplicatesRec(array, newArray, src+1, dst); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private int countRemainingElementsForRemoveDuplicates(T[] array, int index) { | ||||||
|  |         if (index >= array.length) { | ||||||
|  |             return 0; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         var current = 0; | ||||||
|  |         if (!Objects.equals(array[index], array[index-1])) { | ||||||
|  |             current++; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return current + countRemainingElementsForRemoveDuplicates(array, index+1); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public FullyUsedArray<T> invert(FullyUsedArray<T> array) { |     public FullyUsedArray<T> invert(FullyUsedArray<T> array) { | ||||||
|         return null; |         invertRec(array.theArray, 0); | ||||||
|  |         return array; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void invertRec(T[] array, int index) { | ||||||
|  |         if (index >= array.length / 2) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         T t = array[index]; | ||||||
|  |         array[index] = array[array.length - 1 - index]; | ||||||
|  |         array[array.length - 1 - index] = t; | ||||||
|  | 
 | ||||||
|  |         invertRec(array, index+1); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public FullyUsedArray<T> clone(FullyUsedArray<T> array) { |     public FullyUsedArray<T> clone(FullyUsedArray<T> array) { | ||||||
|         return null; |         var newArray = new FullyUsedArray<T>(); | ||||||
|  |         newArray.theArray = Arrays.newArray(array.theArray.length); | ||||||
|  | 
 | ||||||
|  |         copyRestOfElements(array.theArray, 0, newArray.theArray, 0); | ||||||
|  | 
 | ||||||
|  |         return newArray; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public FullyUsedArray<T> alternate(FullyUsedArray<T> a, FullyUsedArray<T> b) { |     public FullyUsedArray<T> alternate(FullyUsedArray<T> a, FullyUsedArray<T> b) { | ||||||
|         return null; |         var newArray = new FullyUsedArray<T>(); | ||||||
|  |         newArray.theArray = Arrays.newArray(a.theArray.length + b.theArray.length); | ||||||
|  | 
 | ||||||
|  |         alternateRec(a.theArray, 0, b.theArray, 0, newArray.theArray, 0); | ||||||
|  | 
 | ||||||
|  |         return newArray; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void alternateRec(T[] a, int indexA, T[] b, int indexB, T[] array, int index) { | ||||||
|  |         if (indexA >= a.length) { | ||||||
|  |             copyRestOfElements(b, indexB, array, index); | ||||||
|  |         } else if (indexB >= b.length) { | ||||||
|  |             copyRestOfElements(a, indexA, array, index); | ||||||
|  |         } else { | ||||||
|  |             array[index] = a[indexA]; | ||||||
|  |             array[index+1] = b[indexB]; | ||||||
|  |             alternateRec(a, indexA+1, b, indexB+1, array, index+2); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public FullyUsedArray<T> merge(FullyUsedArray<T> a, FullyUsedArray<T> b, Comparator<T> cmp) { |     public FullyUsedArray<T> merge(FullyUsedArray<T> a, FullyUsedArray<T> b, Comparator<T> cmp) { | ||||||
|         return null; |         var newArray = new FullyUsedArray<T>(); | ||||||
|  |         newArray.theArray = Arrays.newArray(a.theArray.length + b.theArray.length); | ||||||
|  | 
 | ||||||
|  |         mergeRec(a.theArray, 0, b.theArray, 0, newArray.theArray, 0, cmp); | ||||||
|  | 
 | ||||||
|  |         return newArray; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void mergeRec(T[] a, int indexA, T[] b, int indexB, T[] newArray, int index, Comparator<T> cmp) { | ||||||
|  |         if (indexA >= a.length) { | ||||||
|  |             copyRestOfElements(b, indexB, newArray, index); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         if (indexB >= b.length) { | ||||||
|  |             copyRestOfElements(a, indexA, newArray, index); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (cmp.compare(a[indexA], b[indexB]) < 0) { | ||||||
|  |             newArray[index] = a[indexA]; | ||||||
|  |             mergeRec(a, indexA+1, b, indexB, newArray, index+1, cmp); | ||||||
|  |         } else { | ||||||
|  |             newArray[index] = b[indexB]; | ||||||
|  |             mergeRec(a, indexA, b, indexB+1, newArray, index+1, cmp); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void copyRestOfElements(T[] src, int srcIndex, T[] dst, int dstIndex) { | ||||||
|  |         if (srcIndex >= src.length) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         dst[dstIndex] = src[srcIndex]; | ||||||
|  |         copyRestOfElements(src, srcIndex+1, dst, dstIndex+1); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public Pair<FullyUsedArray<T>, FullyUsedArray<T>> divideAlternating(FullyUsedArray<T> array) { |     public Pair<FullyUsedArray<T>, FullyUsedArray<T>> divideAlternating(FullyUsedArray<T> array) { | ||||||
|         return null; |         var p = createPairForDivideAlternating(array); | ||||||
|  |         divideAlternatingRec(p, array.theArray, 0, 0, 0); | ||||||
|  |         return p; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void divideAlternatingRec(Pair<FullyUsedArray<T>, FullyUsedArray<T>> p, T[] array, | ||||||
|  |                                       int index, int indexA, int indexB) { | ||||||
|  |         if (index >= array.length) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (index % 2 == 0) { | ||||||
|  |             p.fst.theArray[indexA] = array[index]; | ||||||
|  |             divideAlternatingRec(p, array, index+1, indexA+1, indexB); | ||||||
|  |         } else { | ||||||
|  |             p.snd.theArray[indexB] = array[index]; | ||||||
|  |             divideAlternatingRec(p, array, index+1, indexA, indexB+1); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public Pair<FullyUsedArray<T>, FullyUsedArray<T>> divideAlternatingByRuns(FullyUsedArray<T> array, Comparator<T> cmp) { |     public Pair<FullyUsedArray<T>, FullyUsedArray<T>> divideAlternatingByRuns(FullyUsedArray<T> array, Comparator<T> cmp) { | ||||||
|         return null; |         var elementsInFst = countElementsInFirst(array.theArray, cmp, true, 0); | ||||||
|  |         var p = createPairForDivideAlternatingByRuns(array, elementsInFst); | ||||||
|  | 
 | ||||||
|  |         divideAlternatingByRunsRec(array.theArray, p, cmp, true, 0, 0, 0); | ||||||
|  |         return p; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void divideAlternatingByRunsRec(T[] array, Pair<FullyUsedArray<T>, FullyUsedArray<T>> p, Comparator<T> cmp, | ||||||
|  |                                             boolean runInFst, int index, int indexA, int indexB) { | ||||||
|  |         if (index >= array.length) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (runInFst) { | ||||||
|  |             p.fst.theArray[indexA] = array[index]; | ||||||
|  |             indexA++; | ||||||
|  |         } else { | ||||||
|  |             p.snd.theArray[indexB] = array[index]; | ||||||
|  |             indexB++; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (index < array.length-1 && cmp.compare(array[index], array[index + 1]) > 0) { | ||||||
|  |             runInFst = !runInFst; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         divideAlternatingByRunsRec(array, p, cmp, runInFst, index+1, indexA, indexB); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private int countElementsInFirst(T[] array, Comparator<T> cmp, boolean runInFst, int index) { | ||||||
|  |         if (index >= array.length) { | ||||||
|  |             return 0; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         var countCurrentElement = 0; | ||||||
|  | 
 | ||||||
|  |         if (runInFst) { | ||||||
|  |             countCurrentElement++; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (index < array.length-1 && cmp.compare(array[index], array[index + 1]) > 0) { | ||||||
|  |             runInFst = !runInFst; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return countCurrentElement + countElementsInFirst(array, cmp, runInFst, index+1); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public Pair<FullyUsedArray<T>, FullyUsedArray<T>> divideByPivot(FullyUsedArray<T> array, T pivot, Comparator<T> cmp) { |     public Pair<FullyUsedArray<T>, FullyUsedArray<T>> divideByPivot(FullyUsedArray<T> array, T pivot, Comparator<T> cmp) { | ||||||
|         return null; |         var counts = new Pair<Integer, Integer>(); | ||||||
|  |         counts.fst = 0; | ||||||
|  |         counts.snd = 0; | ||||||
|  | 
 | ||||||
|  |         countLessAndGreater(array.theArray, pivot, cmp, 0, counts); | ||||||
|  | 
 | ||||||
|  |         var p = createPairForDivideByPivot(counts.fst, counts.snd); | ||||||
|  |         divideByPivotRec(array.theArray, pivot, cmp, p, 0, 0, 0); | ||||||
|  | 
 | ||||||
|  |         return p; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void divideByPivotRec(T[] array, T pivot, Comparator<T> cmp, Pair<FullyUsedArray<T>, FullyUsedArray<T>> p, | ||||||
|  |                                   int index, int indexA, int indexB) { | ||||||
|  |         if (index >= array.length) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         var c =  cmp.compare(array[index], pivot); | ||||||
|  |         if (c < 0) { | ||||||
|  |             p.fst.theArray[indexA] = array[index]; | ||||||
|  |             divideByPivotRec(array, pivot, cmp, p, index+1, indexA+1, indexB); | ||||||
|  |         } else if (c > 0) { | ||||||
|  |             p.snd.theArray[indexB] = array[index]; | ||||||
|  |             divideByPivotRec(array, pivot, cmp, p, index+1, indexA, indexB+1); | ||||||
|  |         } else { | ||||||
|  |             divideByPivotRec(array, pivot, cmp, p, index+1, indexA, indexB); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void countLessAndGreater(T[] array, T pivot, Comparator<T> cmp, int index, Pair<Integer, Integer> counts) { | ||||||
|  |         if (index >= array.length) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         var c =  cmp.compare(array[index], pivot); | ||||||
|  |         if (c < 0) { | ||||||
|  |             counts.fst++; | ||||||
|  |         } | ||||||
|  |         if (c > 0) { | ||||||
|  |             counts.snd++; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         countLessAndGreater(array, pivot, cmp, index+1, counts); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|  |  | ||||||
|  | @ -313,10 +313,10 @@ public abstract class SequenceProcessorTest<S> { | ||||||
|     void testThat_isItemWiseLessWithAlmostSameIsTrue(List<Integer> list) { |     void testThat_isItemWiseLessWithAlmostSameIsTrue(List<Integer> list) { | ||||||
|         S a = processor.create(list); |         S a = processor.create(list); | ||||||
| 
 | 
 | ||||||
|         var index = list.size()/2; |  | ||||||
|         if (list.isEmpty()) { |         if (list.isEmpty()) { | ||||||
|             list.add(1); |             list.add(1); | ||||||
|         } else { |         } else { | ||||||
|  |             var index = list.size()/2; | ||||||
|             list.set(index, list.get(index)+1); |             list.set(index, list.get(index)+1); | ||||||
|         } |         } | ||||||
|         S b = processor.create(list); |         S b = processor.create(list); | ||||||
|  | @ -330,14 +330,15 @@ public abstract class SequenceProcessorTest<S> { | ||||||
|     void testThat_isItemWiseLessWithPlus5Works(List<Integer> list) { |     void testThat_isItemWiseLessWithPlus5Works(List<Integer> list) { | ||||||
|         S a = processor.create(list); |         S a = processor.create(list); | ||||||
| 
 | 
 | ||||||
|  |         if (list.isEmpty()) { | ||||||
|  |             list.add(1); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         for (int i = 0; i < list.size(); i++) { |         for (int i = 0; i < list.size(); i++) { | ||||||
|             if (i % 2 == 0) { |             if (i % 2 == 0) { | ||||||
|                 list.set(i, list.get(i)+5); |                 list.set(i, list.get(i)+5); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         if (list.isEmpty()) { |  | ||||||
|             list.add(1); |  | ||||||
|         } |  | ||||||
|         S b = processor.create(list); |         S b = processor.create(list); | ||||||
| 
 | 
 | ||||||
|         assertTrue(processor.isItemWiseLess(a, b, cmp)); |         assertTrue(processor.isItemWiseLess(a, b, cmp)); | ||||||
|  | @ -353,7 +354,7 @@ public abstract class SequenceProcessorTest<S> { | ||||||
| 
 | 
 | ||||||
|     @ParameterizedTest |     @ParameterizedTest | ||||||
|     @ArgumentsSource(DoubleLatinProvider.class) |     @ArgumentsSource(DoubleLatinProvider.class) | ||||||
|     void testThat_isLexSmallerWithWorksLikeStrings(String stringA, String stringB) { |     void testThat_isLexSmallerWorksLikeStringsDo(String stringA, String stringB) { | ||||||
|         S a = toSequenceByAscii(stringA); |         S a = toSequenceByAscii(stringA); | ||||||
|         S b = toSequenceByAscii(stringB); |         S b = toSequenceByAscii(stringB); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Reference in a new issue