From d74b505eb2addd9eadb525e755165263b40b7de0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Skj=C3=B8lberg?= Date: Sat, 21 Sep 2024 19:13:09 +0200 Subject: [PATCH] Refactor --- ...ractStackableItemGroupIteratorBuilder.java | 4 +- ...eItemGroupPermutationRotationIterator.java | 6 +- .../AbstractStackableItemIteratorBuilder.java | 2 +- ...ckableItemPermutationRotationIterator.java | 2 +- ...eItemGroupPermutationRotationIterator.java | 223 ++++++++++++++++++ ...ckableItemPermutationRotationIterator.java | 64 ++--- ...mGroupPermutationRotationIteratorList.java | 19 +- ...eItemGroupPermutationRotationIterator.java | 44 ++++ ...ckableItemPermutationRotationIterator.java | 4 + ...mGroupPermutationRotationIteratorTest.java | 175 ++++++++++++++ ...adablePermutationRotationIteratorTest.java | 10 +- 11 files changed, 507 insertions(+), 46 deletions(-) create mode 100644 core/src/main/java/com/github/skjolber/packing/iterator/MutableIndexedStackableItemGroupPermutationRotationIterator.java create mode 100644 core/src/main/java/com/github/skjolber/packing/iterator/StackableItemGroupPermutationRotationIterator.java create mode 100644 core/src/test/java/com/github/skjolber/packing/iterator/MutableIndexedStackableItemGroupPermutationRotationIteratorTest.java diff --git a/core/src/main/java/com/github/skjolber/packing/iterator/AbstractStackableItemGroupIteratorBuilder.java b/core/src/main/java/com/github/skjolber/packing/iterator/AbstractStackableItemGroupIteratorBuilder.java index 305e6f1a..95b098dc 100644 --- a/core/src/main/java/com/github/skjolber/packing/iterator/AbstractStackableItemGroupIteratorBuilder.java +++ b/core/src/main/java/com/github/skjolber/packing/iterator/AbstractStackableItemGroupIteratorBuilder.java @@ -18,7 +18,7 @@ * "https://www.sitepoint.com/self-types-with-javas-generics/">https://www.sitepoint.com/self-types-with-javas-generics/ */ -public abstract class AbstractStackableItemGroupIteratorBuilder> { +public abstract class AbstractStackableItemGroupIteratorBuilder> { protected int maxLoadWeight = -1; protected Predicate filter; @@ -103,6 +103,6 @@ protected List toMatrix() { return results; } - public abstract StackableItemPermutationRotationIterator build(); + public abstract StackableItemGroupPermutationRotationIterator build(); } diff --git a/core/src/main/java/com/github/skjolber/packing/iterator/AbstractStackableItemGroupPermutationRotationIterator.java b/core/src/main/java/com/github/skjolber/packing/iterator/AbstractStackableItemGroupPermutationRotationIterator.java index 496c4439..a3f9957f 100644 --- a/core/src/main/java/com/github/skjolber/packing/iterator/AbstractStackableItemGroupPermutationRotationIterator.java +++ b/core/src/main/java/com/github/skjolber/packing/iterator/AbstractStackableItemGroupPermutationRotationIterator.java @@ -4,7 +4,7 @@ import com.github.skjolber.packing.api.StackableItem; -public abstract class AbstractStackableItemGroupPermutationRotationIterator extends AbstractStackableItemPermutationRotationIterator { +public abstract class AbstractStackableItemGroupPermutationRotationIterator extends AbstractStackableItemPermutationRotationIterator implements StackableItemGroupPermutationRotationIterator { protected List groups; @@ -122,7 +122,9 @@ public void removePermutations(List removed) { } } } - + public List getGroups() { + return groups; + } } diff --git a/core/src/main/java/com/github/skjolber/packing/iterator/AbstractStackableItemIteratorBuilder.java b/core/src/main/java/com/github/skjolber/packing/iterator/AbstractStackableItemIteratorBuilder.java index 9872da00..7236d97d 100644 --- a/core/src/main/java/com/github/skjolber/packing/iterator/AbstractStackableItemIteratorBuilder.java +++ b/core/src/main/java/com/github/skjolber/packing/iterator/AbstractStackableItemIteratorBuilder.java @@ -88,6 +88,6 @@ protected IndexedStackableItem[] toMatrix() { return results; } - public abstract StackableItemPermutationRotationIterator build(); + public abstract I build(); } diff --git a/core/src/main/java/com/github/skjolber/packing/iterator/AbstractStackableItemPermutationRotationIterator.java b/core/src/main/java/com/github/skjolber/packing/iterator/AbstractStackableItemPermutationRotationIterator.java index 876f06b4..4dafc304 100644 --- a/core/src/main/java/com/github/skjolber/packing/iterator/AbstractStackableItemPermutationRotationIterator.java +++ b/core/src/main/java/com/github/skjolber/packing/iterator/AbstractStackableItemPermutationRotationIterator.java @@ -168,7 +168,7 @@ public long countPermutations() { return n; } - protected IndexedStackableItem[] getStackableItems() { + public IndexedStackableItem[] getStackableItems() { return stackableItems; } public long getMinStackableVolume(int offset) { diff --git a/core/src/main/java/com/github/skjolber/packing/iterator/MutableIndexedStackableItemGroupPermutationRotationIterator.java b/core/src/main/java/com/github/skjolber/packing/iterator/MutableIndexedStackableItemGroupPermutationRotationIterator.java new file mode 100644 index 00000000..e84e5e8a --- /dev/null +++ b/core/src/main/java/com/github/skjolber/packing/iterator/MutableIndexedStackableItemGroupPermutationRotationIterator.java @@ -0,0 +1,223 @@ +package com.github.skjolber.packing.iterator; + +import java.util.ArrayList; +import java.util.List; + +import com.github.skjolber.packing.api.StackValue; +import com.github.skjolber.packing.api.packager.StackableItems; + + /** + * + * An iterator which also acts as {@linkplain StackableItemsS}. + * + * State is restored on each remove, next rotation or next permutation. + * + */ + + +public class MutableIndexedStackableItemGroupPermutationRotationIterator extends AbstractStackableItemGroupPermutationRotationIterator implements StackableItems, StackableItemPermutationRotationIterator { + + public static Builder newBuilder() { + return new Builder(); + } + + public static DelegateBuilder newBuilder(AbstractStackableItemGroupIteratorBuilder builder) { + return new DelegateBuilder(builder); + } + + public static class Builder { + + private StackableItemGroupPermutationRotationIterator iterator; + + public Builder withIterator(StackableItemGroupPermutationRotationIterator iterator) { + this.iterator = iterator; + return this; + } + + public MutableIndexedStackableItemGroupPermutationRotationIterator build() { + return new MutableIndexedStackableItemGroupPermutationRotationIterator(iterator); + } + } + + public static class DelegateBuilder extends AbstractStackableItemGroupIteratorBuilder { + + private final AbstractStackableItemGroupIteratorBuilder builder; + + public DelegateBuilder(AbstractStackableItemGroupIteratorBuilder builder) { + this.builder = builder; + } + + public MutableIndexedStackableItemGroupPermutationRotationIterator build() { + if(maxLoadWeight == -1) { + throw new IllegalStateException(); + } + if(size == null) { + throw new IllegalStateException(); + } + if(builder == null) { + throw new IllegalStateException(); + } + + StackableItemGroupPermutationRotationIterator iterator = builder + .withLoadSize(size) + .withMaxLoadWeight(maxLoadWeight) + .withStackableItemGroups(stackableItemGroups) + .withFilter(filter) + .build(); + + return new MutableIndexedStackableItemGroupPermutationRotationIterator(iterator); + } + } + + protected List mutableStackableItems; + + protected final StackableItemGroupPermutationRotationIterator iterator; + + public MutableIndexedStackableItemGroupPermutationRotationIterator(StackableItemGroupPermutationRotationIterator iterator) { + super(iterator.getStackableItems(), iterator.getGroups()); + + permutations = new int[0]; // n! + + this.iterator = iterator; + + resetFromIterator(); + } + + protected void resetFromIterator() { + mutableStackableItems = new ArrayList<>(); + for (int i = 0; i < stackableItems.length; i++) { + IndexedStackableItem loadableItem = stackableItems[i]; + if(loadableItem != null && !loadableItem.isEmpty()) { + mutableStackableItems.add(new MutableIndexedStackableItem(loadableItem)); + } + } + + int[] permutations = iterator.getPermutations(); + + this.permutations = new int[permutations.length]; + this.rotations = new int[permutations.length]; + this.minStackableVolume = new long[permutations.length]; + this.groups = iterator.getGroups(); + + System.arraycopy(permutations, 0, this.permutations, 0, permutations.length); + System.arraycopy(iterator.getMinStackableVolume(), 0, minStackableVolume, 0, permutations.length); + } + + public IndexedStackableItem get(int index) { + return mutableStackableItems.get(index); + } + + @Override + public int size() { + return mutableStackableItems.size(); + } + + @Override + public int length() { + return permutations.length; + } + + @Override + public int nextPermutation(int maxIndex) { + int result = iterator.nextPermutation(maxIndex); + if(result != -1) { + resetFromIterator(); + } + return result; + } + + @Override + public int nextRotation(int maxIndex) { + int result = iterator.nextRotation(maxIndex); + if(result != -1) { + resetFromIterator(); + } + return result; + } + + @Override + public void remove(int index, int count) { + IndexedStackableItem loadableItem = mutableStackableItems.get(index); + loadableItem.decrement(count); + + if(loadableItem.isEmpty()) { + mutableStackableItems.remove(index); + } + + int remainingCount = permutations.length - count; + + // make inline changes, do not reset + int[] permutations = new int[remainingCount]; + int[] rotations = new int[remainingCount]; + + int offset = 0; + for(int i = 0; i < this.permutations.length; i++) { + if(this.permutations[i] == loadableItem.getIndex() && count > 0) { + count--; + } else { + permutations[offset] = this.permutations[i]; + rotations[offset] = this.rotations[i]; + + offset++; + } + } + + this.permutations = permutations; + this.rotations = rotations; + + if(remainingCount > 0) { + calculateMinStackableVolume(0); + } + } + + public PermutationRotationState getState() { + return new PermutationRotationState(rotations, permutations); + } + + @Override + public int[] getPermutations() { + int[] permutations = new int[this.permutations.length]; + System.arraycopy(this.permutations, 0, permutations, 0, permutations.length); + return permutations; + } + + public List get(PermutationRotationState state, int length) { + return iterator.get(state, length); + } + + @Override + public int nextRotation() { + int result = iterator.nextRotation(); + if(result != -1) { + resetFromIterator(); + } + return result; + } + + @Override + public int nextPermutation() { + int result = iterator.nextPermutation(); + if(result != -1) { + resetFromIterator(); + } + return result; + } + + @Override + public void removePermutations(List removed) { + iterator.removePermutations(removed); + + resetFromIterator(); + } + + public void removePermutations(int removed) { + iterator.removePermutations(removed); + + resetFromIterator(); + } + + protected StackableItemPermutationRotationIterator getIterator() { + return iterator; + } + +} diff --git a/core/src/main/java/com/github/skjolber/packing/iterator/MutableIndexedStackableItemPermutationRotationIterator.java b/core/src/main/java/com/github/skjolber/packing/iterator/MutableIndexedStackableItemPermutationRotationIterator.java index 766925ea..e1ba92c6 100644 --- a/core/src/main/java/com/github/skjolber/packing/iterator/MutableIndexedStackableItemPermutationRotationIterator.java +++ b/core/src/main/java/com/github/skjolber/packing/iterator/MutableIndexedStackableItemPermutationRotationIterator.java @@ -17,17 +17,34 @@ public class MutableIndexedStackableItemPermutationRotationIterator extends AbstractStackableItemPermutationRotationIterator implements StackableItems, StackableItemPermutationRotationIterator { - public static Builder newMutableBuilder() { + public static Builder newBuilder() { return new Builder(); } + + public static DelegateBuilder newBuilder(AbstractStackableItemIteratorBuilder builder) { + return new DelegateBuilder(builder); + } + + public static class Builder { - public static class Builder extends AbstractStackableItemIteratorBuilder { + private StackableItemPermutationRotationIterator iterator; - private AbstractStackableItemIteratorBuilder builder; + public Builder withIterator(StackableItemPermutationRotationIterator iterator) { + this.iterator = iterator; + return this; + } - public Builder withBuilder(AbstractStackableItemIteratorBuilder builder) { + public MutableIndexedStackableItemPermutationRotationIterator build() { + return new MutableIndexedStackableItemPermutationRotationIterator(iterator); + } + } + + public static class DelegateBuilder extends AbstractStackableItemIteratorBuilder { + + private final AbstractStackableItemIteratorBuilder builder; + + public DelegateBuilder(AbstractStackableItemIteratorBuilder builder) { this.builder = builder; - return this; } public MutableIndexedStackableItemPermutationRotationIterator build() { @@ -41,22 +58,22 @@ public MutableIndexedStackableItemPermutationRotationIterator build() { throw new IllegalStateException(); } - StackableItemPermutationRotationIterator iterator = builder + AbstractStackableItemPermutationRotationIterator iterator = builder .withLoadSize(size) .withMaxLoadWeight(maxLoadWeight) .withStackableItems(stackableItems) .withFilter(filter) .build(); - return new MutableIndexedStackableItemPermutationRotationIterator((AbstractStackableItemPermutationRotationIterator) iterator); + return new MutableIndexedStackableItemPermutationRotationIterator(iterator); } } protected List mutableStackableItems; - protected final AbstractStackableItemPermutationRotationIterator iterator; + protected final StackableItemPermutationRotationIterator iterator; - public MutableIndexedStackableItemPermutationRotationIterator(AbstractStackableItemPermutationRotationIterator iterator) { + public MutableIndexedStackableItemPermutationRotationIterator(StackableItemPermutationRotationIterator iterator) { super(iterator.getStackableItems()); permutations = new int[0]; // n! @@ -67,8 +84,6 @@ public MutableIndexedStackableItemPermutationRotationIterator(AbstractStackableI } protected void resetFromIterator() { - int[] permutations = iterator.getPermutations(); - mutableStackableItems = new ArrayList<>(); for (int i = 0; i < stackableItems.length; i++) { IndexedStackableItem loadableItem = stackableItems[i]; @@ -77,9 +92,11 @@ protected void resetFromIterator() { } } + int[] permutations = iterator.getPermutations(); + this.permutations = new int[permutations.length]; - rotations = new int[permutations.length]; - minStackableVolume = new long[permutations.length]; + this.rotations = new int[permutations.length]; + this.minStackableVolume = new long[permutations.length]; System.arraycopy(permutations, 0, this.permutations, 0, permutations.length); System.arraycopy(iterator.getMinStackableVolume(), 0, minStackableVolume, 0, permutations.length); @@ -148,23 +165,7 @@ public void remove(int index, int count) { this.rotations = rotations; if(remainingCount > 0) { - calculateMutableMinStackableVolume(0); - } - } - - private void calculateMutableMinStackableVolume(int offset) { - StackValue last = getStackValue(permutations.length - 1); - - minStackableVolume[permutations.length - 1] = last.getVolume(); - - for (int i = permutations.length - 2; i >= offset; i--) { - long volume = getStackValue(i).getVolume(); - - if(volume < minStackableVolume[i + 1]) { - minStackableVolume[i] = volume; - } else { - minStackableVolume[i] = minStackableVolume[i + 1]; - } + calculateMinStackableVolume(0); } } @@ -214,9 +215,8 @@ public void removePermutations(int removed) { resetFromIterator(); } - protected AbstractStackableItemPermutationRotationIterator getIterator() { + protected StackableItemPermutationRotationIterator getIterator() { return iterator; } - } diff --git a/core/src/main/java/com/github/skjolber/packing/iterator/ParallelStackableItemGroupPermutationRotationIteratorList.java b/core/src/main/java/com/github/skjolber/packing/iterator/ParallelStackableItemGroupPermutationRotationIteratorList.java index 5a99c080..129c33ee 100644 --- a/core/src/main/java/com/github/skjolber/packing/iterator/ParallelStackableItemGroupPermutationRotationIteratorList.java +++ b/core/src/main/java/com/github/skjolber/packing/iterator/ParallelStackableItemGroupPermutationRotationIteratorList.java @@ -4,7 +4,6 @@ import java.util.List; import com.github.skjolber.packing.api.StackValue; -import com.github.skjolber.packing.api.StackableItem; /** * @@ -12,7 +11,7 @@ * */ -public class ParallelStackableItemGroupPermutationRotationIteratorList implements StackableItemPermutationRotationIterator { +public class ParallelStackableItemGroupPermutationRotationIteratorList implements StackableItemGroupPermutationRotationIterator { protected final static int PADDING = 16; @@ -45,7 +44,6 @@ public ParallelStackableItemGroupPermutationRotationIteratorList build() { return new ParallelStackableItemGroupPermutationRotationIteratorList(groups, parallelizationCount); } - } protected final int[] frequencies; @@ -316,4 +314,19 @@ public long countPermutations() { return workUnits[0].countPermutations(); } + @Override + public long[] getMinStackableVolume() { + return workUnits[workUnitIndex].getMinStackableVolume(); + } + + @Override + public IndexedStackableItem[] getStackableItems() { + return workUnits[workUnitIndex].getStackableItems(); + } + + @Override + public List getGroups() { + return workUnits[workUnitIndex].getGroups(); + } + } diff --git a/core/src/main/java/com/github/skjolber/packing/iterator/StackableItemGroupPermutationRotationIterator.java b/core/src/main/java/com/github/skjolber/packing/iterator/StackableItemGroupPermutationRotationIterator.java new file mode 100644 index 00000000..35836074 --- /dev/null +++ b/core/src/main/java/com/github/skjolber/packing/iterator/StackableItemGroupPermutationRotationIterator.java @@ -0,0 +1,44 @@ +package com.github.skjolber.packing.iterator; + +import java.util.List; + +import com.github.skjolber.packing.api.StackValue; + +/** + * + * Rotation and permutations built into the same interface. Minimizes the number of + * rotations.
+ *
+ * The maximum number of combinations is n! * 6^n, however after accounting for + * bounds and sides with equal lengths the number can be a lot lower (and this + * number can be obtained before starting the calculation).
+ *
+ * Note that permutations are for the boxes which actually fit within this container. + *
+ *
+ * Assumes a do-while approach: + * + *
+ * {@code
+ * do {
+ * 	do {
+ * 		for (int i = 0; i < n; i++) {
+ * 			PermutationRotation box = instance.get(i);
+ * 			// .. your code here
+ * 		}
+ * 	} while (instance.nextRotation() != -1);
+ * } while (instance.nextPermutation() != -1);
+ *
+ * }
+ * 
+ * + * @see next-lexicographical-permutation-algorithm + */ + +public interface StackableItemGroupPermutationRotationIterator extends StackableItemPermutationRotationIterator { + + List getGroups(); + +} \ No newline at end of file diff --git a/core/src/main/java/com/github/skjolber/packing/iterator/StackableItemPermutationRotationIterator.java b/core/src/main/java/com/github/skjolber/packing/iterator/StackableItemPermutationRotationIterator.java index dcc43314..339e3d79 100644 --- a/core/src/main/java/com/github/skjolber/packing/iterator/StackableItemPermutationRotationIterator.java +++ b/core/src/main/java/com/github/skjolber/packing/iterator/StackableItemPermutationRotationIterator.java @@ -71,6 +71,8 @@ public interface StackableItemPermutationRotationIterator { long getMinStackableVolume(int index); + long[] getMinStackableVolume(); + int getMinStackableAreaIndex(int i); /** @@ -132,5 +134,7 @@ public interface StackableItemPermutationRotationIterator { void removePermutations(List removed); void removePermutations(int count); + + IndexedStackableItem[] getStackableItems(); } \ No newline at end of file diff --git a/core/src/test/java/com/github/skjolber/packing/iterator/MutableIndexedStackableItemGroupPermutationRotationIteratorTest.java b/core/src/test/java/com/github/skjolber/packing/iterator/MutableIndexedStackableItemGroupPermutationRotationIteratorTest.java new file mode 100644 index 00000000..aad53a42 --- /dev/null +++ b/core/src/test/java/com/github/skjolber/packing/iterator/MutableIndexedStackableItemGroupPermutationRotationIteratorTest.java @@ -0,0 +1,175 @@ +package com.github.skjolber.packing.iterator; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.junit.jupiter.api.Test; + +import com.github.skjolber.packing.api.Box; +import com.github.skjolber.packing.api.Dimension; +import com.github.skjolber.packing.api.StackableItem; +import com.github.skjolber.packing.api.StackableItemGroup; +import com.github.skjolber.packing.api.packager.StackableItems; +import com.github.skjolber.packing.iterator.MutableIndexedStackableItemPermutationRotationIterator.Builder; +import com.github.skjolber.packing.iterator.MutableIndexedStackableItemPermutationRotationIterator.DelegateBuilder; + +class MutableIndexedStackableItemGroupPermutationRotationIteratorTest extends AbstractStackableItemGroupPermutationRotationIteratorTest { + + @Override + public MutableIndexedStackableItemGroupPermutationRotationIterator.DelegateBuilder newBuilder() { + return new MutableIndexedStackableItemGroupPermutationRotationIterator.DelegateBuilder(DefaultStackableItemGroupPermutationRotationIterator.newBuilder()); + } + + @Test + void testMutableRotationCount() { + for (int i = 1; i <= 8; i++) { + Dimension container = new Dimension(null, 3 * (i + 1), 3, 1); + + List groups = new ArrayList<>(); + + List products1 = new ArrayList<>(); + + for (int k = 0; k < i; k++) { + Box box = Box.newBuilder().withSize(3, 1, 1).withRotate3D().withId(Integer.toString(k)).withWeight(1).build(); + + StackableItem item = new StackableItem(box); + + products1.add(item); + } + + groups.add(new StackableItemGroup("1", products1)); + + MutableIndexedStackableItemGroupPermutationRotationIterator rotator = + newBuilder() + .withLoadSize(container) + .withStackableItemGroups(groups) + .withMaxLoadWeight(products1.size()) + .build(); + + StackableItems items = rotator; + + long unmodifiedRotationsCount = rotator.getIterator().countRotations(); + + long modifiedRotationsCount = rotator.countRotations(); + + assertTrue(unmodifiedRotationsCount >= modifiedRotationsCount); + + long rotate = 0; + do { + // removing items do not affect the number of rotations + assertEquals(items.size(), products1.size()); + + items.remove(0, 1); + for(int k = 0; k < items.size(); k++) { + StackableItem item = items.get(k); + assertFalse(item.getStackable().getId().equals("0")); + } + + rotate++; + } while (rotator.nextRotation() != -1); + + assertEquals(unmodifiedRotationsCount, rotate); + } + } + + @Test + void testMutablePermutationsWithMultipleBoxes() { + Dimension container = new Dimension(null, 9, 1, 1); + + List products = new ArrayList<>(); + + products.add(new StackableItem(Box.newBuilder().withRotate3D().withSize(1, 1, 3).withId("0").withWeight(1).build(), 2)); + products.add(new StackableItem(Box.newBuilder().withRotate3D().withSize(1, 1, 3).withId("1").withWeight(1).build(), 4)); + + List groups = new ArrayList<>(); + groups.add(new StackableItemGroup("1", products)); + + MutableIndexedStackableItemGroupPermutationRotationIterator rotator = newBuilder() + .withLoadSize(container) + .withStackableItemGroups(groups) + .withMaxLoadWeight(products.size()) + .build(); + + + int count = 0; + do { + assertEquals(rotator.size(), products.size()); + + // removing items do not affect the number of permutations + rotator.remove(0, 1); + + // still two types of loadable items + assertEquals(rotator.size(), 2); + + count++; + } while (rotator.nextPermutation() != -1); + + assertEquals((6 * 5 * 4 * 3 * 2 * 1) / ((4 * 3 * 2 * 1) * (2 * 1)), count); + } + + @Test + void testLoadableItems() { + Dimension container = new Dimension(null, 9, 1, 1); + + List products = new ArrayList<>(); + + products.add(new StackableItem(Box.newBuilder().withRotate3D().withSize(1, 1, 3).withId("0").withWeight(1).build(), 2)); + products.add(new StackableItem(Box.newBuilder().withRotate3D().withSize(1, 1, 3).withId("1").withWeight(1).build(), 4)); + + List groups = new ArrayList<>(); + groups.add(new StackableItemGroup("1", products)); + + MutableIndexedStackableItemGroupPermutationRotationIterator rotator = newBuilder() + .withLoadSize(container) + .withStackableItemGroups(groups) + .withMaxLoadWeight(products.size()) + .build(); + + rotator.remove(0, 1); + + // still two types of loadable items + assertEquals(rotator.size(), 2); + + int[] frequencies = toFrequency(rotator, 2); + + assertEquals(1, frequencies[0]); + assertEquals(4, frequencies[1]); + + // still two types of loadable items + rotator.remove(1, 2); + assertEquals(rotator.size(), 2); + + frequencies = toFrequency(rotator, 2); + assertEquals(1, frequencies[0]); + assertEquals(2, frequencies[1]); + + rotator.remove(0, 1); + // 0 exhausted + assertEquals(rotator.size(), 1); + + frequencies = toFrequency(rotator, 2); + assertEquals(0, frequencies[0]); + assertEquals(2, frequencies[1]); + + rotator.remove(0, 2); + // 1 exhausted + assertEquals(rotator.size(), 0); + } + + public int[] toFrequency(MutableIndexedStackableItemGroupPermutationRotationIterator rotator, int size) { + int[] counts = new int[size]; + for (int i : rotator.getPermutations()) { + counts[i]++; + } + return counts; + } + + + + +} diff --git a/core/src/test/java/com/github/skjolber/packing/iterator/MutableLoadablePermutationRotationIteratorTest.java b/core/src/test/java/com/github/skjolber/packing/iterator/MutableLoadablePermutationRotationIteratorTest.java index c0e61f58..08234261 100644 --- a/core/src/test/java/com/github/skjolber/packing/iterator/MutableLoadablePermutationRotationIteratorTest.java +++ b/core/src/test/java/com/github/skjolber/packing/iterator/MutableLoadablePermutationRotationIteratorTest.java @@ -14,12 +14,14 @@ import com.github.skjolber.packing.api.Dimension; import com.github.skjolber.packing.api.StackableItem; import com.github.skjolber.packing.api.packager.StackableItems; +import com.github.skjolber.packing.iterator.MutableIndexedStackableItemPermutationRotationIterator.Builder; +import com.github.skjolber.packing.iterator.MutableIndexedStackableItemPermutationRotationIterator.DelegateBuilder; -class MutableLoadablePermutationRotationIteratorTest extends AbstractStackableItemPermutationRotationIteratorTest { +class MutableLoadablePermutationRotationIteratorTest extends AbstractStackableItemPermutationRotationIteratorTest { @Override - public MutableIndexedStackableItemPermutationRotationIterator.Builder newBuilder() { - return MutableIndexedStackableItemPermutationRotationIterator.newMutableBuilder().withBuilder(DefaultStackableItemPermutationRotationIterator.newBuilder()); + public DelegateBuilder newBuilder() { + return new DelegateBuilder(DefaultStackableItemPermutationRotationIterator.newBuilder()); } @Test @@ -67,8 +69,6 @@ void testMutableRotationCount() { } while (rotator.nextRotation() != -1); assertEquals(unmodifiedRotationsCount, rotate); - - System.out.println(unmodifiedRotationsCount + " -> " + modifiedRotationsCount); } }