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;
import java.util.Arrays;
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
of {@code k}-element subsets that can be selected from an {@code n}-element
set.
Generates {@code k}-element combinations from an {@code n}-element set (i.e.
{@code n} choose {@code k}).
<p>Asymptotic analysis:
<ul>
<li>time_worst=O(n^k)
<li>space_worst=O(n)
</ul>
@param n a number of possibilities
@param k a number of outcomes
@return the binomial coefficient {@code n} choose {@code k}
@param A the target array
@param k the number of elements per combination
@return the {@code k}-element combinations of {@code A}
*/
int rec(int n, int k) {
return (k == 0 || k == n) ? 1 : rec(n - 1, k) + rec(n - 1, k - 1);
List<T[]> generate(T[] A, int k) {
helper(A, A.length, k, 0, 0);
return L;
}
class Combinator<T> {
List<T[]> L = new ArrayList<>();
/**
Asymptotic analysis:
<ul>
<li>time_worst=O(n^k)
<li>space_worst=O(n)
</ul>
@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 helper(T[] A, int n, int k, int i, int j) {
if (i == k) {
L.add(Arrays.copyOfRange(A, 0, k));
} else {
if (j < n) {
swap(A, i, j);
helper(A, n, k, i + 1, j + 1);
helper(A, n, k, i, j + 1);
swap(A, i, j);
}
}
}
private void swap(T[] A, int i, int j) {
T t = A[i];
A[i] = A[j];
A[j] = t;
}
private void swap(T[] A, int i, int j) {
T t = A[i];
A[i] = A[j];
A[j] = t;
}
}
package misc;
import misc.NChooseK.Combinator;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
......@@ -13,79 +11,53 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
class NChooseKTest {
private NChooseK chooseK;
private NChooseK<Integer> nChooseK;
private Integer[] A;
@BeforeEach
void beforeEach() {
chooseK = new NChooseK();
nChooseK = new NChooseK<>();
A = new Integer[] { 1, 2, 3, 4 };
}
@Test
void itCalculatesTheBinomialCoefficient() {
assertEquals(1, chooseK.rec(5, 0));
assertEquals(5, chooseK.rec(5, 1));
assertEquals(10, chooseK.rec(5, 2));
assertEquals(10, chooseK.rec(5, 3));
assertEquals(5, chooseK.rec(5, 4));
assertEquals(1, chooseK.rec(5, 5));
void itGeneratesOneCombinationWithZeroElements() {
var expected = "[[]]";
var actual = toS(nChooseK.generate(A, 0));
assertEquals(expected, actual);
}
@Test
void itCalculatesTheBaseCase() {
assertEquals(1, chooseK.rec(1, 0));
assertEquals(1, chooseK.rec(1, 1));
void itGeneratesFourCombinationsWithOneElement() {
var expected = "[[1], [2], [3], [4]]";
var actual = toS(nChooseK.generate(A, 1));
assertEquals(expected, actual);
}
@Nested
class WhenItGeneratesCombinations {
private Combinator<Integer> combinator;
private Integer[] A;
@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
void itGeneratesSixCombinationsWithTwoElements() {
var expected = "[[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]";
var actual = toS(nChooseK.generate(A, 2));
assertEquals(expected, actual);
}
@Test
void itGeneratesFourCombinationsWithThreeElements() {
var expected = "[[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]";
var actual = toS(combinator.generate(A, 3));
assertEquals(expected, actual);
}
@Test
void itGeneratesFourCombinationsWithThreeElements() {
var expected = "[[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]";
var actual = toS(nChooseK.generate(A, 3));
assertEquals(expected, actual);
}
@Test
void itGeneratesOneCombinationWithFourElements() {
var expected = "[[1, 2, 3, 4]]";
var actual = toS(combinator.generate(A, 4));
assertEquals(expected, actual);
}
@Test
void itGeneratesOneCombinationWithFourElements() {
var expected = "[[1, 2, 3, 4]]";
var actual = toS(nChooseK.generate(A, 4));
assertEquals(expected, actual);
}
@Test
void itGeneratesZeroCombinations() {
assertTrue(combinator.generate(A, 5).isEmpty());
}
@Test
void itGeneratesZeroCombinationsWithFiveElements() {
assertTrue(nChooseK.generate(A, 5).isEmpty());
}
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