В общем, от идеи полного перебора пришлось отказаться - считает слишком долго. Пробовал и с рекурсией, и с представлением BigInteger по основанию N (штатным и самодельным) - не дождаться :)
Основную задачу решаю так. Допустим, N = 5. Тогда "максимальная" комбинация будет:
0, 1, 2, 3, 4
Все остальные будут получаться из неё выкидыванием элементов.
Сначала выкидываем по одному, потом по два и т.д. Т.е. мне надо перебрать не сами элементы, а их позиции. Я сделал что-то вроде двоичной маски, в которой "1" - оставляем элемент, "0" - выкидываем. Например:
0, 1, 2, 3, 4 - исходная комбинация
0, 1, 0, 1, 0 - маска
-, 1, -, 3, -> 1, 3 - результат
Осталось пройти по всем вариантам маски, а это просто инкремент целого - и все комбинации получены! Тоже небыстро, но гораздо быстрее полного перебора! Если кто-то знает как ещё можно ускорить - поделитесь :)
И да, собрать все комбинации в массив - тоже дохлая затея: память кончается очень быстро :) Приходится каждую комбинацию обрабатывать "на месте".
котт:
public class Part {
public static void main(String[] args) {
int numberOfThings = 41;
long top = ((long) Math.pow(2, numberOfThings + 1));
long bottom = ((long) Math.pow(2, numberOfThings)) + 1;
int[] things = new int[numberOfThings];
for (int i = 0; i < numberOfThings; i++) {
things[i] = i;
}
while (bottom != top) {
char[] mask = Long.toBinaryString(bottom++).toCharArray();
List<Integer> comb = new ArrayList<>();
for (int i = 0; i < numberOfThings; i++) {
if (mask[i + 1] == '1') comb.add(things[i]);
}
// Обработка комбинации
System.out.println(comb);
}
}
}