Search for all length combinations with specific bits

This is such an obscure problem that I suspect that I will have to do it at a different level in my code ... but I hope the hive mind, which is a stack overflow, can help ...

I have a long one, which, if expressed as a binary string, will have exactly five bits. For instance,

long l = 341; // as a bit string, "101010101"

I am looking for an array containing all ten possible lengths that set exactly three of these bits. To continue this example,

long[] results = {
  101010000,
  101000100,
  101000001,
  100010100,
  100010001,
  100000101,
    1010100,
    1010001,
    1000101,
      10101
}

The corresponding method signature will look here:

public long[] toThreeBitCombinations(long l) {
    // what goes here?
}

(The problem area is poker, listing all the possible card combinations in Omaha Poker's hand. Yes, there are other ways to get close to this, but I am testing this approach, since dealing with bits is much faster than most other alternatives.)

+2
2

, . . Gosper Hack , , .

static long next(long v, long m)
{
    long t = v | (v - 1 & m);
    long t1 = (((t | ~m) + 1) & m);
    int c = Long.numberOfTrailingZeros(v) + 2; // *
    long w = t1 | (((~t & t1) - 1 & m) >>> c);
    return w;
}

, 2 , , - 2 1.

, x = next(x, 0x155) ( x = 0x15, ), , .

+2

. 1 , . k . , , "popcount" ( 1-):

unsigned next_combination(unsigned comb, unsigned set) {
    unsigned h = (-comb & (comb ^ set)) - 1;
    unsigned l = set;
    for (int i = 0; i < popcount(h & comb) - 1; ++i)
        l &= l - 1;
    comb = (set & h) ^ l;
    return comb;
}

: , popcount wiki : . :

unsigned next_combination(unsigned comb, unsigned set) {
    unsigned tmp = comb - 1;
    unsigned rip = set & ((tmp | comb) - set);
    for (comb = (tmp ^ rip) & comb; comb; rip ^= tmp, set ^= tmp) {
        tmp = set & -set;
        comb &= comb - 1;
    }
    return rip;
}

, , , - popcount.

+2

All Articles