2

I am supposed to write a program that would print out all possible N-bit sequences with K 1s, the rest (N - K) would be 0s. There should be also a counter that indicates how many sequences are there in the end.

In my case, N = 9 and K = 3, so the program should write out something like this:

111000000
110100000
...
101100000
101010000
...
000000111
Total: 84

So far, my code looks like this

// N bits and K 1s
import java.util.ArrayList;
import java.util.Arrays;

public class Sequence {

    public static void main(String[] args) {

        ArrayList<int[]> all = new ArrayList<>();
        int counter = 0;
        int first = 0;
        int second;
        int third;

        for (int i = first; i < 9; i++) {
            int[] sequence = {0, 0, 0, 0, 0, 0, 0, 0, 0};
            // the 1st "1"
            sequence[i] = 1;

            second = i + 1;

            for (int j = second; j < 9; j++) {
                int[] seq2 = sequence;
                // the 2nd "1"
                seq2[j] = 1;

                third = j + 1;
                for (int l = third; l < 9; l++) {
                    int[] seq3 = seq2;
                    // the 3rd "1"
                    seq3[l] = 1;
                    all.add(seq3); 
                    counter++;

                    seq3[l] = 0;
                    third++;
                }

                second++;
            }   

            first++;
        }

        for (int[] sequences : all) {
            System.out.println(Arrays.toString(sequences));
        }
        System.out.println("Total: " + counter);
    }   
}

but it doesn't seem to do it and I cannot figure out why. The code is in java and I used an ArrayList of arrays of 9 integers for the 9-bit sequences.

Niklas B.
  • 92,950
  • 18
  • 194
  • 224
bowl
  • 65
  • 5
  • 1
    If N fits in integer, see http://stackoverflow.com/q/27755687 (and Gospers Hack in general) – harold Feb 21 '15 at 14:02
  • for a generalized version, you could also use this algorithm: http://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order – גלעד ברקן Feb 21 '15 at 17:33

2 Answers2

1

You almost got it right.

Your problem is here :

int[] seq2 = sequence;

and here :

int[] seq3 = seq2;

These assignments mean that you have only one array that you keep changing and adding to the output list.

Change them to :

int[] seq2 = Arrays.copyOf(sequence, sequence.length);

and :

int[] seq3 = Arrays.copyOf(seq2, seq2.length);

