The hard thing seems to be the permutations, especially when having repeated values in an array.
For that I order the permutations lexically with boolean nextPermution(double[] values)
.
An increasingly sorted array brings the lowest permutation: 235, followed by 253, 325, 352, 523, 532.
/**
* Find next higher permutation.
*/
static boolean nextPermution(double[] values) {
// Find the first position i from the right, that can made larger out of the right part.
// ... [4] < 7 > 5 > 3 > 2 > 0
// i
int i = values.length - 2;
while (i >= 0 && values[i] >= values[i + 1]) {
--i;
}
if (i < 0) {
return false;
}
// Take the next larger:
// ... [5] < 7 > 4 > 3 > 2 > 0
// \________/
// i j
double xi = values[i];
int j = values.length - 1;
while (j > i && xi >= values[j]) {
--j;
}
values[i] = values[j];
values[j] = xi;
// And for the right part the smallest permutation:
// By reversal of the order.
// ... [5] < 0 < 2 < 3 < 4 < 7
int nright = values.length - (i + 1);
for (int k = 0; k < nright / 2; ++k) {
double xk = values[i + 1 + k];
values[i + 1 + k] = values[values.length - 1 - k];
values[values.length - 1 - k] = xk;
}
return true;
}
Taking the negative or positive values can be done by counting upto 2³ for both arrays: 2³*2³.
static void processPairsNegating(double[] raw, double[] cal) {
double[] rawSigned = raw.clone();
double[] calSigned = cal.clone();
long rawM = 1L << raw.length;
long calM = 1L << cal.length;
LongStream.range(0L, rawM).forEach(rawI -> {
Arrays.setAll(rawSigned, i -> ((1L << i) & rawI) != 0 ? raw[i] : -raw[i]);
LongStream.range(0L, calM).forEach(calI -> {
Arrays.setAll(calSigned, i -> ((1L << i) & calI) != 0 ? cal[i] : -cal[i]);
processPair(rawSigned, calSigned);
});
});
//System.out.println(Arrays.toString(raw));
}
static int counter = 0;
static void processPair(double[] raw, double[] cal) {
//double[] result = raw.clone();
System.out.printf("%d. %s%n", counter++, Arrays.toString(raw));
}
Note that I start with using the absolute values, and sorting them.
Thus { -3,3 } will not give unnessary repeated combinations.
One could make an method initPermutation(doubl[]. values)
.
public static void main(String[] args) {
double[] rawValues = {169.58185f, 20.343851f, 1.4982328f};
//double[] rawValues = {1, 2, 3, 3};
double[] calValues = {110.131454f, 4.442127f, 7.5981708f};
Arrays.setAll(rawValues, i -> Math.abs(rawValues[i]));
Arrays.sort(rawValues);
Arrays.setAll(calValues, i -> Math.abs(calValues[i]));
Arrays.sort(calValues);
for (;;) {
processPairsNegating(rawValues, calValues);
if (!nextPermution(rawValues)) {
break;
}
}
}
The code above is not nicely packaged, but relatively simple.
I used double instead of float, because it hast more support.