I'm having trouble implementing a method to create an array of distances using BFS from a chosen starting vertex, it currently seems to work in some cases, but fails in larger graphs. The idea is each index in the array represents the corresponding vertex in a graph.
here is the relevant code
public int[] getDistances(Graph g, int startVertex) {
boolean[] visited = new boolean[g.getNumberOfVertices()];
int[] distance = new int[g.getNumberOfVertices()];
for (int i = 0; i < distance.length; i++)
{
distance[i] = -1;
}
ArrayList<Integer> q = new ArrayList<Integer>();
q.add(startVertex);
int dist_int = 0;
while (!q.isEmpty())
{
int current = q.get(0);
q.remove(0);
dist_int++;
visited[startVertex] = true;
for (int j = 0; j < g.getEdgeMatrix()[current].length; j++)
{
if (startVertex == j)
distance[j] = 0;
if (g.getEdgeMatrix()[current][j] == 1 && !visited[j])
{
q.add(j);
distance[j] = dist_int;
visited[j] = true;
}
}
}
return distance;
}
the idea is it iterates through an adjacency matrix, determining each unvisited child, each time a child is found the current dist_int is assigned to the corresponding index in the distance array. With the distance increasing each time all of the children of the current node have been assigned, then the current moves to the first child and repeats.
Instead of using dist_int to hold the distance values just call
distance[j] = distance[current] + 1;
I have implemented an program that can calculate shortest path's for any graph either by using Floyd's/Dijkstra's algorithm based on user input.
Both algorithm's work fine for directed graph.
The output is supposed to display
1)The actual path to be taken from the start vertex
2)The shortest distance to be travelled
But when it come's to undirected graph I run into problems.
My graph is not represented by an adjacency matrix but with an Graph & Edge classes as shown below
class Graph
{
private final int noOfVertices;
private final ArrayList<Edge> edges = new ArrayList<Edge>();
private boolean undirected = false;
Graph(int vertexCount)
{
noOfVertices = vertexCount;
edges.ensureCapacity(2 * (vertexCount - 1));
}
public int getWeight(int src,int dst)
{
int weight=90000;
for(Edge edge:edges)
{
if(edge.src==src && edge.dst==dst)
{
weight=edge.weight;
break;
}
}
return weight;
}
public int getEdgeCount(){return edges.size();}
public int getVertexCount(){return noOfVertices;}
public static class Edge
{
public int src;
public int dst;
public int weight;
Edge(int v1, int v2, int w)
{
src = v1;
dst = v2;
weight = w;
}
}
}
To implement undirected graph this is the code used below
void newEdge(int src,int dst,int weight)
{
edges.add(new Edge(src,dst,weight));
if(undirected){ edges.add(new Edge(dst,src,weight));}
}
Now Dijkstra's algorithm work's fine on this setup but when I use Floyd's algorithm I start to get incorrect path's but correct distance's
This is my Floyd's algorithm
public static Integer[] Floyd(Graph graph, int startVertex, int endVertex)
{
ArrayList<Integer> pathInfo = new ArrayList<Integer>();
int dist[][] = new int[graph.getVertexCount()][graph.getVertexCount()];
int path[][] = new int[graph.getVertexCount()][graph.getVertexCount()];
int V = graph.getVertexCount();
for (int i = 0; i < V; i++)
{
for (int j = 0; j < V; j++)
{
if (i == j)
{
dist[i][j] = 0;
}
else
{
dist[i][j] = graph.getWeight(i, j);
}/*Initialize with edge weight's between vertices i,j.If edge does not exist graph.getWeight() return's 90000 i.e simply an value somewhat close to infinite because when I use Integer.MAX_VALUE I get negative distance's when doing dist[i][k]+dist[k][j] so i avoid it*/
path[i][j] = j;
}
}
/*actual Floyd's algorithm*/
for (int k = 0; k < V; k++)
{
for (int i = 0; i < V; i++)
{
for (int j = 0; j < V; j++)
{
if (dist[i][j] > dist[i][k] + dist[k][j])
{
dist[i][j] = dist[i][k] + dist[k][j];
path[i][j] = k; /*if path exist's record the intermediate vertex*/
}
}
}
}
int currentVertex=endVertex; /*Start from last vertex*/
int nextVertex=path[startVertex][endVertex];/*Find path*/
pathInfo.add(currentVertex);/*Add Current Vertex*/
while(currentVertex!=nextVertex)/*Backtrack until the vertex we are currently at and the next vertex we need to go to from there are the same which mean's we have reached our target*/
{
currentVertex=nextVertex;
pathInfo.add(0,currentVertex);
nextVertex=path[startVertex][nextVertex];
}
pathInfo.add(0,startVertex);/*Finally add the vertex we ended at*/
pathInfo.add(dist[startVertex][endVertex]);/*Come's out correct in both cases*/
return pathInfo.toArray(new Integer[]{});/*Convert info to array*/
}
So here is my undirected graph given below.
The doted lines represent's an edge that goes in both direction's.
0--1--2--3
Each edge has an weight of 2
Now when I call Floyd's algorithm with start vertex=0 and end vertex=3
I get The correct output path.
0,1,2,3
But when I again call Floyd's algorithm with start Vertex=3 and end Vertex=0
The output path is
3,2,0
Vertex 1 is missing.
But with Dijkstra's algorithm I get the correct result's in both cases
Here is the path matrix calculated above.
0 1 1 2
0 1 2 2
1 1 2 3
2 2 2 3
The distance come's out correct that is 6 in both cases but the path is wrong when I reverse the vertex order only for Floyd's algorithm.
Most of the video ideas were incorporated from this link
https://www.bing.com/videos/search?q=floyd%27s+algorithm&&view=detail&mid=E17F409B3AB0B2307233E17F409B3AB0B2307233&&FORM=VRDGAR
Any idea's on where I went wrong?
I wrote this algorithm. It works (at least with my short test cases), but takes too long on larger inputs. How can I make it faster?
// Returns an array of length 2 with the two closest points to each other from the
// original array of points "arr"
private static Point2D[] getClosestPair(Point2D[] arr)
{
int n = arr.length;
float min = 1.0f;
float dist = 0.0f;
Point2D[] ret = new Point2D[2];
// If array only has 2 points, return array
if (n == 2) return arr;
// Algorithm says to brute force at 3 or lower array items
if (n <= 3)
{
for (int i = 0; i < arr.length; i++)
{
for (int j = 0; j < arr.length; j++)
{
// If points are identical but the point is not looking
// at itself, return because shortest distance is 0 then
if (i != j && arr[i].equals(arr[j]))
{
ret[0] = arr[i];
ret[1] = arr[j];
return ret;
}
// If points are not the same and current min is larger than
// current stored distance
else if (i != j && dist < min)
{
dist = distanceSq(arr[i], arr[j]);
ret[0] = arr[i];
ret[1] = arr[j];
min = dist;
}
}
}
return ret;
}
int halfN = n/2;
// Left hand side
Point2D[] LHS = Arrays.copyOfRange(arr, 0, halfN);
// Right hand side
Point2D[] RHS = Arrays.copyOfRange(arr, halfN, n);
// Result of left recursion
Point2D[] LRes = getClosestPair(LHS);
// Result of right recursion
Point2D[] RRes = getClosestPair(RHS);
float LDist = distanceSq(LRes[0], LRes[1]);
float RDist = distanceSq(RRes[0], RRes[1]);
// Calculate minimum of both recursive results
if (LDist > RDist)
{
min = RDist;
ret[0] = RRes[0];
ret[1] = RRes[1];
}
else
{
min = LDist;
ret[0] = LRes[0];
ret[1] = LRes[1];
}
for (Point2D q : LHS)
{
// If q is close to the median line
if ((halfN - q.getX()) < min)
{
for (Point2D p : RHS)
{
// If p is close to q
if ((p.getX() - q.getX()) < min)
{
dist = distanceSq(q, p);
if (!q.equals(p) && dist < min)
{
min = dist;
ret[0] = q;
ret[1] = p;
}
}
}
}
}
return ret;
}
private static float distanceSq(Point2D p1, Point2D p2)
{
return (float)Math.pow((p1.getX() - p2.getX()) + (p1.getY() - p2.getY()), 2);
}
I am loosely following the algorithm explained here: http://www.cs.mcgill.ca/~cs251/ClosestPair/ClosestPairDQ.html
and a different resource with pseudocode here:
http://i.imgur.com/XYDTfBl.png
I cannot change the return type of the function, or add any new arguments.
Thanks for any help!
There are several things you can do.
First, you can very simply cut the time the program takes to run by changing the second iteration to run only on the "reminder" points. This helps you to avoid calculating both (i,j) and (j,i) for each values. To do so, simply change:
for (int j = 0; j < arr.length; j++)
to
for (int j = i+1; j < arr.length; j++)
This will still be O(n^2) though.
You can achieve O(nlogn) time by iterating the points, and storing each in a smart data structure (kd-tree most likely). Before each insertion, find the closest point already stored in the DS (the kd-tree supports this in O(logn) time), and it is your candidate for minimal distance.
I believe the linked algorithm mentions sorting the array by one coordinate so that given LHS q in point 1 to 2000, if RHS p at point 200 is more than 'min' distance away with only its x distance, you can avoid checking the remaining 201 to 2000 points.
I figured it out - cut the time by a vast amount. The distanceSq function is wrong. Best to use Java's Point2D somepoint.distanceSq(otherpoint); method instead.
As for the original brute force when n is 3 (it will only ever be 3 or 2 in that scenario), a linear search is better and more effective.
The checks against the min variable are also wrong in the inner for loops after the brute force condition. Using squared distance is fine, but min is not squared. It has preserved, original distance, which means that min must be square rooted in both checks (once in the outer loop, once in the inner for each check).
So,
if ((p.getX() - q.getX()) < min)
Should be
if ((p.getX() - q.getX()) < Math.sqrt(min))
Same goes for the other check.
Thanks for your answers everyone!
Really stumped on this one, don't know where to begin. I thought about making a separate method which calculates the paths between two different vertices, but I don't know how I would implement that.
I thought that finding the minimum degree of the graph and then adding one would give me the girth, but that is assuming there is a cycle in the graph. So I would need the program to scan through the adjacency matrix, somehow uses the true values to find out if there is a cycle or not and then calculate the distance of that cycle.
Looking for a step in the right direction.
Also I'm looking to not use the ArrayList approach, hence why I'm stumped
This is what I have so far:
import java.util.Scanner;
import java.util.*;
public class Graph {
// Setup privately modified variables which will define the graph
// These two parameters are storage variables for edges and vertices
//These variables were changed from Vertex and Edge to numVertices and numEdges.
private int numVertices;
private int numEdges;
// This will be the adjacency matrix to represent our graph, this will
// represent edges.
// adj_Matrix_Edges was previously static meaning it did not have access to multiple graphs, onyl one graph.
private boolean[][] adj_Matrix_Edges;
// first step will be to setup the graph, using this constructor
public Graph(int vertices) {
numVertices = vertices;
if (numVertices < 0) {
throw new RuntimeException(
"Number of vertices cannot be a nonnegative value");
}
System.out.println("There are now " + numVertices
+ " vertices in the graph.");
// A graph is created based on the specifications, N X N or (n^2)
// graph.
adj_Matrix_Edges = new boolean[vertices][vertices];
}
// This method validates whether or not two vertices are adjacent, returns
// true if adjacent false otherwise.
public boolean adjacent(int i, int j) {
if (adj_Matrix_Edges[i][j] == true) {
return true;
} else {
return false;
}
}
// I needed a review of this class so I had to read about ArrayList class, but it allows
// you to iterate the columns in the adjacency matrix.
// It also allows you to print out integers values instead of booleans
// The for loop, loops over a column you would select, and then the if
// statement checks for an incident in that column.
public List<Integer> neighbors(int vertex) {
List<Integer> neighbors = new ArrayList<Integer>();
for (int i = 0; i < adj_Matrix_Edges.length; i++) {
// The if statement here does not need an equality sign since
// booleans are in the 2-d matrix.
if (adj_Matrix_Edges[vertex][i]) {
// adds that vertex i to the list
neighbors.add(i);
}
}
System.out.println("The neighbors of vertex " + vertex + " are " + neighbors);
return neighbors;
}
//This method will count the number of neighbors for a specific vertex.
public double averageDegree(){
//create a variable for the count, and initialize the counter to 0.
double neighborCount = 0;
for (int i = 0; i < adj_Matrix_Edges.length; i++){
for (int j = 0; j < adj_Matrix_Edges[i].length; j++){
//this if statement scans the specific vertex for true statements in the boolean array
if (adj_Matrix_Edges[i][j]){
// this logical expression adds up the count of the true statements, in graph theory this is adding up the
// degree of that specific vertex.
neighborCount++;
}
}
}
neighborCount= neighborCount / numVertices;
System.out.println("The average degree of the graph is " + neighborCount);
return neighborCount;
}
public boolean[][] addVertex() {
// add an extra vertex to the graph.
numVertices++;
// secondly we have to copy over the contents of the old array into a new array.
// Initialize a new array
boolean[][] new_adj_Matrix_Edges = adj_Matrix_Edges;
// setup a for loop which sets up new values for
for (int i = 0; i < adj_Matrix_Edges.length; i++){
for (int j = 0; j < adj_Matrix_Edges.length; j++){
adj_Matrix_Edges[i][j] = new_adj_Matrix_Edges[i + 1][j + 1];
}
}
return new_adj_Matrix_Edges;
}
public boolean[][] removeVertex(int vertex){
// set a local variable.
int vertex_Selected = vertex;
// create a new 2-d array where you can copy the old one over.
boolean[][] new_adj_Matrix_Edges = adj_Matrix_Edges;
//create a for loop setup to copy over all data from old array to the new array.
for (int g = 0; g < adj_Matrix_Edges.length; g++){
for (int h = 0; h < adj_Matrix_Edges[g].length; h++){
adj_Matrix_Edges[g][h] = new_adj_Matrix_Edges[g][h];
}
}
// now that a new array has been created, and all information is copied over we can then set
// all values of the selected vertex to false.
for (int i = 0; i < new_adj_Matrix_Edges.length; i++){
for (int j = 0; j < new_adj_Matrix_Edges[i].length; j++){
if (new_adj_Matrix_Edges[vertex_Selected][j] == true){
new_adj_Matrix_Edges[vertex_Selected][j] = false;
}
if (new_adj_Matrix_Edges[i][vertex_Selected] == true){
new_adj_Matrix_Edges[i][vertex_Selected] = false;
}
}
}
return new_adj_Matrix_Edges;
}
public void addEdge(int vertex_add_1, int vertex_add_2) {
if (adj_Matrix_Edges[vertex_add_1][vertex_add_2] == false) {
adj_Matrix_Edges[vertex_add_1][vertex_add_2] = true;
adj_Matrix_Edges[vertex_add_2][vertex_add_1] = true;
} else {
System.out.println("There is already an edge between vertex "
+ vertex_add_1 + " and vertex " + vertex_add_2 + ".");
}
}
// This method removes an edge if the two int values in the 2-d boolean
// array are true, converts to false, otherwise it stays false if no edge
// present
public void removeEdge(int vertex_remove_1, int vertex_remove_2) {
if (adj_Matrix_Edges[vertex_remove_1][vertex_remove_2] == true) {
adj_Matrix_Edges[vertex_remove_1][vertex_remove_2] = false;
adj_Matrix_Edges[vertex_remove_1][vertex_remove_2] = false;
} else {
System.out.println("There is no edge between vertex "
+ vertex_remove_1 + " and vertex " + vertex_remove_2);
}
}
// setup a method which finds the shortest cycle in the graph.
// We want to set the method to return an int value, because the girth of the graph will represent an integer value
// which cannot be a negative value.
// if we find the diameter of a graph then the shortest cycle will be the girth, which will be the
// 2diam(G) + 1.
public int girth(){
// Set the
}
public int pathVertices(int vertex_1, int vertex_2){
if (vertex_1 != vertex_2){
}
}
public static void main(String[] args) {
// Make an arbritary graph with 5 vertices.
Graph graph = new Graph(10);
graph.addEdge(1, 2);
graph.removeEdge(0, 1);
graph.adjacent(1, 2);
graph.adjacent(2, 1);
graph.neighbors(1);
graph.neighbors(4);
graph.addVertex();
graph.removeVertex(0);
graph.averageDegree();
// for (int i = 0; i < adj_Matrix_Edges.length; i++) {
// for (int j = 0; j < adj_Matrix_Edges[i].length; j++) {
// System.out.println(adj_Matrix_Edges[i][j] + " ");
// }
// System.out.println("-----");
// }
}
}
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
}