Also remove this line (since a new array is created in each iteration, there's no need to clear the lth element) :

seq3[l] = 0;

You'll get this output :

[1, 1, 1, 0, 0, 0, 0, 0, 0]
[1, 1, 0, 1, 0, 0, 0, 0, 0]
[1, 1, 0, 0, 1, 0, 0, 0, 0]
[1, 1, 0, 0, 0, 1, 0, 0, 0]
[1, 1, 0, 0, 0, 0, 1, 0, 0]
[1, 1, 0, 0, 0, 0, 0, 1, 0]
[1, 1, 0, 0, 0, 0, 0, 0, 1]
[1, 0, 1, 1, 0, 0, 0, 0, 0]
[1, 0, 1, 0, 1, 0, 0, 0, 0]
[1, 0, 1, 0, 0, 1, 0, 0, 0]
[1, 0, 1, 0, 0, 0, 1, 0, 0]
[1, 0, 1, 0, 0, 0, 0, 1, 0]
[1, 0, 1, 0, 0, 0, 0, 0, 1]
[1, 0, 0, 1, 1, 0, 0, 0, 0]
[1, 0, 0, 1, 0, 1, 0, 0, 0]
[1, 0, 0, 1, 0, 0, 1, 0, 0]
[1, 0, 0, 1, 0, 0, 0, 1, 0]
[1, 0, 0, 1, 0, 0, 0, 0, 1]
[1, 0, 0, 0, 1, 1, 0, 0, 0]
[1, 0, 0, 0, 1, 0, 1, 0, 0]
[1, 0, 0, 0, 1, 0, 0, 1, 0]
[1, 0, 0, 0, 1, 0, 0, 0, 1]
[1, 0, 0, 0, 0, 1, 1, 0, 0]
[1, 0, 0, 0, 0, 1, 0, 1, 0]
[1, 0, 0, 0, 0, 1, 0, 0, 1]
[1, 0, 0, 0, 0, 0, 1, 1, 0]
[1, 0, 0, 0, 0, 0, 1, 0, 1]
[1, 0, 0, 0, 0, 0, 0, 1, 1]
[0, 1, 1, 1, 0, 0, 0, 0, 0]
[0, 1, 1, 0, 1, 0, 0, 0, 0]
[0, 1, 1, 0, 0, 1, 0, 0, 0]
[0, 1, 1, 0, 0, 0, 1, 0, 0]
[0, 1, 1, 0, 0, 0, 0, 1, 0]
[0, 1, 1, 0, 0, 0, 0, 0, 1]
[0, 1, 0, 1, 1, 0, 0, 0, 0]
[0, 1, 0, 1, 0, 1, 0, 0, 0]
[0, 1, 0, 1, 0, 0, 1, 0, 0]
[0, 1, 0, 1, 0, 0, 0, 1, 0]
[0, 1, 0, 1, 0, 0, 0, 0, 1]
[0, 1, 0, 0, 1, 1, 0, 0, 0]
[0, 1, 0, 0, 1, 0, 1, 0, 0]
[0, 1, 0, 0, 1, 0, 0, 1, 0]
[0, 1, 0, 0, 1, 0, 0, 0, 1]
[0, 1, 0, 0, 0, 1, 1, 0, 0]
[0, 1, 0, 0, 0, 1, 0, 1, 0]
[0, 1, 0, 0, 0, 1, 0, 0, 1]
[0, 1, 0, 0, 0, 0, 1, 1, 0]
[0, 1, 0, 0, 0, 0, 1, 0, 1]
[0, 1, 0, 0, 0, 0, 0, 1, 1]
[0, 0, 1, 1, 1, 0, 0, 0, 0]
[0, 0, 1, 1, 0, 1, 0, 0, 0]
[0, 0, 1, 1, 0, 0, 1, 0, 0]
[0, 0, 1, 1, 0, 0, 0, 1, 0]
[0, 0, 1, 1, 0, 0, 0, 0, 1]
[0, 0, 1, 0, 1, 1, 0, 0, 0]
[0, 0, 1, 0, 1, 0, 1, 0, 0]
[0, 0, 1, 0, 1, 0, 0, 1, 0]
[0, 0, 1, 0, 1, 0, 0, 0, 1]
[0, 0, 1, 0, 0, 1, 1, 0, 0]
[0, 0, 1, 0, 0, 1, 0, 1, 0]
[0, 0, 1, 0, 0, 1, 0, 0, 1]
[0, 0, 1, 0, 0, 0, 1, 1, 0]
[0, 0, 1, 0, 0, 0, 1, 0, 1]
[0, 0, 1, 0, 0, 0, 0, 1, 1]
[0, 0, 0, 1, 1, 1, 0, 0, 0]
[0, 0, 0, 1, 1, 0, 1, 0, 0]
[0, 0, 0, 1, 1, 0, 0, 1, 0]
[0, 0, 0, 1, 1, 0, 0, 0, 1]
[0, 0, 0, 1, 0, 1, 1, 0, 0]
[0, 0, 0, 1, 0, 1, 0, 1, 0]
[0, 0, 0, 1, 0, 1, 0, 0, 1]
[0, 0, 0, 1, 0, 0, 1, 1, 0]
[0, 0, 0, 1, 0, 0, 1, 0, 1]
[0, 0, 0, 1, 0, 0, 0, 1, 1]
[0, 0, 0, 0, 1, 1, 1, 0, 0]
[0, 0, 0, 0, 1, 1, 0, 1, 0]
[0, 0, 0, 0, 1, 1, 0, 0, 1]
[0, 0, 0, 0, 1, 0, 1, 1, 0]
[0, 0, 0, 0, 1, 0, 1, 0, 1]
[0, 0, 0, 0, 1, 0, 0, 1, 1]
[0, 0, 0, 0, 0, 1, 1, 1, 0]
[0, 0, 0, 0, 0, 1, 1, 0, 1]
[0, 0, 0, 0, 0, 1, 0, 1, 1]
[0, 0, 0, 0, 0, 0, 1, 1, 1]
Total: 84
Eran
  • 387,369
  • 54
  • 702
  • 768
1

An easy way would be to use a string-based approach. Here is a complete working solution:

int k = 3, n = 9, count = 0;
for (int i = 1 << n; i < 2 << n; i++) {
    if (Long.toString(i, 2).replace("0", "").length() == k + 1) {
        System.out.println(Long.toString(i, 2).substring(1));
        count++;
    }
}
System.out.println("Total: " +count);

I tested this code and it produces correct output. This iterates over a number range with an extra leading one to neatly sidestep the problem of truncated leading zeroes.

Note that this implementation will only handle n up to 62. For n greater than 62, change the loop type to BigInteger:

int k = 3, n = 9, count = 0;
BigInteger end = new BigInteger("2").pow(n + 1);
for (BigInteger i = new BigInteger("2").pow(n); i.compareTo(end) < 0; i = i.add(BigInteger.ONE)) {
    if (i.toString( 2).replace("0", "").length() == k + 1) {
        System.out.println(i.toString( 2).substring(1));
        count++;
    }
}
System.out.println(count);

This implementation works for arbitrarily large values of n.`


If you look at this code and think "oooh, performance!?", this code executes in about 20ms for the 1st version and 40ms for the 2nd on my very average hardware - fast enough.


btw, if you absolutely must have the order of output as you had it, change the loop to count down instead of up.

Bohemian
  • 412,405
  • 93
  • 575
  • 722