Commit e00c976a authored by Fokion Zervoudakis's avatar Fokion Zervoudakis

Delete redundant method. Update N choose K implementation.

parent 9bd1a7dc
...@@ -4,60 +4,43 @@ import java.util.ArrayList; ...@@ -4,60 +4,43 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
class NChooseK { class NChooseK<T> {
List<T[]> L = new ArrayList<>();
/** /**
Calculates the binomial coefficient {@code n} choose {@code k}: the number Generates {@code k}-element combinations from an {@code n}-element set (i.e.
of {@code k}-element subsets that can be selected from an {@code n}-element {@code n} choose {@code k}).
set. <p>Asymptotic analysis:
<ul> <ul>
<li>time_worst=O(n^k) <li>time_worst=O(n^k)
<li>space_worst=O(n) <li>space_worst=O(n)
</ul> </ul>
@param n a number of possibilities @param A the target array
@param k a number of outcomes @param k the number of elements per combination
@return the binomial coefficient {@code n} choose {@code k} @return the {@code k}-element combinations of {@code A}
*/ */
int rec(int n, int k) { List<T[]> generate(T[] A, int k) {
return (k == 0 || k == n) ? 1 : rec(n - 1, k) + rec(n - 1, k - 1); helper(A, A.length, k, 0, 0);
return L;
} }
class Combinator<T> { private void helper(T[] A, int n, int k, int i, int j) {
List<T[]> L = new ArrayList<>(); if (i == k) {
L.add(Arrays.copyOfRange(A, 0, k));
/** } else {
Asymptotic analysis: if (j < n) {
<ul> swap(A, i, j);
<li>time_worst=O(n^k) helper(A, n, k, i + 1, j + 1);
<li>space_worst=O(n) helper(A, n, k, i, j + 1);
</ul> swap(A, i, j);
@param A the target array
@param k the number of combinations
@return the {@code k}-element combinations of {@code A}
*/
List<T[]> generate(T[] A, int k) {
helper(A, 0, k, 0);
return L;
}
private void helper(T[] A, int n, int k, int start) {
if (n == k) {
L.add(Arrays.copyOfRange(A, 0, k));
} else {
for (int i = start; i < A.length; i++) {
swap(A, i, n);
helper(A, n + 1, k, i + 1);
// backtrack
swap(A, i, n);
}
} }
} }
}
private void swap(T[] A, int i, int j) { private void swap(T[] A, int i, int j) {
T t = A[i]; T t = A[i];
A[i] = A[j]; A[i] = A[j];
A[j] = t; A[j] = t;
}
} }
} }
package misc; package misc;
import misc.NChooseK.Combinator;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.Arrays; import java.util.Arrays;
...@@ -13,79 +11,53 @@ import static org.junit.jupiter.api.Assertions.assertEquals; ...@@ -13,79 +11,53 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
class NChooseKTest { class NChooseKTest {
private NChooseK chooseK; private NChooseK<Integer> nChooseK;
private Integer[] A;
@BeforeEach @BeforeEach
void beforeEach() { void beforeEach() {
chooseK = new NChooseK(); nChooseK = new NChooseK<>();
A = new Integer[] { 1, 2, 3, 4 };
} }
@Test @Test
void itCalculatesTheBinomialCoefficient() { void itGeneratesOneCombinationWithZeroElements() {
assertEquals(1, chooseK.rec(5, 0)); var expected = "[[]]";
assertEquals(5, chooseK.rec(5, 1)); var actual = toS(nChooseK.generate(A, 0));
assertEquals(10, chooseK.rec(5, 2)); assertEquals(expected, actual);
assertEquals(10, chooseK.rec(5, 3));
assertEquals(5, chooseK.rec(5, 4));
assertEquals(1, chooseK.rec(5, 5));
} }
@Test @Test
void itCalculatesTheBaseCase() { void itGeneratesFourCombinationsWithOneElement() {
assertEquals(1, chooseK.rec(1, 0)); var expected = "[[1], [2], [3], [4]]";
assertEquals(1, chooseK.rec(1, 1)); var actual = toS(nChooseK.generate(A, 1));
assertEquals(expected, actual);
} }
@Nested @Test
class WhenItGeneratesCombinations { void itGeneratesSixCombinationsWithTwoElements() {
private Combinator<Integer> combinator; var expected = "[[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]";
private Integer[] A; var actual = toS(nChooseK.generate(A, 2));
assertEquals(expected, actual);
@BeforeEach }
void beforeEach() {
combinator = chooseK.new Combinator<>();
A = new Integer[] { 1, 2, 3, 4 };
}
@Test
void itGeneratesOneCombinationWithZeroElements() {
var expected = "[[]]";
var actual = toS(combinator.generate(A, 0));
assertEquals(expected, actual);
}
@Test
void itGeneratesFourCombinationsWithOneElement() {
var expected = "[[1], [2], [3], [4]]";
var actual = toS(combinator.generate(A, 1));
assertEquals(expected, actual);
}
@Test
void itGeneratesSixCombinationsWithTwoElements() {
var expected = "[[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]";
var actual = toS(combinator.generate(A, 2));
assertEquals(expected, actual);
}
@Test @Test
void itGeneratesFourCombinationsWithThreeElements() { void itGeneratesFourCombinationsWithThreeElements() {
var expected = "[[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]"; var expected = "[[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]";
var actual = toS(combinator.generate(A, 3)); var actual = toS(nChooseK.generate(A, 3));
assertEquals(expected, actual); assertEquals(expected, actual);
} }
@Test @Test
void itGeneratesOneCombinationWithFourElements() { void itGeneratesOneCombinationWithFourElements() {
var expected = "[[1, 2, 3, 4]]"; var expected = "[[1, 2, 3, 4]]";
var actual = toS(combinator.generate(A, 4)); var actual = toS(nChooseK.generate(A, 4));
assertEquals(expected, actual); assertEquals(expected, actual);
} }
@Test @Test
void itGeneratesZeroCombinations() { void itGeneratesZeroCombinationsWithFiveElements() {
assertTrue(combinator.generate(A, 5).isEmpty()); assertTrue(nChooseK.generate(A, 5).isEmpty());
}
} }
private String toS(List<Integer[]> L) { private String toS(List<Integer[]> L) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment