0
votes

I am trying to implement an algorithm to calculate all combinations of an Array where one character is replaced by '*' without changing the order of the Arrays entries.

For example the following Array with two entries:

{"A", "B"}

Should reproduce this Output:

[A, B]
[*, B]
[A, *]
[*, *]

My current code is:

public class TestCombination {

   public static void combinations(List<String[]> values, String[] attr, String all, int iteration) {
      String[] val = new String[attr.length];
      for (int i = 0; i < attr.length; i++) {
         val[i] = attr[i];
      }
      if (iteration < attr.length) {
         val[iteration] = all;
      }

      values.add(val);
      iteration = iteration + 1;

      if (Math.pow(attr.length, 2) != iteration) {
         combinations(values, attr, all, iteration);
      }
   }

   public static void main() {
      String[] values = new String[] {"A", "B"};
      List<String[]> resultValues = new ArrayList<String[]>();
      combinations(resultValues, values, "*", 0);

      for (String[] res : resultValues) {
         System.out.println(Arrays.deepToString(res));
      }
   }

}

The Output i get is:

[*, B]
[A, *]
[A, B]
[A, B]

This is especially because of this not correct code:

if (iteration < attr.length) {
    val[iteration] = all;
}

I do not have any idea, how the next possible index can be calculated to replace the Array value at that index by '*'.

Can you give me please some hints on that?

3
Why is [B, *] not an option? - Oliver Charlesworth
How's [*, A] not changing the order of the array entries? - Sergey Kalinichenko
After your edit, [*, B] is twice. Is it right? - Shahid
@dasblinkenlight, shalid sorry that was a mistake.. i corrected it. - zennon
So, simplified problem would be generating binary strings of 00, 01, 10, 11, yes? - OneCricketeer

3 Answers

4
votes

One simple approach is to use a bit mask of length n. Iterate all n-digit binary numbers, and then for each of the n positions do the following:

  • If position i has one, output an asterisk *
  • If position i has zero, output the original value.

This will cover all combinations.

String[] a = new String[] {"A", "B", "C"};
for (int mask = 0 ; mask != 1<<a.length ; mask++) {
    for (int i = 0 ; i != a.length ; i++) {
        if ((mask & 1<<i) != 0) {
            System.out.print("* ");
        } else {
            System.out.print(a[i]+" ");
        }
    }
    System.out.println();
}

Demo.

0
votes

My solution is a modification of @dasblinkenlight solution where I'm using recursive function and not mask bit. My solution is in javascript.

var arr = ['A', 'B', 'C'],
  len = arr.length,
  pattern = function(startIndex, arr) {
    var newArr = [].concat(arr),
      i;
    newArr[startIndex] = '*';
    console.log(newArr.toString());
    for (i = startIndex + 1; i < len; i++) {
      pattern(i, newArr);
    }
  };
console.log(arr.toString())
for (i = 0; i < len; i++) {
  pattern(i, arr);
}
0
votes

You can use a recursive function to get the current string and one index and one time change the character at that index to * and another time call the function without changing the character at that index. Print the result when index reaches end of the string:

public class Main{
    public static void main(String args[]){
        f(new StringBuilder("ABC"),0);
    }

    public static void f(StringBuilder str, int index){
        if (index == str.length()){
            System.out.println(str);
            return;
        }
        f(str, index+1);
        char c = str.charAt(index);
        str.setCharAt(index, '*');
        f(str, index+1);
        str.setCharAt(index, c);
    }
}

output

ABC
AB*
A*C
A**
*BC
*B*
**C
***