生成设置为1的位对的所有组合?

时间:2012-09-05 20:39:50

标签: javascript bit-manipulation combinations bitwise-operators

我正在尝试为给定位宽内的1对生成所有可能的组合。

假设比特宽度为6,即数字32.这就是我想要生成的内容:

000000
000011
000110
001100
001111
011000
011011
011110
110000
110011
110110
111100
111111

如果我有变量:

var a = 1,
    b = 2;
    num = a | b;

并创建一个我将循环width - 1次的循环,并且在我移动a << 1b << 1的位置,我将获得一对的所有组合。在那之后,我几乎陷入困境。

请有人提供一些帮助。

更新:工作示例
基于Barmar的数学方法,这是我设法实现的目标

var arr = [],
    arrBits = [];

function getCombs(pairs, startIdx) {
    var i, j, val = 0, tmpVal, idx;

    if (startIdx + 2 < pairs) {
        startIdx = arr.length - 1;
        pairs -= 1;
    }

    if (pairs < 2) {
        return;
    }

    for (i = 0; i < pairs-1; i++) {
        idx = startIdx - (i * 2);
        val += arr[idx];

    }

    for (j = 0; j < idx - 1; j++) {
        arrBits.push((val + arr[j]).toString(2));
    }

    getCombs(pairs, startIdx-1);
}

(function initArr(bits) {
    var i, val, pairs, startIdx;

    for (i = 1; i < bits; i++) {
        val = i == 1 ? 3 : val * 2;
        arr.push(val);
        arrBits.push(val.toString(2));
    }

    pairs = Math.floor(bits / 2);
    startIdx = arr.length - 1;

    getCombs(pairs, startIdx);
    console.log(arrBits);

}(9));

关于JSFiddle的工作示例
http://jsfiddle.net/zywc5/

5 个答案:

答案 0 :(得分:3)

只有一对1的数字是序列3,6,12,24,48 ......;他们从3开始,每次只加倍。

两对1的数字是12 + 3,24 + 3,24 + 6,48 + 3,48 + 6,48 + 12,...;这些是从12 +原始序列开始直到n / 4的上述序列。

三对1的数字是48 + 12 + 3,96 + 12 + 3,96 + 24 + 3,96 + 24 + 6,......

这些中的每一个之间的关系表明利用原始倍增序列的递归算法。我现在没有时间写它,但我认为这应该让你去。

答案 1 :(得分:0)

如果位宽不是那么大,那么在循环中为0到31之间的所有数字创建位表示会更好,并且只是忽略位中具有奇数个“1”的位表示表示。

答案 2 :(得分:0)

也许以二进制方式正常开始计数并将11的全部1替换为:

n = 5
n = n.toString(2)          //= "101"
n = n.replace(/1/g, "11")  //= "11011"
n = parseInt(n, 2)         //= 27

所以你会得到:

0   -> 0
1   -> 11
10  -> 110
11  -> 1111
100 -> 1100
101 -> 11011
110 -> 11110
111 -> 111111

等等。您必须在左侧计数最多31个左右,并拒绝右侧超过6位的数据。

答案 3 :(得分:0)

请参阅http://jsfiddle.net/SBH6R/

var len=6,
    arr=[''];
for(var i=0;i<len;i++){
    for(var j=0;j<arr.length;j++){
        var k=j;
        if(getNum1(arr[j])%2===1){
            arr[j]+=1;
        }else{
            if(i<len-1){
                arr.splice(j+1,0,arr[j]+1);
                j++;
            }
            arr[k]+=0;
        }      
    }
}
function getNum1(str){
    var n=0;
    for(var i=str.length-1;i>=0;i--){
        if(str.substr(i,1)==='1'){n++;}
        else{break;}
    }
    return n;
}
document.write(arr.join('<br />'));

或者您可能更喜欢http://jsfiddle.net/SBH6R/1/。它更简单,但是你必须sort()数组:

var len=6,
    arr=[''];
for(var i=0;i<len;i++){
    for(var k=0,l=arr.length;k<l;k++){
        if(getNum1(arr[k])%2===1){
            arr[k]+=1;
        }else{
            if(i<len-1){
                arr.push(arr[k]+1);
            }
            arr[k]+=0;
        }     
    }
}
function getNum1(str){
    var n=0;
    for(var i=str.length-1;i>=0;i--){
        if(str.substr(i,1)==='1'){n++;}
        else{break;}
    }
    return n;
}
document.write(arr.sort().join('<br />'));

如果要比较效果,请参阅http://jsperf.com/generate-all-combinations-for-pair-of-bits-set-to-1。似乎最快的代码是Chrome上的第一个代码,但是Firefox上的第二个代码。

答案 4 :(得分:0)

你也可以通过比特琐事来做到这一点。如果最低的两位为零,我们需要设置它们,这相当于增加3.否则,我们需要用它的最高位和它左边的1位替换最低的1块。这可以按如下方式完成,其中x是当前组合:

x3 = x + 3;
return (((x ^ x3) - 2) >> 2) + x3;