Reputation: 2482
I'm trying to generate all possible combinations for pair of 1's within given bit width.
Let's say the bit width is 6, i.e. number 32. This is what I would like to generate:
000000
000011
000110
001100
001111
011000
011011
011110
110000
110011
110110
111100
111111
If I have variables:
var a = 1,
b = 2;
num = a | b;
and create a loop that I'll loop over width - 1
times, and where I shift both a << 1
and b << 1
, I'll get all combinations for one pair. After that, I'm pretty much stuck.
Could someone , please, provide some help.
Update: working example
Based on Barmar's mathematical approach, this is what I managed to implement
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));
Working example on JSFiddle
http://jsfiddle.net/zywc5/
Upvotes: 6
Views: 1651
Reputation: 5040
You can also do this with bit twiddling. If the lowest two bits are zero, we need to set them, which is equivalent to adding 3. Otherwise, we need to replace the lowest block of ones by its top bit and a 1-bit to the left of it. This can be done as follows, where x
is the current combination:
x3 = x + 3;
return (((x ^ x3) - 2) >> 2) + x3;
Upvotes: 0
Reputation: 288290
See 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 />'));
Or maybe you will prefer http://jsfiddle.net/SBH6R/1/. It's simpler, but then you will have to sort()
the array:
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 />'));
See http://jsperf.com/generate-all-combinations-for-pair-of-bits-set-to-1 if you want to compare the performance. It seems that the fastest code is the first one on Chrome but the second one on Firefox.
Upvotes: 0
Reputation: 176675
Maybe start counting normally in binary and replace all 1's with 11's like this:
n = 5
n = n.toString(2) //= "101"
n = n.replace(/1/g, "11") //= "11011"
n = parseInt(n, 2) //= 27
So you'll get:
0 -> 0
1 -> 11
10 -> 110
11 -> 1111
100 -> 1100
101 -> 11011
110 -> 11110
111 -> 111111
And so on. You'll have to count up to 31 or so on the left side, and reject ones longer than 6 bits on the right side.
Upvotes: 0
Reputation: 781255
The numbers with exactly one pair of 1's are the sequence 3, 6, 12, 24, 48, ...; they start with 3 and just double each time.
The numbers with two pairs of 1's are 12+3, 24+3, 24+6, 48+3, 48+6, 48+12, ...; these are the above sequence starting at 12 + the original sequence up to n/4.
The numbers with three pairs of 1's are 48+12+3, 96+12+3, 96+24+3, 96+24+6, ...
The relationship between each of these suggests a recursive algorithm making use of the original doubling sequence. I don't have time right now to write it, but I think this should get you going.
Upvotes: 3
Reputation: 962
if the bit width isn't that big then you'll be way better off creating bit representations for all numbers from 0 to 31 in a loop and simply ignore the ones that have an odd number of "ones" in the bit representation.
Upvotes: 0