/*
***************************************************************************************
* Copyright (C) 2006 EsperTech, Inc. All rights reserved. *
* http://www.espertech.com/esper *
* http://www.espertech.com *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the GPL license *
* a copy of which has been included with this distribution in the license.txt file. *
***************************************************************************************
*/
package com.espertech.esper.collection;
import java.util.Enumeration;
import java.util.NoSuchElementException;
/**
* Provides an enumeration of each combination of numbers between zero and N-1
* with N must be at least 1,
* with each combination cannot have duplicates,
* with each combination at least one element,
* with the longest combination gets returned first and the least long combination of the highest N-1 value last.
* <p>
* For example, for N=3:
* </p>
* <pre>
* {0, 1, 2}
* {0, 1}
* {0, 2}
* {1, 2}
* {0}
* {1}
* {2}
* </pre>
*/
public class NumberAscCombinationEnumeration implements Enumeration<int[]> {
private final int n;
private int level;
private int[] current;
public NumberAscCombinationEnumeration(int n) {
if (n < 1) {
throw new IllegalArgumentException();
}
this.n = n;
this.level = n;
this.current = levelCurrent(n);
}
public boolean hasMoreElements() {
return current != null;
}
public int[] nextElement() {
if (!hasMoreElements()) {
throw new NoSuchElementException();
}
int[] item = copyCurrent(current);
computeNext();
return item;
}
private void computeNext() {
// determine whether there is a next for the outermost
int last = current.length - 1;
if (current[last] + 1 < n) {
current[last]++;
return;
}
// overflow
int currOverflowedLevel = last - 1;
while (currOverflowedLevel >= 0) {
int maxAtPosition = n - level + currOverflowedLevel;
if (current[currOverflowedLevel] < maxAtPosition) {
current[currOverflowedLevel]++;
for (int i = currOverflowedLevel + 1; i < current.length; i++) {
current[i] = current[i - 1] + 1;
}
return;
}
currOverflowedLevel--;
}
// bump level down
level--;
if (level == 0) {
current = null;
} else {
this.current = levelCurrent(level);
}
}
private static int[] levelCurrent(int level) {
int[] current = new int[level];
for (int i = 0; i < level; i++) {
current[i] = i;
}
return current;
}
private int[] copyCurrent(int[] current) {
int[] updated = new int[current.length];
System.arraycopy(current, 0, updated, 0, updated.length);
return updated;
}
}