I have the two arrays:
String[] operators = {"+", "-", "*"};
int[] numbers = {48, 24, 12, 6};
And I want to get all possible combination in a String format like this:
48+24+12+6
48+24+12-6
48+24+12*6
48+24-12+6
48+24-12-6
48+24-12*6
..........
48*24*12*6
This what I have tried:
for (int i = 0; i < operators.length; i++) {
System.out.println(numbers[0] + operators[i] + numbers[1] +
operators[i] + numbers[2] + operators[i] + numbers[3]);
}
But it only prints:
48+24+12+6
48-24-12-6
48*24*12*6
How to solve this?
This is not a duplicate because I don't want to get every two pairs of data, I want to get every combination in 4 pairs. The duplicate is different.
const arr1 = ["A","B","C"]; const arr2 = ["1","2","3"]; We are required to write a JavaScript function that takes in two such arrays of literals. The function should then combine each element of the first array with each element of the second array and push them into a new array.
To calculate combinations, we will use the formula nCr = n! / r! * (n - r)!, where n represents the total number of items, and r represents the number of items being chosen at a time. To calculate a combination, you will need to calculate a factorial.
You take first element of an array (k=0) and exchange it with any element (i) of the array. Then you recursively apply permutation on array starting with second element. This way you get all permutations starting with i-th element.
Use Recurrence to Generate All Possible Combinations in Java First, we create an empty array that will store the outputs. The idea is to fix elements one by one and then use recurrence. Finally, when the number of elements in the initial array becomes equal to the size of combinations, then we print the initial array.
Use a triple loop:
for (int i=0; i < operators.length; ++i) {
for (int j=0; j < operators.length; ++j) {
for (int k=0; k < operators.length; ++k) {
System.out.println(numbers[0] + operators[i] + numbers[1] + operators[j] +
numbers[2] + operators[k] + numbers[3]);
}
}
}
You essentially want to take the cross product of the operators vector (if it were a vector). In Java, this translates to a triply-nested set of loops.
While @TimBiegeleisen solution would work like a charm, its complexity might be an issue. The better approach would be a code like this:
static void combinationUtil(
int[] arr, int n, int r, int index, int[] data, int i) {
// Current combination is ready to be printed, print it
if (index == r) {
for (int j = 0; j < r; j++)
System.out.print(data[j] + " ");
System.out.println("");
return;
}
// When no more elements are there to put in data[]
if (i >= n)
return;
// current is included, put next at next location
data[index] = arr[i];
combinationUtil(arr, n, r, index + 1, data, i + 1);
// current is excluded, replace it with next (Note that
// i+1 is passed, but index is not changed)
combinationUtil(arr, n, r, index, data, i + 1);
}
// The main function that prints all combinations of size r
// in arr[] of size n. This function mainly uses combinationUtil()
static void printCombination(int arr[], int n, int r) {
// A temporary array to store all combination one by one
int data[] = new int[r];
// Print all combination using temprary array 'data[]'
combinationUtil(arr, n, r, 0, data, 0);
}
Source: GeeksForGeeks and my IDE :)
This sounds like a textbook case for a recursive solution:
public static void combineAndPrint(String[] pieces, String[] operators) {
if (pieces.length < 1) {
// no pieces? do nothing!
} else if (pieces.length == 1) {
// just one piece? no need to join anything, just print it!
System.out.println(pieces[0]);
} else {
// make a new array that's one piece shorter
String[] newPieces = new String[pieces.length - 1];
// copy all but the first two pieces into it
for (int i = 2; i < pieces.length; i++) {
newPieces[i - 1] = pieces[i];
}
// combine the first two pieces and recurse
for (int i = 0; i < operators.length; i++) {
newPieces[0] = pieces[0] + operators[i] + pieces[1];
combineAndPrint(newPieces, operators);
}
}
}
public static void main(String[] args) {
String[] operators = {"+", "-", "*"};
String[] numbers = {"48", "24", "12", "6"};
combineAndPrint(numbers, operators);
}
Try it online!
BTW, to generalize this method so that you can do more things with the generated expressions than just printing them, I would recommend making it accept an extra Consumer<String>
parameter. That is, you could rewrite the method declaration as:
public static void combine(String[] pieces, String[] operators, Consumer<String> consumer) {
and replace the System.out.println(pieces[0])
with consumer.accept(pieces[0])
and the recursive call to combineAndPrint(newPieces, operators)
with combine(newPieces, operators, consumer)
. Then just call it from your main method e.g. as:
combine(numbers, operators, s -> System.out.println(s));
Try it online!
(Of course, doing it in this more flexible way requires a somewhat modern Java version — Java 8 or later, to be specific — whereas the first example I showed above should work on even ancient versions all the way down to Java 1.0. Maybe in some future version of Java we'll get proper support for coroutines and generators, like Python and Kotlin and even modern JS already have, and then we won't even need to pass the consumer around any more.)
As already pointed out by findusl in his answer, the problem here is, strictly speaking, not to find any sort of "combination of two arrays". Instead, you basically just want to find all possible combinations of the available operators.
(The fact that you later want to "interveave" them with operands is rather unrelated to the core of the question)
So here is another option for solving this: You can create an iterable over all combinations of a certain number of elements from a certain set (in your case: the operators) and then simply combine the results with the other set (in your case: the operands).
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
public class OperatorsTest {
public static void main(String[] args) {
String[] operators = {"+", "-", "*"};
int[] numbers = {48, 24, 12, 6};
CombinationIterable<String> iterable =
new CombinationIterable<String>(3, Arrays.asList(operators));
for (List<String> element : iterable) {
System.out.println(interveave(element, numbers));
}
}
private static String interveave(List<String> operators, int numbers[]) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < operators.size(); i++) {
sb.append(numbers[i]);
sb.append(operators.get(i));
}
sb.append(numbers[numbers.length - 1]);
return sb.toString();
}
}
class CombinationIterable<T> implements Iterable<List<T>> {
private final List<T> input;
private final int sampleSize;
private final int numElements;
public CombinationIterable(int sampleSize, List<T> input) {
this.sampleSize = sampleSize;
this.input = input;
numElements = (int) Math.pow(input.size(), sampleSize);
}
@Override
public Iterator<List<T>> iterator() {
return new Iterator<List<T>>() {
private int current = 0;
private final int chosen[] = new int[sampleSize];
@Override
public boolean hasNext() {
return current < numElements;
}
@Override
public List<T> next() {
if (!hasNext()) {
throw new NoSuchElementException("No more elements");
}
List<T> result = new ArrayList<T>(sampleSize);
for (int i = 0; i < sampleSize; i++) {
result.add(input.get(chosen[i]));
}
increase();
current++;
return result;
}
private void increase() {
int index = chosen.length - 1;
while (index >= 0) {
if (chosen[index] < input.size() - 1) {
chosen[index]++;
return;
}
chosen[index] = 0;
index--;
}
}
};
}
}
The task resembles that of finding a set of operations that can be done with a certain number of operands and operators, and thus, this Q/A may be related. But whether or not things like associativity or commutativity should be considered here was not mentioned in the question.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With