Related
I am trying to do the following function in the java code below: I am trying to generate the array of integers that do not match between 'match' array and 'original' array.
To do this I created a subarray class, a class that allows me to get the rest of unmatched elements in the two arrays (match and original), and lastly, I have a class that is called match_sequence that does the job.
My problem is there is a bug in the function that I have no idea why, for example if my input is int[] original = {1,0}; int[] match = {1,0}; I get the residual for both original and match with [0] when it should be [], and if my inputs are {1,0,0},{1,0,0}, there is no such problem but if my inputs are both {1,0,1,0,0}, I got [0, 0] in both elements as unmatched array, when again, the result should be [] because those are perfectly matched arrays.
This is driving me insane can someone please let me know where is the bug?
import java.util.Arrays;
public class subarray
{
// Generic method to get subarray of a non-primitive array
// between specified indices
public static<T> int[] subArray(int[] arr, int beg, int end) {
return Arrays.copyOfRange(arr, beg, end+1);
}
}
import java.util.Arrays;
public class results {
private int[] array1; //array2
private int[] array2; //array1
public results (int[] result1, int[] result2)
{
array1 = result1;
array2 = result2;
//return results(array1,array2);
}
public int[] getArray1() { return array1; }
public int[] getArray2() { return array2; }
}
import java.util.Scanner;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class match_sequence {
public static results match_sequence(int[] original_rest,int[] match) {
if(match.length <= original_rest.length) {
for (int j = 0; j < match.length; j++) {
//set a initial starting point plus i if we are not starting from 0
if (original_rest[j]==match[j]) {
match = subarray.subArray(match,j+1,match.length-1);
original_rest = subarray.subArray(original_rest,j+1,original_rest.length-1);
} else if (original_rest[j]!=match[j]) {
original_rest = subarray.subArray(original_rest,j,original_rest.length-1);
match = subarray.subArray(match,j,match.length-1);
if(original_rest[0]!=match[0]){
System.out.println("This is not an interweave of two sub elements!");
}
break;
}
}
}
if(match.length > original_rest.length) {
for (int j = 0; j < original_rest.length; j++) {
//set a initial starting point plus i if we are not starting from 0
if (original_rest[j]==match[j]) {
match = subarray.subArray(match,j+1,match.length-1);
original_rest = subarray.subArray(original_rest,j+1,original_rest.length-1);
} else if (original_rest[j]!=match[j]) {
original_rest = subarray.subArray(original_rest,j,original_rest.length-1);
match = subarray.subArray(match,j,match.length-1);
if(original_rest[0]!=match[0]) {
System.out.println("This is not an interweave of two sub elements!");
}
break;
}
}
}
return new results(match,original_rest);
}
//here is the problem:
public static void main(String[] args)
{
int[] original = {1,0};
int[] match = {1,0};
//bug1: there is mismatch over here and should be resolved through debugging
int[] rest_of_match = match_sequence(original,match).getArray1();
System.out.println("Final match"+Arrays.toString(rest_of_match));
int[] original_rest = match_sequence(original,match).getArray2();
System.out.println("Final original"+Arrays.toString(original_rest));
}
}
The problem is inside match_sequence() method. You slice first element of an array, but you don't move j index back. To do so add such line at the end of for loop:
j--;
Also match_sequence() contains big code duplication. If statements are redudant, you can combine them in one for loop:
public static results match_sequence(int[] original_rest, int[] match) {
for(int j = 0; j < Math.min(match.length, original_rest.length); j++) {
//set a initial starting point plus i if we are not starting from 0
if(original_rest[j] == match[j]) {
match = subarray.subArray(match, j + 1, match.length - 1);
original_rest = subarray.subArray(original_rest, j + 1, original_rest.length - 1);
} else if(original_rest[j] != match[j]) {
original_rest = subarray.subArray(original_rest, j, original_rest.length - 1);
match = subarray.subArray(match, j, match.length - 1);
if(original_rest[0] != match[0]) {
System.out.println("This is not an interweave of two sub elements!");
}
break;
}
j--;
}
return new results(match, original_rest);
}
Output:
Final match[]
Final original[]
Update:
Picture below shows why you need to move j back. If you don't do that, then you will skip second element of list.
This is from code fights. The method works but is apparently taking too long for large inputs. Can someone please explain what is inefficient about this solution?
Question:
Given an array of integers, write a function that determines whether the array contains any duplicates. Your function should return true if any element appears at least twice in the array, and it should return false if every element is distinct.
Example
For a = [1, 2, 3, 1], the output should be
containsDuplicates(a) = true.
There are two 1s in the given array.
Solution:
static boolean containsDuplicates(int[] a) {
boolean elementRepeat = false;
for (int loop1 = 0; loop1 < a.length; loop1++){
for (int loop2 = 0; loop2 < a.length; loop2++){
if (a[loop1] == a[loop2] && loop1!=loop2){
elementRepeat = true;
return elementRepeat;
}
}
}
return elementRepeat;
}
One way to do this is by storing the array in Set and then comparing the length of the array and set. Here is how:
static boolean containsDuplicates(int[] array) {
HashSet<Integer> integers = new HashSet<>();
Arrays.stream(array).forEach(integers::add);
array.length == integers.size();
}
I think that #Henry did a very good sugestion.
This is an example:
import java.util.HashSet;
import java.util.Set;
public class Test4 {
public static void main(String[] args) {
Integer[] arrayInt = {1, 2, 3, 1};
Set<Integer> integers = new HashSet<Integer>();
boolean hasDuplicates = false;
for (Integer integerNumber : arrayInt) {
if (!integers.add(integerNumber)) {
hasDuplicates = true;
break;
}
}
System.out.println("Contains duplicates? " + hasDuplicates);
}
}
And it will print:
Contains duplicates? true
I'm trying to solve the two sum algorithm on Leetcode:
Given an array of integers, return indices of the two numbers such that they add up to a specific target. You may assume that each input would have exactly one solution, and you may not use the same element twice.
And came up with this:
public class Leet {
public static void main(String[] args) {
System.out.println(Arrays.toString(twoSum(new int[]{1, 2, 3, 4, 5, 6}, 2)));
}
public static int[] twoSum(int[] nums, int target) {
int[] answer = null;
int i = 0;
for (int j = nums[i]; i < nums.length; i++) {
for (int x : nums) {
if (x != j & (j + x) == target) {
int x2 = java.util.Arrays.asList(nums).indexOf(x);
answer[0] = i;
answer[1] = x2;
} else {
return nums;
}
}
}
System.out.println("leet method executed");
return answer;
}
}
The problem is it's not returning anything, not event the printed statement. Any ideas?
See some fixes. Remember about array initialization and cases when values can be same in the array.
public class Solution {
public int[] twoSum(int[] nums, int target) {
int[] answer = null;
for(int i=0;i<nums.length;i++) {
int value = nums[i];
for(int j=i+1;j<nums.length;j++) {
int x=nums[j];
if ((value+x)==target) {
answer = new int[2];
answer[0]=i;
answer[1]=j;
}
}
}
System.out.println("leet method executed");
if (answer == null) {
return nums;
}
return answer;
}
}
I can see 2 things wrong or not intended in the program (leaving aside whether it's the best approach to the problem).
As stated in a comment, you should use && instead of & for boolean AND. & is bitwise AND, useful for integer bit twiddling.
You declare answer as an array, but never create space for it. You need to say int [] answer = new int[2]; or similar.
I haven't run the code, but if the test program ends with no output, check that you aren't getting a NullPointerException (caused by #2 above).
Don't forget about null-checks and the case where no correct number-pair was found.
public static int[] twoSum(int[] numbers, int target) {
if(Objects.isNull(numbers)){
throw new IllegalArgumentException("numbers is not allowed to be null");
}
for (int a=0;a<numbers.length;a++) {
int first = numbers[a];
for (int b=0;b<numbers.length;b++) {
int second = numbers[b];
if (first + second == target && a!=b) {
return new int[] { first, second };
}
}
}
throw new IllegalArgumentException("there has to be a matching pair");
}
I'm writing a code where I have an int[a] and the method should return the number of unique values. Example: {1} = 0 different values, {3,3,3} = 0 different values, {1,2} = 2 different values, {1,2,3,4} = 4 different values etc. I am not allowed to sort the array.
The thing is that my method doesn't work probably. There is something wrong with my for statement and I can't figure it out.
public class Program
{
public static void main(String[] args)
{
int[] a = {1, 2, 3, 1};
System.out.println(differentValuesUnsorted(a));
//run: 4 //should be 3
}
public static int differentValuesUnsorted(int[] a)
{
int values; //values of different numbers
if (a.length < 2)
{
return values = 0;
}else if (a[0] == a[1])
{
return values = 0;
}else
{
values = 2;
}
int numberValue = a[0];
for (int i = a[1]; i < a.length; i++)
{
if (a[i] != numberValue)
{
numberValue++;
values++;
}
}
return values;
}
}
Can anybody help?
This is actually much simpler than most people have made it out to be, this method works perfectly fine:
public static int diffValues(int[] numArray){
int numOfDifferentVals = 0;
ArrayList<Integer> diffNum = new ArrayList<>();
for(int i=0; i<numArray.length; i++){
if(!diffNum.contains(numArray[i])){
diffNum.add(numArray[i]);
}
}
if(diffNum.size()==1){
numOfDifferentVals = 0;
}
else{
numOfDifferentVals = diffNum.size();
}
return numOfDifferentVals;
}
Let me walk you through it:
1) Provide an int array as a parameter.
2) Create an ArrayList which will hold integers:
If that arrayList DOES NOT contain the integer with in the array
provided as a parameter, then add that element in the array parameter
to the array list
If that arrayList DOES contain that element from the int array parameter, then do nothing. (DO NOT ADD THAT VALUE TO THE ARRAY LIST)
N.B: This means that the ArrayList contains all the numbers in the int[], and removes the repeated numbers.
3) The size of the ArrayList (which is analogous to the length property of an array) will be the number of different values in the array provided.
Trial
Input:
int[] numbers = {3,1,2,2,2,5,2,1,9,7};
Output: 6
First create distinct value array, It can simply create using HashSet.
Then alreadyPresent.size() will provide number of different values. But for the case such as -{3,3,3} = 0 (array contains same elements); output of alreadyPresent.size() is 1. For that use this simple filter
if(alreadyPresent.size() == 1)){
return 0;
}
Following code will give the count of different values.
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class Demo {
public static void main(String[] args)
{
int array[] = {9,9,5,2,3};
System.out.println(differentValuesUnsorted(array));
}
public static int differentValuesUnsorted(int[] array)
{
Set<Integer> alreadyPresent = new HashSet<Integer>();
for (int nextElem : array) {
alreadyPresent.add(nextElem);
}
if(alreadyPresent.size() == 1){
return 0;
}
return alreadyPresent.size();
}
}
You can use a HashSet, which can only contain unique elements. The HashSet will remove the duplicated items and you can then get the size of the set.
public static int differentValuesUnsorted(int[] a) {
Set<Integer> unique = new HashSet<Integer>();
for (int val : a) {
unique.add(val); // will only be added if a is not in unique
}
if (unique.size() < 2) { // if there are no different values
return 0;
}
return unique.size();
}
For small arrays, this is a fast concise method that does not require the allocation of any additional temporary objects:
public static int uniqueValues(int[] ids) {
int uniques = 0;
top:
for (int i = 0; i < ids.length; i++) {
final int id = ids[i];
for (int j = i + 1; j < ids.length; j++) {
if (id == ids[j]) continue top;
}
uniques++;
}
return uniques;
}
Try this:
import java.util.ArrayList;
public class DifferentValues {
public static void main(String[] args)
{
int[] a ={1, 2, 3, 1};
System.out.println(differentValuesUnsorted(a));
}
public static int differentValuesUnsorted(int[] a)
{
ArrayList<Integer> ArrUnique = new ArrayList<Integer>();
int values=0; //values of different numbers
for (int num : a) {
if (!ArrUnique.contains(num)) ArrUnique.add(num);
}
values = ArrUnique.size();
if (values == 1) values = 0;
return values;
}
}
input:{1,1,1,1,1} - output: 0
input:{1,2,3,1} - output: 3
Try this... its pretty simple using ArrayList. You don't even need two loop. Go on
import java.util.*;
public class distinctNumbers{
public static void main(String []args){
int [] numbers = {2, 7, 3, 2, 3, 7, 7};
ArrayList<Integer> list=new ArrayList<Integer>();
for(int i=0;i<numbers.length;i++)
{
if(!list.contains(numbers[i])) //checking if the number is present in the list
{
list.add(numbers[i]); //if not present then add the number to the list i.e adding the distinct number
}
}
System.out.println(list.size());
}
}
Try this simple code snippet.
public static int differentValuesUnsorted(int[] a)
{
ArrayList<Integer> list=new ArrayList<Integer>(); //import java.util.*;
for(int i:numbers) //Iterate through all the elements
if(!list.contains(i)) //checking for duplicate element
list.add(i); //Add to list if unique
return list.size();
}
What about this?
private <T> int arrayDistinctCount(T[] array) {
return Arrays.stream(array).collect(Collectors.toSet()).size();
}
Use a set to remove duplicates
public static int differentValuesUnsorted(int[] a) {
if (a.length < 2) {
return 0;
}
Set<Integer> uniques = new HashSet<>(a);
return singleUnique.size();
}
I'm working on a puzzle that involves analyzing all size k subsets and figuring out which one is optimal. I wrote a solution that works when the number of subsets is small, but it runs out of memory for larger problems. Now I'm trying to translate an iterative function written in python to java so that I can analyze each subset as it's created and get only the value that represents how optimized it is and not the entire set so that I won't run out of memory. Here is what I have so far and it doesn't seem to finish even for very small problems:
public static LinkedList<LinkedList<Integer>> getSets(int k, LinkedList<Integer> set)
{
int N = set.size();
int maxsets = nCr(N, k);
LinkedList<LinkedList<Integer>> toRet = new LinkedList<LinkedList<Integer>>();
int remains, thresh;
LinkedList<Integer> newset;
for (int i=0; i<maxsets; i++)
{
remains = k;
newset = new LinkedList<Integer>();
for (int val=1; val<=N; val++)
{
if (remains==0)
break;
thresh = nCr(N-val, remains-1);
if (i < thresh)
{
newset.add(set.get(val-1));
remains --;
}
else
{
i -= thresh;
}
}
toRet.add(newset);
}
return toRet;
}
Can anybody help me debug this function or suggest another algorithm for iteratively generating size k subsets?
EDIT: I finally got this function working, I had to create a new variable that was the same as i to do the i and thresh comparison because python handles for loop indexes differently.
First, if you intend to do random access on a list, you should pick a list implementation that supports that efficiently. From the javadoc on LinkedList:
All of the operations perform as could be expected for a doubly-linked
list. Operations that index into the list will traverse the list from
the beginning or the end, whichever is closer to the specified index.
An ArrayList is both more space efficient and much faster for random access. Actually, since you know the length beforehand, you can even use a plain array.
To algorithms: Let's start simple: How would you generate all subsets of size 1? Probably like this:
for (int i = 0; i < set.length; i++) {
int[] subset = {i};
process(subset);
}
Where process is a method that does something with the set, such as checking whether it is "better" than all subsets processed so far.
Now, how would you extend that to work for subsets of size 2? What is the relationship between subsets of size 2 and subsets of size 1? Well, any subset of size 2 can be turned into a subset of size 1 by removing its largest element. Put differently, each subset of size 2 can be generated by taking a subset of size 1 and adding a new element larger than all other elements in the set. In code:
processSubset(int[] set) {
int subset = new int[2];
for (int i = 0; i < set.length; i++) {
subset[0] = set[i];
processLargerSets(set, subset, i);
}
}
void processLargerSets(int[] set, int[] subset, int i) {
for (int j = i + 1; j < set.length; j++) {
subset[1] = set[j];
process(subset);
}
}
For subsets of arbitrary size k, observe that any subset of size k can be turned into a subset of size k-1 by chopping of the largest element. That is, all subsets of size k can be generated by generating all subsets of size k - 1, and for each of these, and each value larger than the largest in the subset, add that value to the set. In code:
static void processSubsets(int[] set, int k) {
int[] subset = new int[k];
processLargerSubsets(set, subset, 0, 0);
}
static void processLargerSubsets(int[] set, int[] subset, int subsetSize, int nextIndex) {
if (subsetSize == subset.length) {
process(subset);
} else {
for (int j = nextIndex; j < set.length; j++) {
subset[subsetSize] = set[j];
processLargerSubsets(set, subset, subsetSize + 1, j + 1);
}
}
}
Test code:
static void process(int[] subset) {
System.out.println(Arrays.toString(subset));
}
public static void main(String[] args) throws Exception {
int[] set = {1,2,3,4,5};
processSubsets(set, 3);
}
But before you invoke this on huge sets remember that the number of subsets can grow rather quickly.
You can use
org.apache.commons.math3.util.Combinations.
Example:
import java.util.Arrays;
import java.util.Iterator;
import org.apache.commons.math3.util.Combinations;
public class tmp {
public static void main(String[] args) {
for (Iterator<int[]> iter = new Combinations(5, 3).iterator(); iter.hasNext();) {
System.out.println(Arrays.toString(iter.next()));
}
}
}
Output:
[0, 1, 2]
[0, 1, 3]
[0, 2, 3]
[1, 2, 3]
[0, 1, 4]
[0, 2, 4]
[1, 2, 4]
[0, 3, 4]
[1, 3, 4]
[2, 3, 4]
Here is a combination iterator I wrote recetnly
package psychicpoker;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import static com.google.common.base.Preconditions.checkArgument;
public class CombinationIterator<T> implements Iterator<Collection<T>> {
private int[] indices;
private List<T> elements;
private boolean hasNext = true;
public CombinationIterator(List<T> elements, int k) throws IllegalArgumentException {
checkArgument(k<=elements.size(), "Impossible to select %d elements from hand of size %d", k, elements.size());
this.indices = new int[k];
for(int i=0; i<k; i++)
indices[i] = k-1-i;
this.elements = elements;
}
public boolean hasNext() {
return hasNext;
}
private int inc(int[] indices, int maxIndex, int depth) throws IllegalStateException {
if(depth == indices.length) {
throw new IllegalStateException("The End");
}
if(indices[depth] < maxIndex) {
indices[depth] = indices[depth]+1;
} else {
indices[depth] = inc(indices, maxIndex-1, depth+1)+1;
}
return indices[depth];
}
private boolean inc() {
try {
inc(indices, elements.size() - 1, 0);
return true;
} catch (IllegalStateException e) {
return false;
}
}
public Collection<T> next() {
Collection<T> result = new ArrayList<T>(indices.length);
for(int i=indices.length-1; i>=0; i--) {
result.add(elements.get(indices[i]));
}
hasNext = inc();
return result;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
I've had the same problem today, of generating all k-sized subsets of a n-sized set.
I had a recursive algorithm, written in Haskell, but the problem required that I wrote a new version in Java.
In Java, I thought I'd probably have to use memoization to optimize recursion. Turns out, I found a way to do it iteratively. I was inspired by this image, from Wikipedia, on the article about Combinations.
Method to calculate all k-sized subsets:
public static int[][] combinations(int k, int[] set) {
// binomial(N, K)
int c = (int) binomial(set.length, k);
// where all sets are stored
int[][] res = new int[c][Math.max(0, k)];
// the k indexes (from set) where the red squares are
// see image above
int[] ind = k < 0 ? null : new int[k];
// initialize red squares
for (int i = 0; i < k; ++i) { ind[i] = i; }
// for every combination
for (int i = 0; i < c; ++i) {
// get its elements (red square indexes)
for (int j = 0; j < k; ++j) {
res[i][j] = set[ind[j]];
}
// update red squares, starting by the last
int x = ind.length - 1;
boolean loop;
do {
loop = false;
// move to next
ind[x] = ind[x] + 1;
// if crossing boundaries, move previous
if (ind[x] > set.length - (k - x)) {
--x;
loop = x >= 0;
} else {
// update every following square
for (int x1 = x + 1; x1 < ind.length; ++x1) {
ind[x1] = ind[x1 - 1] + 1;
}
}
} while (loop);
}
return res;
}
Method for the binomial:
(Adapted from Python example, from Wikipedia)
private static long binomial(int n, int k) {
if (k < 0 || k > n) return 0;
if (k > n - k) { // take advantage of symmetry
k = n - k;
}
long c = 1;
for (int i = 1; i < k+1; ++i) {
c = c * (n - (k - i));
c = c / i;
}
return c;
}
Of course, combinations will always have the problem of space, as they likely explode.
In the context of my own problem, the maximum possible is about 2,000,000 subsets. My machine calculated this in 1032 milliseconds.
Inspired by afsantos's answer :-)... I decided to write a C# .NET implementation to generate all subset combinations of a certain size from a full set. It doesn't need to calc the total number of possible subsets; it detects when it's reached the end. Here it is:
public static List<object[]> generateAllSubsetCombinations(object[] fullSet, ulong subsetSize) {
if (fullSet == null) {
throw new ArgumentException("Value cannot be null.", "fullSet");
}
else if (subsetSize < 1) {
throw new ArgumentException("Subset size must be 1 or greater.", "subsetSize");
}
else if ((ulong)fullSet.LongLength < subsetSize) {
throw new ArgumentException("Subset size cannot be greater than the total number of entries in the full set.", "subsetSize");
}
// All possible subsets will be stored here
List<object[]> allSubsets = new List<object[]>();
// Initialize current pick; will always be the leftmost consecutive x where x is subset size
ulong[] currentPick = new ulong[subsetSize];
for (ulong i = 0; i < subsetSize; i++) {
currentPick[i] = i;
}
while (true) {
// Add this subset's values to list of all subsets based on current pick
object[] subset = new object[subsetSize];
for (ulong i = 0; i < subsetSize; i++) {
subset[i] = fullSet[currentPick[i]];
}
allSubsets.Add(subset);
if (currentPick[0] + subsetSize >= (ulong)fullSet.LongLength) {
// Last pick must have been the final 3; end of subset generation
break;
}
// Update current pick for next subset
ulong shiftAfter = (ulong)currentPick.LongLength - 1;
bool loop;
do {
loop = false;
// Move current picker right
currentPick[shiftAfter]++;
// If we've gotten to the end of the full set, move left one picker
if (currentPick[shiftAfter] > (ulong)fullSet.LongLength - (subsetSize - shiftAfter)) {
if (shiftAfter > 0) {
shiftAfter--;
loop = true;
}
}
else {
// Update pickers to be consecutive
for (ulong i = shiftAfter+1; i < (ulong)currentPick.LongLength; i++) {
currentPick[i] = currentPick[i-1] + 1;
}
}
} while (loop);
}
return allSubsets;
}
This solution worked for me:
private static void findSubsets(int array[])
{
int numOfSubsets = 1 << array.length;
for(int i = 0; i < numOfSubsets; i++)
{
int pos = array.length - 1;
int bitmask = i;
System.out.print("{");
while(bitmask > 0)
{
if((bitmask & 1) == 1)
System.out.print(array[pos]+",");
bitmask >>= 1;
pos--;
}
System.out.print("}");
}
}
Swift implementation:
Below are two variants on the answer provided by afsantos.
The first implementation of the combinations function mirrors the functionality of the original Java implementation.
The second implementation is a general case for finding all combinations of k values from the set [0, setSize). If this is really all you need, this implementation will be a bit more efficient.
In addition, they include a few minor optimizations and a smidgin logic simplification.
/// Calculate the binomial for a set with a subset size
func binomial(setSize: Int, subsetSize: Int) -> Int
{
if (subsetSize <= 0 || subsetSize > setSize) { return 0 }
// Take advantage of symmetry
var subsetSizeDelta = subsetSize
if (subsetSizeDelta > setSize - subsetSizeDelta)
{
subsetSizeDelta = setSize - subsetSizeDelta
}
// Early-out
if subsetSizeDelta == 0 { return 1 }
var c = 1
for i in 1...subsetSizeDelta
{
c = c * (setSize - (subsetSizeDelta - i))
c = c / i
}
return c
}
/// Calculates all possible combinations of subsets of `subsetSize` values within `set`
func combinations(subsetSize: Int, set: [Int]) -> [[Int]]?
{
// Validate inputs
if subsetSize <= 0 || subsetSize > set.count { return nil }
// Use a binomial to calculate total possible combinations
let comboCount = binomial(setSize: set.count, subsetSize: subsetSize)
if comboCount == 0 { return nil }
// Our set of combinations
var combos = [[Int]]()
combos.reserveCapacity(comboCount)
// Initialize the combination to the first group of set indices
var subsetIndices = [Int](0..<subsetSize)
// For every combination
for _ in 0..<comboCount
{
// Add the new combination
var comboArr = [Int]()
comboArr.reserveCapacity(subsetSize)
for j in subsetIndices { comboArr.append(set[j]) }
combos.append(comboArr)
// Update combination, starting with the last
var x = subsetSize - 1
while true
{
// Move to next
subsetIndices[x] = subsetIndices[x] + 1
// If crossing boundaries, move previous
if (subsetIndices[x] > set.count - (subsetSize - x))
{
x -= 1
if x >= 0 { continue }
}
else
{
for x1 in x+1..<subsetSize
{
subsetIndices[x1] = subsetIndices[x1 - 1] + 1
}
}
break
}
}
return combos
}
/// Calculates all possible combinations of subsets of `subsetSize` values within a set
/// of zero-based values for the set [0, `setSize`)
func combinations(subsetSize: Int, setSize: Int) -> [[Int]]?
{
// Validate inputs
if subsetSize <= 0 || subsetSize > setSize { return nil }
// Use a binomial to calculate total possible combinations
let comboCount = binomial(setSize: setSize, subsetSize: subsetSize)
if comboCount == 0 { return nil }
// Our set of combinations
var combos = [[Int]]()
combos.reserveCapacity(comboCount)
// Initialize the combination to the first group of elements
var subsetValues = [Int](0..<subsetSize)
// For every combination
for _ in 0..<comboCount
{
// Add the new combination
combos.append([Int](subsetValues))
// Update combination, starting with the last
var x = subsetSize - 1
while true
{
// Move to next
subsetValues[x] = subsetValues[x] + 1
// If crossing boundaries, move previous
if (subsetValues[x] > setSize - (subsetSize - x))
{
x -= 1
if x >= 0 { continue }
}
else
{
for x1 in x+1..<subsetSize
{
subsetValues[x1] = subsetValues[x1 - 1] + 1
}
}
break
}
}
return combos
}