So I came into this online test question, something like this :
Write a function to check if the given value is a single digit. If it is not, add up all the numbers until it becomes a single digit. For example, the given value is 55555 resulting 25. When 2 and 5 added will get 7.
And here is my answer :
function createCheckDigit(membershipId) {
let sum = 0;
let array = membershipId.toString().split("")
if(array.length > 1){
for(let i = 0; i < array.length; i++){
sum = sum + parseInt(array[i]);
}
}
if(sum.toString().split("").length > 1){
return createCheckDigit(sum.toString())
} else {
return sum
}
}
console.log(createCheckDigit("55555"));
The goal for this question is:
test case answer = 7 (done)
single iteration required (required)
two iterations required (done)
multiple iterations required (done)
I managed to get 1, 3, 4 fulfilled but not 2. I don't understand which part should the single iteration takes place?
I think I have found a solution to the problem:
function checkDigit(v) {
let sum = 0;
const digits = v.toString().split("");
for (let i = 0; i < digits.length; ++i) {
sum += Number(digits[i]);
if (sum >= 10) {
sum -= 9; // same as (sum - 10) + 1; this works because we won't ever get a sum greater than 9+9=18 so the sum of those digits will be a single digit
}
}
return sum;
}
console.log(checkDigit('55555'));
console.log(checkDigit('2'));
console.log(checkDigit('12345'));
console.log(checkDigit('99999'));
console.log(checkDigit('775542'));
This question already has answers here:
Generate unique random numbers between 1 and 100
(32 answers)
Closed 2 years ago.
this is my first question here.
I need to generate an array containing 16 random numbers and that's my solution:
var arr = [];
for (var i = 0; i < 16; i++) {
arr.push(Math.floor(Math.random() * 100) + 1);
}
The problem is that in this way it is possible that there are repeated numbers. Is there someone who can help me? Thanks in advance.
The shortest approach is to use a Set and check the wanted size of it.
let numbers = new Set,
result;
while (numbers.size < 16) numbers.add(Math.floor(Math.random() * 100) + 1);
result = [...numbers];
console.log(...result);
Use a while loop
const MAX_NUMBER = 16;
const arr = [];
do {
const randomNumber = Math.floor(Math.random() * 100) + 1
// Push if the array does not contain it
if (!arr.includes(randomNumber)) {
arr.push(randomNumber);
}
} while (arr.length < MAX_NUMBER);
console.log(arr)
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 need to generate 30 Random Numbers between 1 to 20. I am using this code but this is making conflict since the loop number is bigger than the Random range (I guess!)
var arr1 = [];
for (var i = 0; i < 30;) {
var ran = Math.floor(Math.random() * 20) + 1;
if ( arr1.indexOf(ran) == -1)
arr1[i++] = ran;
}
can you please let me know why this is happening and how I can prevent this to create 30 random numbers?
Thanks
I created a fiddle here , have a look
https://jsbin.com/kagixi/edit?html,js,output
In first case, we are updating values by iterating over all the indices.
var list = new Array(30).fill(0);
list.forEach(function(d, index){
list[index] = Math.floor(Math.random() * 20) + 1;
});
console.log(list);
Another way of doing this is to initialize array just to loop and then simply create a new array with same length or replace the existing one as I did in this example.
var list2 = new Array(30).fill(0);
list2 = list2.map(function(){
return Math.floor(Math.random() * 20) + 1;
});
You miss the third argument on your for statement.
Try this:
var arr1 = [];
for (var i = 0; i < 30; i++) {
arr1[i] = Math.floor(Math.random() * 20) + 1;
}
Your code creates an infinite loop.
Your random numbers are between 1 and 20 but you want 30 of them in your array. The check for duplicates in the line if ( arr1.indexOf(ran) == -1) is guaranteed to return false after 20 iterations, creating an infinite loop.
Ok so i need to create four randomly generated numbers between 1-10 and they cannot be the same. so my thought is to add each number to an array but how can I check to see if the number is in the array, and if it is, re-generate the number and if it isnt add the new number to the array?
so basically it will go,
1.create new number and add to array
2.create second new number, check to see if it exist already, if it doesn't exist, add to array. If it does exist, re-create new number, check again etc...
3.same as above and so on.
You want what is called a 'random grab bag'. Consider you have a 'bag' of numbers, each number is only represented once in this bag. You take the numbers out, at random, for as many as you need.
The problem with some of the other solutions presented here is that they randomly generate the number, and check to see if it was already used. This will take longer and longer to complete (theoretically up to an infinite amount of time) because you are waiting for the random() function to return a value you don't already have (and it doesn't have to do that, it could give you 1-9 forever, but never return 10).
There are a lot of ways to implement a grab-bag type solution, each with varying degrees of cost (though, if done correctly, won't ever be infinite).
The most basic solution to your problem would be the following:
var grabBag = [1,2,3,4,5,6,7,8,9,10];
// randomize order of elements with a sort function that randomly returns -1/0/1
grabBag.sort(function(xx,yy){ return Math.floor(Math.random() * 3) - 1; })
function getNextRandom(){
return grabBag.shift();
};
var originalLength = grabBag.length;
for(var i = 0; i < originalLength; i++){
console.log(getNextRandom());
}
This is of course destructive to the original grabBag array. And I'm not sure how 'truly random' that sort is, but for many applications it could be 'good enough'.
An slightly different approach would be to store all the unused elements in an array, randomly select an index, and then remove the element at that index. The cost here is how frequently you are creating/destroying arrays each time you remove an element.
Here are a couple versions using Matt's grabBag technique:
function getRandoms(numPicks) {
var nums = [1,2,3,4,5,6,7,8,9,10];
var selections = [];
// randomly pick one from the array
for (var i = 0; i < numPicks; i++) {
var index = Math.floor(Math.random() * nums.length);
selections.push(nums[index]);
nums.splice(index, 1);
}
return(selections);
}
You can see it work here: http://jsfiddle.net/jfriend00/b3MF3/.
And, here's a version that lets you pass in the range you want to cover:
function getRandoms(numPicks, low, high) {
var len = high - low + 1;
var nums = new Array(len);
var selections = [], i;
// initialize the array
for (i = 0; i < len; i++) {
nums[i] = i + low;
}
// randomly pick one from the array
for (var i = 0; i < numPicks; i++) {
var index = Math.floor(Math.random() * nums.length);
selections.push(nums[index]);
nums.splice(index, 1);
}
return(selections);
}
And a fiddle for that one: http://jsfiddle.net/jfriend00/UXnGB/
Use an array to see if the number has already been generated.
var randomArr = [], trackingArr = [],
targetCount = 4, currentCount = 0,
min = 1, max = 10,
rnd;
while (currentCount < targetCount) {
rnd = Math.floor(Math.random() * (max - min + 1)) + min;
if (!trackingArr[rnd]) {
trackingArr[rnd] = rnd;
randomArr[currentCount] = rnd;
currentCount += 1;
}
}
alert(randomArr); // Will contain four unique, random numbers between 1 and 10.
Working example: http://jsfiddle.net/FishBasketGordo/J4Ly7/
var a = [];
for (var i = 0; i < 5; i++) {
var r = Math.floor(Math.random()*10) + 1;
if(!(r in a))
a.push(r);
else
i--;
}
That'll do it for you. But be careful. If you make the number of random numbers generated greater than the may number (10) you'll hit an infinite loop.
I'm using a recursive function. The test function pick 6 unique value between 1 and 9.
//test(1, 9, 6);
function test(min, max, nbValue){
var result = recursValue(min, max, nbValue, []);
alert(result);
}
function recursValue(min, max, nbValue, result){
var randomNum = Math.random() * (max-min);
randomNum = Math.round(randomNum) + min;
if(!in_array(randomNum, result)){
result.push(randomNum);
nbValue--;
}
if(nbValue>0){
recursValue(min, max, nbValue, result);
}
return result;
}
function in_array(value, my_array){
for(var i=0;i< my_array.length; i++){
if(my_array[i] == value){
console.log(my_array+" val "+value);
return true;
}
}
return false;
}
Here is a recursive function what are you looking for.
"howMany" parameter is count of how many unique numbers you want to generate.
"randomize" parameter is biggest number that function can generate.
for example : rand(4,8) function returns an array that has 4 number in it, and the numbers are between 0 and 7 ( because as you know, Math.random() function generates numbers starting from zero to [given number - 1])
var array = [];
var isMatch= false;
function rand(howMany, randomize){
if( array.length < howMany){
var r = Math.floor( Math.random() * randomize );
for( var i = 0; i < howMany; i++ ){
if( array[i] !== r ){
isMatch= false;
continue;
} else {
isMatch= true;
break;
}
}
if( isMatch == false ){
array.push(r);
ran(howMany, randomize);
}
ran(howMany, randomize);
return array;
}
}
In your answer earlier, you do have a small bug. Instead of
var originalLength = grabBag.length;
for(var i = 0; i < originalLength .length; i++){
console.log(getNextRandom());
}
I believe you meant:
var originalLength = grabBag.length;
for(var i = 0; i < originalLength; i++){
console.log(getNextRandom());
}
Thanks.