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
Related
I am trying to solve the below problem in JavaScript
The count-and-say sequence is the sequence of integers beginning as follows:
1, 11, 21, 1211, 111221, ...
1 is read off as one 1 or 11.
11 is read off as two 1s or 21.
21 is read off as one 2, then one 1 or 1211.
Given an integer n, generate the nth sequence.
Note: The sequence of integers will be represented as a string.
Example:
if n = 2,
the sequence is 11.
So I want to create a function which pass N integer and gives it value
Here is my code:
let countAndSay = function (A) {
if (A == 1) return "1"
if (A == 2) return "11"
let str ="11"
if(A > 2){
// count
}
}
I don't understand the logic for how to build this.
You need to be able to dynamically determine the number and type of chunks a string has, which can be done pretty concisely with a regular expression. To come up with the string to deconstruct on index n, recursively call countAndSay to get the result of n - 1:
let countAndSay = function (count) {
if (count === 1) {
return '1';
}
const digitsArr = countAndSay(count - 1).match(/(\d)\1*/g);
// You now have an array of each chunk to construct
// eg, from 1211, you get
// ['1', '2', '11']
return digitsArr // Turn the above into ['11', '12', '21']:
.map(digitStr => digitStr.length + digitStr[0])
.join(''); // Turn the above into '111221'
};
console.log(
countAndSay(1),
countAndSay(2),
countAndSay(3),
countAndSay(4),
countAndSay(5),
);
Here's a function that generates the next string of numbers based on the previous string you feed it:
function next(s) {
s = s + "*"; // add a flag value at the end of the string
var output = "";
var j = 0;
for (var i = 1; i < s.length; i++) {
if (s.charAt(i) != s.charAt(i - 1)) { // if the character changes, concatenate the amount (i - j) and the digit
output += (i - j) + s.substring(j, j+1);
j = i;
}
}
return output;
}
Then you'd need to recursively run next N times.
I've been working on a kata from Codewars, the challenge is to write a function, persistence, that takes in a positive parameter num and returns its multiplicative persistence, which is the number of times you must multiply the digits in num until you reach a single digit.
Example:
persistence(39) === 3 // because 3*9 = 27, 2*7 = 14, 1*4=4
// and 4 has only one digit
persistence(999) === 4 // because 9*9*9 = 729, 7*2*9 = 126,
// 1*2*6 = 12, and finally 1*2 = 2
persistence(4) === 0 // because 4 is already a one-digit number
While trying to figure this out I came across a solution online (shown below) and after trying to understand its logic, I couldn't see why the code didn't work
var count = 0;
function persistence(num) {
if (num.toString().length === 1) {
return count;
}
count++;
var mult = 1;
var splitStr = num.toString().split("");
for (var i = 0; i <= splitStr; i++) {
mult *= parseFloat(splitStr[i])
}
return persistence(parseFloat(mult));
}
The output for any single digit number will be 0 which is correct however for any number that is multiple digits, the persistence always logs as 1 and I can't seem to figure out why, any help would be greatly appreciated.
The posted code has quite a few problems.
for (var i = 0; i <= splitStr; i++) {
But splitStr is an array, not a number; i <= splitStr doesn't make sense. It should check against splitStr.length instead of splitStr.
Another problem is that it should use i <, not i <=, else the final splitStr[i] will be undefined.
Another problem is that the count variable is global, so more than one call of persistence will result in inaccurate results. There's no need for a count variable at all. To fix it:
function persistence(num) {
if (num.toString().length === 1) {
return 0;
}
var mult = 1;
var splitStr = num.toString().split("");
for (var i = 0; i < splitStr.length; i++) {
mult *= parseFloat(splitStr[i])
}
return 1 + persistence(parseFloat(mult));
}
console.log(
persistence(999),
persistence(39),
persistence(4)
);
Or, one could avoid the for loop entirely, and use more appropriate array methods:
function persistence(num) {
const str = num.toString();
if (str.length === 1) {
return 0;
}
const nextNum = str.split('').reduce((a, b) => a * b, 1);
return 1 + persistence(nextNum);
}
console.log(
persistence(999),
persistence(39),
persistence(4)
);
or we can use while loop with reduce array method
const persistence=(num)=>{
let splitNumArr=num.toString().split('')
let newList
let count=0
while(splitNumArr.length>1){
newList=splitNumArr.reduce((acc,curr)=>{
return acc*=curr
})
splitNumArr=newList.toString().split('')
count++
}
return count
}
console.log(persistence(39))===3
console.log(persistence(999))===4
console.log(persistence(9))===0
I am trying to write a function that takes a positive integer and returns the next smaller positive integer containing the same digits, and -1 when there is no smaller number that contains the same digits.
For example:
nextSmaller(21) == 12
nextSmaller(531) == 513
nextSmaller(2071) == 2017
I wrote a code that solves this, but I don't really know how to optimize it further. Could you please help me? It runs fairly fast on repl.it, but when I submit it, it says it takes more than 1200ms and doesn't allow me to submit it even though all the tests pass.
function nextSmaller(n) {
var nArray= n.toString().split("")
var minimumNum = 1 + Array(nArray.length).join('0')
for(var i=n-1; i >= minimumNum; i--) {
var newNumArray = i.toString().split('');
var counter = 0;
for (var j=0; j<newNumArray.length; j++) {
if (nArray.indexOf(newNumArray[j]) > -1) {
counter++
nArray.splice(nArray.indexOf(newNumArray[j]), 1)
if (counter === n.toString().split("").length) {
return i;
}
}
}
nArray = n.toString().split("");
if (i === Number(minimumNum)) return -1;
}
}
Your code could be optimized a bit, for instance you could use a break statement in your inner loop to move on to the next number as soon as you know the current one isn't going to work (that should make it run in about half the time, but it is still quite slow for an n like 91234567) and instead of n.toString().split("").length in the loop, use a variable so you only need to convert n to an array once.
function nextSmaller(n) {
var nArray = n.toString().split("")
var length = nArray.length;
var minimumNum = 1 + Array(length).join('0')
for(var i=n-1; i >= minimumNum; i--) {
var newNumArray = i.toString().split('');
var counter = 0;
for (var j=0; j<newNumArray.length; j++) {
if (nArray.indexOf(newNumArray[j]) < 0)
break;
counter++
nArray.splice(nArray.indexOf(newNumArray[j]), 1)
if (counter === length) {
return i;
}
}
nArray = n.toString().split("");
}
return -1;
}
There is a very efficient algorithm for computing the next permutation, which can easily be adapted to get the previous one instead (and return -1 if the resulting permutation starts with 0). I adapted this algorithm to do that:
[21,531,2071,912345678,9123545678,915345678].forEach( x => console.log( nextSmaller( x ) ) );
function nextSmaller(n) {
const arr = ( n + '' ).split( '' ).map( Number );
// Find longest non-decreasing suffix
let i, prev = 9;
for ( i = arr.length; i--; ) {
if ( arr[ i ] > prev )
break;
prev = arr[ i ];
}
// If whole sequence is non-decreasing,
// it is already the smallest permutation
if ( i < 0 )
return -1;
const pivot_i = i;
const pivot = arr[ pivot_i ];
for ( i = arr.length; i--; ) {
if ( arr[ i ] < pivot )
break;
}
arr[ pivot_i ] = arr[ i ];
arr[ i ] = pivot;
if ( arr[ 0 ] === 0 )
return -1;
return +arr.slice( 0, pivot_i + 1 ).concat( arr.slice( pivot_i + 1 ).reverse( ) ).join('');
}
The algorithm could be like the following:
For the input number n find all numbers that are formed with some permutations of the same digits and sort these numbers. For example, if n=213, we get the sorted list as [123, 132, 213, 231, 312, 321]. (e.g., Permutations in JavaScript? can help you).
Find the index i of the number n in the sorted list. If i>0 return the number at index i-1 else return -1 (if it's the smallest number appearing at the first position of the sorted list).
Another alternative algorithm could be the following:
Decrement the number n until and unless you find one that has exactly same digits (in a different order, you can sort the digits and check for equality).
The most efficient will be similar to the one referred to by #Paulpro(https://www.nayuki.io/page/next-lexicographical-permutation-algorithm)
Find the longest non-decreasing suffix from the decimal string representation of n.
If the entire string n is non-decreasing then return -1 (there can't be any smaller).
Otherwise choose the digit immediately left to the start of the suffix as pivot and swap it with (the leftmost and) the largest digit in the suffix that is smaller than the pivot. Return this number.
I am attempting to write a function that takes an (unsigned) integer as input, and returns the number of bits that are equal to one in the binary representation of that number.
Example: The binary representation of 1234 is 10011010010, so the function should return 5 in this case.
Here is my answer:
var newArr;
var count = 0;
function countBits(num){
newArr = num.toString(2).split('').map(function(el){
if(el == '1')
count++
});;
return count;
}
In my program when I call countBits(7) it returns //3 but when I submit my response it says it is returning //4. Can someone see what I am missing in my response based on question?
Your problem is that you are declaring the variables outside of the function, so when the function is called multiple times they'll keep their values and just increase the count.
Btw, you also shouldn't use map if you don't want to create another array - so better do
function countBits(num){
var newArr = num.toString(2).split('').map(Number);
var count = 0;
for (var i=0; i<newArr.length; i++)
count += newArr[i];
}
return count;
}
or
function countBits(num){
return num.toString(2).split('').reduce(function(count, el) {
return count + (el == "1");
}, 0);
}
function countBits(num){
/* Convert num Base10 to num Base2
then find Ones and save them in an array
length of the array is equal their sum */
return num.toString(2).match(/1/g).length
}
function countBits(num){
// convert num Base10 to Base2
let base2 = num.toString(2)
// declare variable for sum of bits
let sum = 0
// for loop to check bits (bit = 1) and ignore Zeros in the String base2
for(let i = 0; i < base2.length; i++){
if(base2[i] == 1){
// use Number() to convert string to number
count += Number(base2[i])
}
}
return sum ;
}
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;
}