I have 20 different variable-length arrays, each holding a unique value, and I need to calculate every possible combination of these:
#define LENGTH_COUNT 6
#define WIDTH_COUNT 4
etc, for all 20 arrays:
int length[LENGTH_COUNT];
int width[WIDTH_COUNT];
int height[HEIGHT_COUNT];
int weight[WEIGHT_COUNT];
int growth[GROWTH_COUNT];
int decay[DECAY_COUNT];
int sound[SOUND_COUNT];
int texture[TEXTURE_COUNT];
int moisture[MOISTURE_COUNT];
int volume[VOLUME_COUNT];
int speed[SPEED_COUNT];
int color[COLOR_COUNT];
int purpose[PURPOSE_COUNT];
int delay[DELAY_COUNT];
int vibrancy[VIBRANCY_COUNT];
int brix[BRIX_COUNT];
int ripeness[RIPENESS_COUNT];
int mold[MOLD_COUNT];
int temp[TEMP_COUNT];
int language[LANGUAGE_COUNT];
void iterate(void)
{
for (int i = 0; i < LENGTH_COUNT; ++i)
for (int j = 0; j < WIDTH_COUNT; ++j)
for (int k = 0; k < HEIGHT_COUNT; ++k)
// etc for all 20 arrays
int value = doSomething(length[i], width[j], height[k].....);
}
There must be a less brain-dead way to do this. One idea I had is:
#define ARRAY_COUNT 20
#define MAX_LENGTH 12 // the longest array length is 12
int arrays[ARRAY_COUNT][MAX_LENGTH];
But if I were to do this, I don't know how to do the equivalent to what I am doing in the iterate function. Any ideas?
You could create (untested/uncompiled):
int *arrays[] = { first_arr, second_arr, ... }; // array of arrays
int maxes[] = { FIRST_ARR_MAX, SECOND_ARR_MAX, ... }; // array of array lengths
int counter[NUM_ARRAYS] = {0}; // initialize a counter to 0 for each of the arrays.
int state = 0;
while (true) {
doSomething(first_arr[counter[0]], second_arr[counter[1]], ... );
// Update the counter.
int i;
for (i = NUM_ARRAYS - 1; i >= 0; i--) {
counter[i]++;
// If incrementing the current counter didn't overflow, we're good, so we break.
if (counter[i] < maxes[i]) {
break;
} else {
// Overflow by setting the counter to 0.
counter[i] = 0;
// Now we will fall through and move to the next counter.
}
}
// Check for all 0's intelligently. State == 0 means counter[0] is 0.
// If it's no longer 0, move to state 1.
if (state == 0 && counter[0] > 0) {
state = 1;
} else (state == 1 && counter[0] == 0) {
break;
}
}
This seems to work, although I haven't tested it thoroughly. It's in python but hopefully it's clear how to use in your case. The important point is that it divides the problem up into easier parts to avoid the deeply-nested for loops.
test_arrays = [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
def combine(partial, next_array):
new_array = []
for p in partial:
if not isinstance(p, list):
p = [p]
for v in next_array:
new_array.append(p + [v])
return new_array
def combinations(arrays):
base = arrays[0]
for i in xrange(1, len(arrays)):
base = combine(base, arrays[i])
return base
print combinations(test_arrays)
But as others have said above, you almost certainly don't want to do this at all. A better approach would be to select random combinations and test/evaluate those. Various algorithms can be used to improve on naive random sampling, but which is appropriate depends on your application.
.append
method particularly - huon 2012-04-05 02:33