Search code examples
c++stringc++11binarybitset

Why is this bitset collection algorithm not working?


Here's my goal:

  1. Create all possible bit strings of length N.

  2. Once I've created a possible string, I want to take B bits at time, covert them to a index, and use that index to fetch a character from the following string:

    define ALPHABET "abcdefghijklmnopqrstuvwxyz012345"
    
  3. I want to add each character to a string, then print the string once all bits have been parsed.

  4. Repeat until all possible bit strings are processed.

Here's my solution:

for (unsigned int i = 0; i < pow(2, N); i++) {
    // Create bit set.
    std::bitset <N> bits(i);
    // String to hold characters.
    std::string key_val;
    // To hold B bits per time.
    std::bitset <B> temp;
    for (unsigned int j = 0; j < bits.size(); j++) {
        // Add to bitset.
        temp[j % B] = bits[j];
        if (j % B == 0) {
            key_val += ALPHABET[temp.to_ulong()];
        }
    }
    std::cout << key_val << std::endl;
    key_val.clear();
}

Here's the problem:

The output makes no sense. I can see the program creates really weird sequences, that aren't what I need.

Ideally, the output should be (what I'd like) :

aaaaa
aaaab
aaaac
.
.
.

And here's the output what I'm getting:

aaaaa
baaaa
acaaa
bcaaa
aeaaa
beaaa
agaaa
bgaaa
aiaaa
.
.
.

Solution

  • The "append character" condition triggers immediately (j == 0), this is probably not what you want. You'll also need to take care about the end if bits size is not a multiple of B

    for (unsigned int j = 0; j < bits.size(); j++) {
        // Add to bitset.
        temp[j % B] = bits[j];
        if (j % B == B - 1 || j == bits.size() - 1) {
            key_val += ALPHABET[temp.to_ulong()];
        }
    }
    

    Edit: Instead of looping over all bits individually, you can probably do something like this:

    for (int j = 0; j < bits.size(); j += B) {
      key_val += ALPHABET[bits.to_ulong() % B];
      bits >>= B;
    }
    

    P.S.: If the bits fit into the loop variable, you don't need a bitset at all.

    for (unsigned int i = 0; i < (1 << N); i++) {
      std::string key_val;
      for (unsigned int j = 0; j < bits.size(); j += B) {
        key_val += ALPHABET[(i >> j) % B];
      }
      std::cout << key_val << std::endl;
    }
    

    P.P.S. You may want / need to count down in the inner loop instead if you want the digits reversed