I am wanting to create an array of bitmasks of X length and am looking for an efficient function.
For length 3 I would like it to generate:
000, 001, 010, 011, 100, 101, 110, 111
I am looking for a solution that uses bit math to do so - right now I am just using regular for loops as my bit operations is rudimentary.
Did you try the following:
function range(til) {
var x = 0, xs = [];
while (x < til) xs.push(x++);
return xs;
}
function generate(n) {
return range(Math.pow(2, n));
}
Now you can generate all the numbers from 0 to 7 as follows:
var xs = generate(3);
If you want it in string format then use the following function instead:
function replicate(n, x) {
var i = 0, xs = [];
while(i++ < n) xs.push(x);
return xs;
}
function generateBitmasks(n) {
var padding = replicate(n, '0').join('');
return range(Math.pow(2, n)).map(function (x) {
return (padding + x.toString(2)).slice(-n);
});
}
Now you can get the list of bitmasks for 0 to 7 as follows:
var bitmasks = generateBitmasks(3);
I hope that helped.
It's just this:
var length = 3,
limit = 1 << length; //Shift length bytes to the left
for(mask=0; mask < limit; mask++){
console.log(mask); //This will log in decimal, but the bin value is correct
}
They're basically the binary representations of all numbers from 0 to 2^n-1
Hope this helps. Cheers
This is the same idea from Aadit M Shah, merged with Edgar Villegas Alvardo's.
// Pad with left 0's
function pad(val, width) {
val = val + '';
return val.length >= width ? val : new Array(width - n.length + 1).join('0') + val;
}
// Get a list of decimal numbers representing all the bitmasks up to the given length
function getBitmapDecimalList(length) {
var bitmaskMax = 1 << length;
var bitmaskList = [];
for (var i = 0; i < bitmaskMax; i++) {
bitmaskList.push(i);
}
return bitmaskList;
}
// Get a list of strings representing all the bitmasks up to the given length
function getBitmapBinaryList(length) {
var bitmaskMax = 1 << length; // Shift operator, equivalent to Math.pow(2,length)
var bitmaskList = [];
for (var i = 0; i < bitmaskMax; i++) {
// the `.toString(2)` is what transforms the number into a binary string
var bitmaskBinary = Number(i).toString(2);
var paddedBitmask = pad(bitmaskBinary, length);
bitmaskList.push(paddedBitmask);
}
return bitmaskList;
}
Related
Question: Write a function that takes an unsigned integer and returns the number of '1' bits it has (also known as the Hamming weight).
Example 1:
Input: n = 00000000000000000000000000001011
Output: 3
Explanation: The input binary string 00000000000000000000000000001011 has a total of three '1' bits.
My Code
var hammingWeight = function(n) {
for (i=0; i<32; i++) {
var mask = 1;
var count = 0;
if ((mask & n) != 0 ) {
mask <<= 1;
count++;
}
return count;
}
};
Test Case:
00000000000000000000000000001011
00000000000000000000000010000000
11111111111111111111111111111101
Expected Output:
3
1
31
Output:
1
0
1
What did I do wrong with my code?
You have a few issues here:
You are redefining count and mask inside of your for loop.
You are returning after the first iteration of the loop, instead of waiting for the whole thing to count up.
You only shift mask if a bit is 1.
Here is a corrected function:
var hammingWeight = function(n) {
var count = 0;
var mask = 1;
for (i=0; i<32; i++) {
if ((mask & n) != 0 ) {
count++;
}
mask <<= 1;
}
return count;
};
A shorter way to write this could be:
const hammingWeight = value => [...value].filter(f => f == 1).length;
Explanation:
[...value] this will create an array of 0's and 1's based on your string
.filter(f => f == 1) will filter the array, keeping only the 1 values
.length gives you the length of the filtered array
I need to convert a 256-bit ArrayBuffer into 24 11-bit values and then back again.
Is there a simple code snippet to handle this type of operation.
I have this version, to convert it to 24 11 bit values.
var newBuffer = new Uint8Array(data);
var result = [];
for (var i =0, l = 24;i<l;i++){
var index = parseInt((i*11.0)/8.0);
var subBuffer;
if (i==23){
var proxyBuffer = new Uint8Array(2);
proxyBuffer.set(newBuffer.slice(index,index+1));
subBuffer = proxyBuffer;
}else{
subBuffer = newBuffer.slice(index,index+2);
}
var value = new Uint16Array(subBuffer.buffer);
value = value >> (i*3)%8;
value = value % 2048;
result.push(value);
}
console.log(result);
Using bit operations can simplify the conversion process - using parseInt and decimal arithmetic is not an easy approach.
The concept code below uses plain arrays of octet and 11 bit values. While Uint8Array and Uint16Array types may be a better choice, creating typed arrays and/or converting an arrayBuffer to and from a suitable array type is not included.
function ui8To11( buffer8) {
var buffer11 = [];
var acc = 0;
var accBits = 0;
function add( octet) {
acc = (octet << accBits) | acc;
accBits += 8;
if( accBits >=11) {
buffer11.push( acc & 0x7ff);
acc >>= 11;
accBits -= 11;
}
}
function flush() {
if( accBits) {
buffer11.push( acc);
}
}
buffer8.forEach( add);
flush();
return buffer11;
}
function ui11To8( buffer11) {
var buffer8 = [];
var acc = 0;
var accBits = 0;
function add( ui11) {
acc = (ui11 << accBits) | acc;
accBits += 11;
while( accBits >= 8) {
buffer8.push( acc & 0xff);
acc >>= 8;
accBits -= 8;
}
}
function flush() {
if( accBits) {
buffer8.push( acc);
}
}
buffer11.forEach( add);
flush();
return buffer8;
}
var buffer8 = [1,2,3]; // 8 bit values, least significant octet at index 0
console.log("octets: ", buffer8);
var buffer11 = ui8To11( buffer8);
console.log("undectets: ", buffer11);
var reconstructed = ui11To8( buffer11)
console.log("convertedBack", reconstructed);
There is an assumption here that the input array is little-endian, as in each entry in the input array is more significant than the previous entry.
Conversion between 8 and 11 bit values and back again follows a similar pattern, but pushing bits from the accumulator to the output array requires a loop when converting from a higher number of bits to a lower.
The example takes 3 x 8 bit values (24 bits in total) and produces 3 x 11 bit values (33 bits in total). Converting back 33 bits to uint8 integers produces 5 x 8 bit values ( 40 bits). You may need to add code to limit the number of integers pushed into output arrays within conversion routines or truncate output arrays returned as required.
There is a library called Uint1Array which makes everything much easier.
var arr = new Uint1Array(buffer);
for (let i=0, l=arr.length; i<l; i+=11){
var zero = new Uint1Array(16);
for (let index =0, length = 11; index<length;index++){
zero[index]=arr[i+index];
}
let bit16 = new Uint16Array(zero.buffer)[0];
outPut.push(bit16);
}
console.log(outPut);
var bit256 = new Uint1Array(256);
for (let i=0, l=outPut.length;i<l;i++){
var hold = new Uint16Array(1);
hold[0]=outPut[i];
let bit16 = new Uint1Array(hold.buffer);
let bit11 = bit16.slice(0,11);
for (let i2=0, l2=11;i2<l2;i2++){
bit256[(i*11)+i2]=bit11[i2];
}
}
Wondering how to quickly generate lots of unique, small random numbers. When I implemented it like this it slows down exponentially it seems like, to the point where it never finishes, or will take hours to complete. Probably because it creates tons of duplicates toward the end.
var intsmap = {}
var intsarray = []
var i = 100000
while (i--) {
var int = randominteger(6)
if (intsmap[int]) i++
else {
intsmap[int] = true
intsarray.push(int)
}
}
// return intsarray
function randominteger(exp) {
var string = rand(exp)
return pad(string, exp)
}
function pad(num, size) {
var s = rand(9) + num
return s.substr(s.length - size)
}
function rand(exp) {
var integer = Math.random() * Math.pow(10, exp) << 0
var string = toString(integer, '0123456789')
return string
}
function toString(value, code) {
var digit
var radix = code.length
var result = ''
do {
digit = value % radix
result = code[digit] + result
value = Math.floor(value / radix)
} while (value)
return result
}
Wondering how to accomplish that but the code works within a few seconds if possible.
Update
I would like for the set of numbers to be distributed evenly over an arbitrary range (in this example 1000000 strings, not necessarily from 0-1000000, eg maybe 5050000 is in there).
I would like for the numbers to not necessarily be valid numbers, just a string of integers. So for example they can include 01010101 as a valid string, even though that's not a valid number.
You can use an object as a look up and only insert unique random number
var intsmap = {};
var i = 100000;
while (i--) {
var int = Math.random() * Math.pow(10, 6) << 0;
if(intsmap[int])
continue;
else
intsmap[int] = true;
}
console.log(Object.keys(intsmap));
You can use also use Durstenfeld shuffle after generating number in the given range.
var arr = Array.from({length:1000000}, (_,i) => (i+1));
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
shuffleArray(arr);
console.log(arr);
Just try to shuffle the array of numbers 1 to maxNum
First create an array
var maxNum = 1000000;
var arr = Array(maxNum).fill().map((e,i)=>i+1);
Now shuffle the array
arr.sort(function() {
return .5 - Math.random();
});
Now you have the array of unique random numbers
Demo
var startTime = new Date().getTime();
var maxNum = 1000000;
var arr = Array(maxNum).fill().map((e, i) => i + 1);
arr.sort(function() {
return .5 - Math.random();
});
var endTime = new Date().getTime();
console.log( "Time taken to get " + maxNum + " size random unique number is " + ( endTime - startTime ) + " ms");
I can propose this approach:
generate a random number
cast it to a string (0.1234567812345678)
and extract 6 substrings of length of 10
Code:
var res = {},
s = "";
for (let i=0; i<1000000; ++i) {
s = Math.random().toString();
for (let j=0; j<6; ++j) {
res[s.substring(2+j, 12+j)] = true; // extract 10 digits
}
}
After 1,000,000 iterations, you have computed 6,000,000 numbers with very little collisions (1,800 in average). So you have your 1,000,000 numbers and more in few seconds.
If you need unique big array try to think in other way. Just create range 0 ... 100000 and shuffle it and apply you function that you need for this array.
var acc = 0;
const result = [];
for(var i = 0; i < 100000; i++)
result.push(acc += Math.floor(Math.random() * 10) + 1);
I think the most expensive operation is the hashtable lookup/insertion, so simply do it without it.
One place where you might loose performances is in the Math.random call.
It's a quite expensive call, and you are calling it a huge number of times to generate your strings.
One solution to leverage it is to grab the whole string from a single result of Math.random().
var intsmap = {}
var intsarray = []
var i = 100000
while (i--) {
var int = randominteger(6)
if (intsmap[int]) {
i++
} else {
intsmap[int] = true
intsarray.push(int)
}
}
console.log(intsarray);
// It takes the whole string from a single call to 'random'.
// The maximum length is 16.
function randominteger(length){
return (Math.random() + '').substr(2,length);
}
How do I add 1 to this string in JavaScript?
var message = "12345612345678901234567890";
I want the output like this:
"12345612345678901234567891"
I tried this:
var message = "12345612345678901234567890";
message = parseInt(message);
var result = message + 1;
But parseInt returned a value in scientific notation like 1.234567896453e+25.
Try the big integer library BigInteger.js to add large numbers.
var message = "12345612345678901234567890";
var messageAsNumber = bigInt(message);
var messagePlusOne = messageAsNumber.add('1');
console.log(messagePlusOne.toString());
<script src="https://peterolson.github.io/BigInteger.js/BigInteger.min.js"></script>
There is no need to use libraries (2022), you can just use JS BigInt object
let message = "12345612345678901234567890";
let messageBigInt = BigInt(message);
console.log(messageBigInt + BigInt(1)); // 12345612345678901234567891n
You can create an array from the string in .lengths of 3 beginning from the end of the string.
Use a pattern which checks if adding 1 would result in the index of the array as a number would sum to 1000, if true, increment previous array index by 1 and fill the current array index with "000".
The pattern below only checks and adjusts last two elements of array; the same pattern can be extended to check each index of array, to properly adjust one or more of the indexes to "000" and increment the previous index by 1.
let message1 = "12345612345678901234567890";
let message2 = "12345612345678901234567999";
let message3 = "12345612345678901234999999";
function addNumberToString(str, numToAdd, digits = []) {
const [N, len, max] = [3, str.length, 1000];
for (let i = -N, l = len; digits.length < len / N; i -= N, l -= N) {
digits.unshift(str.slice(i, l));
}
function add(m) {
if (+digits[digits.length - m] + numToAdd < max) {
let n = +digits[digits.length - m];
digits[digits.length - m] = String(Number(n + numToAdd));
} else {
const M = m + 1;
if (+digits[digits.length - M] + numToAdd < max) {
let n = +digits[digits.length - M];
digits[digits.length - M] = String(Number(n + numToAdd));
digits[digits.length - (M - 1)] = "0".repeat(N);
} else {
if (digits[digits.length - (m + 1)]) {
digits[digits.length - (M - 1)] = "0".repeat(N);
add(m + 1);
}
}
}
return digits.join("")
}
return add(1);
}
console.log(
addNumberToString(message1, 1)
, addNumberToString(message2, 1)
, addNumberToString(message3, 1)
);
What is the most efficient way to write a javascript loop to calculate the number of occurrences of 7's (as an example number) that will be encountered in counting from 1 to 100?
Example:
function numberOccurences(targetNumber, minNumber, maxNumber) {
var count = 0;
for (i = minNumber; i < maxNumber; i++) {
count = count + (i.toString().split(targetNumber).length - 1);
}
return count;
}
var result = numberOccurences(7,1,100);
This will do it without looking at the actual numbers. Sorry, no loop, but you did ask for effeciency. If you really want to use a loop, make the recursion an iteration.
function digitOccurences(digit, min, max, base) {
if (typeof base != "number") base = 10;
return digitOccurencesPlus(digit, max, base, 1, 0) - digitOccurencesPlus(digit, min, base, 1, 0);
function digitOccurencesPlus(digit, N, base, pow, rest) {
if (N == 0) return 0;
var lastDigit = N%base,
prevDigits = (N-lastDigit)/base;
var occsInLastDigit = pow*(prevDigits+(lastDigit>digit));
var occsOfLastInRest = rest * (lastDigit==digit);
// console.log(prevDigits+" "+lastDigit, rest, occsInLastDigit, occsOfLastInRest);
return occsInLastDigit + occsOfLastInRest + digitOccurencesPlus(digit, prevDigits, base, pow*base, pow*lastDigit+rest);
}
}
This is an interesting problem, and already has similar answers for other languages. Maybe you could try to make this one in javascript: Count the number of Ks between 0 and N
That solution is for occurences from 0 to n, but you could easily use it to calculate from a to b this way:
occurences(a,b)= occurences(0,b)-occurences(0,a)
This is much faster (x6) than my original function...JSPERF
function numberOccurences2(targetNumber, minNumber, maxNumber) {
var strMe = "";
for (i = minNumber; i < maxNumber; i++) {
strMe = strMe.concat(i);
}
var re = new RegExp(targetNumber,"g");
var num1 = strMe.length;
var num2 = strMe.replace(re, "").length;
num2 = num1- num2;
return (num2);
}
There has to be a faster way still...