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; | ||||
| 
 | ||||
| import aud.exam.prep.Pair; | ||||
| import aud.exam.prep.SequenceProcessor; | ||||
| 
 | ||||
| abstract class FullyUsedArrayProcessor<T> implements SequenceProcessor<T, FullyUsedArray<T>> { | ||||
|  | @ -24,4 +25,34 @@ abstract class FullyUsedArrayProcessor<T> implements SequenceProcessor<T, FullyU | |||
|         return () -> | ||||
|             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) { | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         for (int i = 0; i < a.theArray.length; i++) { | ||||
|             if (cmp.compare(a.theArray[i], b.theArray[i]) > 0) { | ||||
|                 return false; | ||||
|  | @ -416,12 +417,7 @@ public class IterativeFullyUsedArrayProcessor<T> extends FullyUsedArrayProcessor | |||
| 
 | ||||
|     @Override | ||||
|     public Pair<FullyUsedArray<T>, FullyUsedArray<T>> divideAlternating(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); | ||||
|         var p = createPairForDivideAlternating(array); | ||||
| 
 | ||||
|         for (int i = 0; i < array.theArray.length; i++) { | ||||
|             if (i % 2 == 0) { | ||||
|  | @ -436,10 +432,6 @@ public class IterativeFullyUsedArrayProcessor<T> extends FullyUsedArrayProcessor | |||
| 
 | ||||
|     @Override | ||||
|     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 elementsInFst = 0; | ||||
| 
 | ||||
|  | @ -453,8 +445,7 @@ public class IterativeFullyUsedArrayProcessor<T> extends FullyUsedArrayProcessor | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         p.fst.theArray = Arrays.newArray(elementsInFst); | ||||
|         p.snd.theArray = Arrays.newArray(array.theArray.length - elementsInFst); | ||||
|         var p = createPairForDivideAlternatingByRuns(array, elementsInFst); | ||||
| 
 | ||||
|         runInFst = true; | ||||
|         var indexA = 0; | ||||
|  | @ -477,10 +468,6 @@ public class IterativeFullyUsedArrayProcessor<T> extends FullyUsedArrayProcessor | |||
| 
 | ||||
|     @Override | ||||
|     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 greater = 0; | ||||
| 
 | ||||
|  | @ -494,8 +481,7 @@ public class IterativeFullyUsedArrayProcessor<T> extends FullyUsedArrayProcessor | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         p.fst.theArray = Arrays.newArray(less); | ||||
|         p.snd.theArray = Arrays.newArray(greater); | ||||
|         var p = createPairForDivideByPivot(less, greater); | ||||
| 
 | ||||
|         var indexA = 0; | ||||
|         var indexB = 0; | ||||
|  |  | |||
|  | @ -4,142 +4,698 @@ import aud.exam.prep.Pair; | |||
| 
 | ||||
| import java.util.Comparator; | ||||
| import java.util.Iterator; | ||||
| import java.util.Objects; | ||||
| 
 | ||||
| public class RecursiveFullyUsedArrayProcessor<T> extends FullyUsedArrayProcessor<T> { | ||||
| 
 | ||||
|     @Override | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|     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 | ||||
|  |  | |||
|  | @ -313,10 +313,10 @@ public abstract class SequenceProcessorTest<S> { | |||
|     void testThat_isItemWiseLessWithAlmostSameIsTrue(List<Integer> list) { | ||||
|         S a = processor.create(list); | ||||
| 
 | ||||
|         var index = list.size()/2; | ||||
|         if (list.isEmpty()) { | ||||
|             list.add(1); | ||||
|         } else { | ||||
|             var index = list.size()/2; | ||||
|             list.set(index, list.get(index)+1); | ||||
|         } | ||||
|         S b = processor.create(list); | ||||
|  | @ -330,14 +330,15 @@ public abstract class SequenceProcessorTest<S> { | |||
|     void testThat_isItemWiseLessWithPlus5Works(List<Integer> list) { | ||||
|         S a = processor.create(list); | ||||
| 
 | ||||
|         if (list.isEmpty()) { | ||||
|             list.add(1); | ||||
|         } | ||||
| 
 | ||||
|         for (int i = 0; i < list.size(); i++) { | ||||
|             if (i % 2 == 0) { | ||||
|                 list.set(i, list.get(i)+5); | ||||
|             } | ||||
|         } | ||||
|         if (list.isEmpty()) { | ||||
|             list.add(1); | ||||
|         } | ||||
|         S b = processor.create(list); | ||||
| 
 | ||||
|         assertTrue(processor.isItemWiseLess(a, b, cmp)); | ||||
|  | @ -353,7 +354,7 @@ public abstract class SequenceProcessorTest<S> { | |||
| 
 | ||||
|     @ParameterizedTest | ||||
|     @ArgumentsSource(DoubleLatinProvider.class) | ||||
|     void testThat_isLexSmallerWithWorksLikeStrings(String stringA, String stringB) { | ||||
|     void testThat_isLexSmallerWorksLikeStringsDo(String stringA, String stringB) { | ||||
|         S a = toSequenceByAscii(stringA); | ||||
|         S b = toSequenceByAscii(stringB); | ||||
| 
 | ||||
|  |  | |||
		Reference in a new issue