This is an automated email from the ASF dual-hosted git repository.
erans pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-numbers.git
The following commit(s) were added to refs/heads/master by this push:
new 7045693 NUMBERS-135: Implementation details removed from public API.
7045693 is described below
commit 7045693efc63d9df82461bcb3e1adde2f043b0c1
Author: Gilles Sadowski <[email protected]>
AuthorDate: Sun Sep 29 02:21:38 2019 +0200
NUMBERS-135: Implementation details removed from public API.
"Comparator" implementation made "private".
Factory method ("of").
---
.../numbers/combinatorics/Combinations.java | 136 +++++++--------------
.../numbers/combinatorics/CombinationsTest.java | 105 +++++++---------
2 files changed, 92 insertions(+), 149 deletions(-)
diff --git
a/commons-numbers-combinatorics/src/main/java/org/apache/commons/numbers/combinatorics/Combinations.java
b/commons-numbers-combinatorics/src/main/java/org/apache/commons/numbers/combinatorics/Combinations.java
index 691b2c1..c72711a 100644
---
a/commons-numbers-combinatorics/src/main/java/org/apache/commons/numbers/combinatorics/Combinations.java
+++
b/commons-numbers-combinatorics/src/main/java/org/apache/commons/numbers/combinatorics/Combinations.java
@@ -35,76 +35,30 @@ public class Combinations implements Iterable<int[]> {
private final int n;
/** Number of elements in each combination. */
private final int k;
- /** Iteration order. */
- private final IterationOrder iterationOrder;
/**
- * Describes the type of iteration performed by the
- * {@link #iterator() iterator}.
- */
- private enum IterationOrder {
- /** Lexicographic order. */
- LEXICOGRAPHIC
- }
-
- /**
- * Creates an instance whose range is the k-element subsets of
- * {0, ..., n - 1} represented as {@code int[]} arrays.
- * <p>
- * The iteration order is lexicographic: the arrays returned by the
- * {@link #iterator() iterator} are sorted in descending order and
- * they are visited in lexicographic order with significance from
- * right to left.
- * For example, {@code new Combinations(4, 2).iterator()} returns
- * an iterator that will generate the following sequence of arrays
- * on successive calls to
- * {@code next()}:<br>
- * {@code [0, 1], [0, 2], [1, 2], [0, 3], [1, 3], [2, 3]}
- * </p>
- * If {@code k == 0} an iterator containing an empty array is returned;
- * if {@code k == n} an iterator containing [0, ..., n - 1] is returned.
- *
* @param n Size of the set from which subsets are selected.
* @param k Size of the subsets to be enumerated.
* @throws IllegalArgumentException if {@code n < 0}.
* @throws IllegalArgumentException if {@code k > n} or {@code k < 0}.
*/
- public Combinations(int n,
- int k) {
- this(n, k, IterationOrder.LEXICOGRAPHIC);
+ private Combinations(int n,
+ int k) {
+ BinomialCoefficient.checkBinomial(n, k);
+ this.n = n;
+ this.k = k;
}
/**
- * Creates an instance whose range is the k-element subsets of
- * {0, ..., n - 1} represented as {@code int[]} arrays.
- * <p>
- * If the {@code iterationOrder} argument is set to
- * {@link IterationOrder#LEXICOGRAPHIC}, the arrays returned by the
- * {@link #iterator() iterator} are sorted in descending order and
- * they are visited in lexicographic order with significance from
- * right to left.
- * For example, {@code new Combinations(4, 2).iterator()} returns
- * an iterator that will generate the following sequence of arrays
- * on successive calls to
- * {@code next()}:<br>
- * {@code [0, 1], [0, 2], [1, 2], [0, 3], [1, 3], [2, 3]}
- * </p>
- * If {@code k == 0} an iterator containing an empty array is returned;
- * if {@code k == n} an iterator containing [0, ..., n - 1] is returned.
- *
* @param n Size of the set from which subsets are selected.
* @param k Size of the subsets to be enumerated.
- * @param iterationOrder Specifies the {@link #iterator() iteration order}.
* @throws IllegalArgumentException if {@code n < 0}.
* @throws IllegalArgumentException if {@code k > n} or {@code k < 0}.
+ * @return a new instance.
*/
- private Combinations(int n,
- int k,
- IterationOrder iterationOrder) {
- BinomialCoefficient.checkBinomial(n, k);
- this.n = n;
- this.k = k;
- this.iterationOrder = iterationOrder;
+ public static Combinations of(int n,
+ int k) {
+ return new Combinations(n, k);
}
/**
@@ -125,21 +79,40 @@ public class Combinations implements Iterable<int[]> {
return k;
}
- /** {@inheritDoc} */
+ /**
+ * Creates an iterator whose range is the k-element subsets of
+ * {0, ..., n - 1} represented as {@code int[]} arrays.
+ * <p>
+ * The iteration order is lexicographic: the arrays returned by the
+ * {@link #iterator() iterator} are sorted in descending order and
+ * they are visited in lexicographic order with significance from
+ * right to left.
+ * For example, {@code new Combinations(4, 2).iterator()} returns
+ * an iterator that will generate the following sequence of arrays
+ * on successive calls to
+ * {@code next()}:<br>
+ * {@code [0, 1], [0, 2], [1, 2], [0, 3], [1, 3], [2, 3]}
+ * </p>
+ * If {@code k == 0} an iterator containing an empty array is returned;
+ * if {@code k == n} an iterator containing [0, ..., n - 1] is returned.
+ */
@Override
public Iterator<int[]> iterator() {
- if (k == 0 ||
- k == n) {
- return new SingletonIterator(k);
- }
+ return k == 0 || k == n ?
+ new SingletonIterator(k) :
+ new LexicographicIterator(n, k);
+ }
- switch (iterationOrder) {
- case LEXICOGRAPHIC:
- return new LexicographicIterator(n, k);
- default:
- // Should never happen.
- throw new UnsupportedOperationException("Please file a bug
report");
- }
+ /**
+ * Creates a comparator.
+ * When performing a comparison, if an element of the array is not
+ * within the interval [0, {@code n}), an {@code IllegalArgumentException}
+ * will be thrown.
+ *
+ * @return a comparator.
+ */
+ public Comparator<int[]> comparator() {
+ return new LexicographicComparator(n, k);
}
/**
@@ -153,7 +126,6 @@ public class Combinations implements Iterable<int[]> {
* implementation. If constructor arguments satisfy {@code k == 0}
* or {@code k >= n}, no exception is generated, but the iterator is empty.
* </p>
- *
*/
private static class LexicographicIterator implements Iterator<int[]> {
/** Size of subsets returned by the iterator. */
@@ -330,10 +302,8 @@ public class Combinations implements Iterable<int[]> {
* The comparison is based on the value (in base 10) represented
* by the digit (interpreted in base {@code n}) in the input array,
* in reverse order.
- * For example if {@code c} is {@code {3, 2, 1}}, and {@code n}
- * is 3, the method will return 18.
*/
- public static class LexicographicComparator
+ private static class LexicographicComparator
implements Comparator<int[]>,
Serializable {
/** Serializable version identifier. */
@@ -347,31 +317,13 @@ public class Combinations implements Iterable<int[]> {
* @param n Size of the set from which subsets are selected.
* @param k Size of the subsets to be enumerated.
*/
- public LexicographicComparator(int n,
- int k) {
+ LexicographicComparator(int n,
+ int k) {
this.n = n;
this.k = k;
}
/**
- * Gets the size of the set from which combinations are drawn.
- *
- * @return the size of the universe.
- */
- public int getN() {
- return n;
- }
-
- /**
- * Gets the number of elements in each combination.
- *
- * @return the size of the subsets.
- */
- public int getK() {
- return k;
- }
-
- /**
* {@inheritDoc}
*
* @throws IllegalArgumentException if the array lengths are not
@@ -411,6 +363,8 @@ public class Combinations implements Iterable<int[]> {
* Computes the value (in base 10) represented by the digit
* (interpreted in base {@code n}) in the input array in reverse
* order.
+ * For example if {@code c} is {@code {3, 2, 1}}, and {@code n}
+ * is 3, the method will return 18.
*
* @param c Input array.
* @return the lexicographic norm.
diff --git
a/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/CombinationsTest.java
b/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/CombinationsTest.java
index 0b768c2..3e5febf 100644
---
a/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/CombinationsTest.java
+++
b/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/CombinationsTest.java
@@ -27,93 +27,84 @@ import org.junit.jupiter.api.Test;
*/
public class CombinationsTest {
@Test
- public void testAccessor1() {
+ public void testGetN() {
final int n = 5;
final int k = 3;
- Assertions.assertEquals(n, new Combinations(n, k).getN());
+ Assertions.assertEquals(n, Combinations.of(n, k).getN());
}
+
@Test
- public void testAccessor2() {
+ public void testGetK() {
final int n = 5;
final int k = 3;
- Assertions.assertEquals(k, new Combinations(n, k).getK());
+ Assertions.assertEquals(k, Combinations.of(n, k).getK());
}
@Test
public void testLexicographicIterator() {
- checkLexicographicIterator(new Combinations.LexicographicComparator(5,
3));
- checkLexicographicIterator(new Combinations.LexicographicComparator(6,
4));
- checkLexicographicIterator(new Combinations.LexicographicComparator(8,
2));
- checkLexicographicIterator(new Combinations.LexicographicComparator(6,
1));
- checkLexicographicIterator(new Combinations.LexicographicComparator(3,
3));
- checkLexicographicIterator(new Combinations.LexicographicComparator(1,
1));
- checkLexicographicIterator(new Combinations.LexicographicComparator(1,
0));
- checkLexicographicIterator(new Combinations.LexicographicComparator(0,
0));
- checkLexicographicIterator(new Combinations.LexicographicComparator(4,
2));
- checkLexicographicIterator(new
Combinations.LexicographicComparator(123, 2));
+ checkLexicographicIterator(5, 3);
+ checkLexicographicIterator(6, 4);
+ checkLexicographicIterator(8, 2);
+ checkLexicographicIterator(6, 1);
+ checkLexicographicIterator(3, 3);
+ checkLexicographicIterator(1, 1);
+ checkLexicographicIterator(1, 0);
+ checkLexicographicIterator(0, 0);
+ checkLexicographicIterator(4, 2);
+ checkLexicographicIterator(123, 2);
}
@Test
public void testLexicographicComparatorWrongIterate1() {
final int n = 5;
final int k = 3;
- final Comparator<int[]> comp = new
Combinations.LexicographicComparator(n, k);
+ final Comparator<int[]> comp = Combinations.of(n, k).comparator();
Assertions.assertThrows(IllegalArgumentException.class,
- () -> comp.compare(new int[] {1}, new int[] {0, 1, 2})
- );
+ () -> comp.compare(new int[] {1},
+ new int[] {0, 1, 2}));
}
@Test
public void testLexicographicComparatorWrongIterate2() {
final int n = 5;
final int k = 3;
- final Comparator<int[]> comp = new
Combinations.LexicographicComparator(n, k);
+ final Comparator<int[]> comp = Combinations.of(n, k).comparator();
Assertions.assertThrows(IllegalArgumentException.class,
- () -> comp.compare(new int[] {0, 1, 2}, new int[] {0, 1, 2, 3})
- );
+ () -> comp.compare(new int[] {0, 1, 2},
+ new int[] {0, 1, 2, 3}));
}
@Test
public void testLexicographicComparatorWrongIterate3() {
final int n = 5;
final int k = 3;
- final Comparator<int[]> comp = new
Combinations.LexicographicComparator(n, k);
+ final Comparator<int[]> comp = Combinations.of(n, k).comparator();
Assertions.assertThrows(IllegalArgumentException.class,
- () -> comp.compare(new int[] {1, 2, 5}, new int[] {0, 1, 2})
- );
+ () -> comp.compare(new int[] {1, 2, 5},
+ new int[] {0, 1, 2}));
}
@Test
public void testLexicographicComparatorWrongIterate4() {
final int n = 5;
final int k = 3;
- final Comparator<int[]> comp = new
Combinations.LexicographicComparator(n, k);
+ final Comparator<int[]> comp = Combinations.of(n, k).comparator();
Assertions.assertThrows(IllegalArgumentException.class,
- () -> comp.compare(new int[] {1, 2, 4}, new int[] {-1, 1, 2})
- );
- }
-
- @Test
- public void testLexicographicComparatorAccessors() {
- final int n = 9;
- final int k = 6;
- final Combinations.LexicographicComparator comp =
- new Combinations.LexicographicComparator(n, k);
- Assertions.assertEquals(n, comp.getN());
- Assertions.assertEquals(k, comp.getK());
+ () -> comp.compare(new int[] {1, 2, 4},
+ new int[] {-1, 1, 2}));
}
@Test
public void testLexicographicComparator() {
final int n = 5;
final int k = 3;
- final Comparator<int[]> comp = new
Combinations.LexicographicComparator(n, k);
+ final Comparator<int[]> comp = Combinations.of(n, k).comparator();
Assertions.assertEquals(1, comp.compare(new int[] {1, 2, 4},
- new int[] {1, 2, 3}));
+ new int[] {1, 2, 3}));
Assertions.assertEquals(-1, comp.compare(new int[] {0, 1, 4},
- new int[] {0, 2, 4}));
+ new int[] {0, 2, 4}));
Assertions.assertEquals(0, comp.compare(new int[] {1, 3, 4},
- new int[] {1, 3, 4}));
+ new int[] {1, 3, 4}));
}
/**
@@ -123,18 +114,18 @@ public class CombinationsTest {
public void testLexicographicComparatorUnsorted() {
final int n = 5;
final int k = 3;
- final Comparator<int[]> comp = new
Combinations.LexicographicComparator(n, k);
+ final Comparator<int[]> comp = Combinations.of(n, k).comparator();
Assertions.assertEquals(1, comp.compare(new int[] {1, 4, 2},
- new int[] {1, 3, 2}));
+ new int[] {1, 3, 2}));
Assertions.assertEquals(-1, comp.compare(new int[] {0, 4, 1},
- new int[] {0, 4, 2}));
+ new int[] {0, 4, 2}));
Assertions.assertEquals(0, comp.compare(new int[] {1, 4, 3},
- new int[] {1, 3, 4}));
+ new int[] {1, 3, 4}));
}
@Test
public void testEmptyCombination() {
- final Iterator<int[]> iter = new Combinations(12345, 0).iterator();
+ final Iterator<int[]> iter = Combinations.of(12345, 0).iterator();
Assertions.assertTrue(iter.hasNext());
final int[] c = iter.next();
Assertions.assertEquals(0, c.length);
@@ -144,7 +135,7 @@ public class CombinationsTest {
@Test
public void testFullSetCombination() {
final int n = 67;
- final Iterator<int[]> iter = new Combinations(n, n).iterator();
+ final Iterator<int[]> iter = Combinations.of(n, n).iterator();
Assertions.assertTrue(iter.hasNext());
final int[] c = iter.next();
Assertions.assertEquals(n, c.length);
@@ -161,16 +152,16 @@ public class CombinationsTest {
* increasing sequence of b(n,k) arrays, each having length k
* and each array itself increasing.
*
- * @param comp Comparator.
+ * @param n Size of the set from which subsets are selected.
+ * @param k Size of the subsets to be enumerated.
*/
- private static void
checkLexicographicIterator(Combinations.LexicographicComparator comp) {
- final int n = comp.getN();
- final int k = comp.getK();
-
+ private static void checkLexicographicIterator(int n,
+ int k) {
int[] lastIterate = null;
long numIterates = 0;
- for (int[] iterate : new Combinations(n, k)) {
+ final Comparator<int[]> comp = Combinations.of(n, k).comparator();
+ for (int[] iterate : Combinations.of(n, k)) {
Assertions.assertEquals(k, iterate.length);
// Check that the sequence of iterates is ordered.
@@ -192,15 +183,13 @@ public class CombinationsTest {
}
@Test
- public void testCombinationsIteratorFail1() {
+ public void testCombinationsPrecondition1() {
Assertions.assertThrows(IllegalArgumentException.class,
- () -> new Combinations(4, 5).iterator()
- );
+ () -> Combinations.of(4, 5));
}
@Test
- public void testCombinationsIteratorFail2() {
+ public void testCombinationsPrecondition2() {
Assertions.assertThrows(IllegalArgumentException.class,
- () -> new Combinations(-1, -2).iterator()
- );
+ () -> Combinations.of(-1, -2));
}
}