Bit manipulation, permutate bits

六月ゝ 毕业季﹏ 提交于 2019-12-04 09:05:49

A bit more complicated, but done purely by bit manipulation. Your example:

#define WIDTH 4
#define BITS 2

void printbits(long pattern) {
  long bit;
  for (bit = 1L << WIDTH - 1; bit; bit >>= 1)
    putchar(pattern & bit ? 49 : 48);
  putchar('\n');
}

void movebits(pattern, bit) {
  long mask = 3L << bit;
  while (((pattern ^= mask) & mask) && (mask < 1L << WIDTH)) {
    mask <<= 1;
    printbits(pattern);
    if (bit)
      movebits(pattern, bit - 1);
  }
}

int main() {
  long pattern = (1L << BITS) - 1L, mask;
  printbits(pattern);
  movebits(pattern, BITS - 1);
}

Your real application:

#define WIDTH 40
#define BITS 10

and, as polygenelubricants says, be prepared to wait for bit :) Of course, you will replace printbits with something more useful to you...

(Edited for insufficient testing :/ Damn typos...)

polygenelubricants

You can use any standard implementation of a choose/combination algorithm. Basically you want to choose 10 bits, out of 40, that will be set to 1.

That said, 40 choose 10 is 847,660,528. And that number will be multiplied by however many possible "tail" bits that aren't in the top 40. Presumably the tail bits aren't subject to any rules, so if there are k bits, that would be another 2k factor.

This algorithm, even once you implement it, will be very slow. It may be a good idea to think of a better approach to solve whatever problem you have.

Related questions

You can simply use next_permutation. Here's a sample to reproduce your 2 out of 4 case (the order varies slightly):

#include <iostream>
#include <algorithm>
using namespace std;
int main () {
 int bits[] = {0,0,1,1};

 do {
  for (int i = 0; i < 4; ++i) cout << bits[i] << " ";
  cout << endl;
 } while ( next_permutation (bits,bits+4) );
 return 0;
}

There is a very non-obvious way to do this efficiently: Gosper's method of finding the next higher integer with the same number of 1 bits, from HAKMEM item 175.

lowest_1_bit = prev_combo & -prev_combo;
tmp = prev_combo + lowest_1_bit;
new_combo = (((prev_combo ^ tmp) >> 2) / lowest_1_bit) | tmp;
  • the first line finds the rightmost 1 bit;
  • the second turns the rightmost run of 1 bits to 0, and the 0 just to the left of the run to 1;
  • the third line replaces the 1 bits that were lost by the second line, at the bottom of the word.

Now (assuming you're using a 64-bit integer type) you can start with 1023 and just apply this repeatedly (until the result exceeds 1<<40).

It's easier if you rewrite this as a set of nested loops indicating bit positions:

0011 = 0 1
0101 = 0 2
1001 = 0 3
0110 = 1 2
1010 = 1 3
1100 = 2 3

That is to say, the position P1 of the first bit runs from 0 to 3-1, and the position of the second bit P2 runs repeatedly from P1+1 to 3. Turning this into a generic recursive function is left as an exercise.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!