function combinations( input ){
var number = parseInt( input, 2 );
var combinations = [];
var zeroes = (new Array(input.length)).join(0);
for(var i=1;i<=number;i++){
if((i&number) == i){ combinations.push( i ) }
}
return combinations.map( function(dec){
return (zeroes + dec.toString(2)).substr( -zeroes.length-1 );
});
}
http://jsfiddle.net/jkf7pfxn/3/
console.log( combinations("00001011") );
// ["00000001", "00000010", "00000011", "00001000", "00001001", "00001010", "00001011"]
The idea goes as follows: iterate all numbers from 1 to the input number. If current number AND input number return the current number then both have 1
bits in the same place.
On a smaller number, "0101"
(which is 5
) it works as follows:
1 & 5 == 1
, (0001 & 0101) push 1
to the matches.
2 & 5 == 0
, (0010 & 0101) no match.
3 & 5 == 1
, (0011 & 0101) no match.
4 & 5 == 4
, (0100 & 0101) push 4
to the matches.
5 & 5 == 5
, (0101 & 0101) push 5
to the matches.
So the combinations for 0101
are 1
(0001
), 2
(0010
), 4
(0100
) and 5
(0101
).
Then there's this little trick to pad numbers with zeroes:
var zeroes = (new Array(input.length)).join(0); // gives a long enough string of zeroes
then
// convert to base 2, add the zeroas at the beginning,
// then return the last n characters using negative value for substring
return (zeroes + dec.toString(2)).substr( -1 * zeroes.length);