Persistent Bugger - Help to get rid of some 0 - javascript

I need some help with a task which is about creating a function that only accepts integer numbers to then multiply each other until getting only one digit. The answer would be the times:
Example: function(39) - answer: 3
Because 3 * 9 = 27, 2 * 7 = 14, 1 * 4 = 4 and 4 has only one digit
Example2: function(999) - answer: 4
Because 9 * 9 * 9 = 729, 7 * 2 * 9 = 126, 1 * 2 * 6 = 12, and finally 1 * 2 = 2
Example3: function(4) - answer: 0
Because it has one digit already
So trying to figure out how to solve this after many failures, I ended up coding this:
function persistence(num) {
let div = parseInt(num.toString().split(""));
let t = 0;
if(Number.isInteger(num) == true){
if(div.length > 1){
for(let i=0; i<div.length; i++){
div = div.reduce((acc,number) => acc * number);
t += 1;
div = parseInt(div.toString().split(""))
if(div.length == 1){
return t } else {continue}
} return t
} else { return t }
} else { return false }
}
console.log(persistence(39),3);
console.log(persistence(4),0);
console.log(persistence(25),2);
console.log(persistence(999),4);
/*
output: 0 3
0 0
0 2
0 4
*/
It seems I could solve it, but the problem is I don't know why those 0s show up. Besides I'd like to receive some feedback and if it's possible to improve those codes or show another way to solve it.
Thanks for taking your time to read this.
///EDIT///
Thank you all for helping and teaching me new things, I could solve this problem with the following code:
function persistence(num){
let t = 0;
let div;
if(Number.isInteger(num) == true){
while(num >= 10){
div = (num + "").split("");
num = div.reduce((acc,val) => acc * val);
t+=1;
} return t
}
}
console.log(persistence(39));
console.log(persistence(4));
console.log(persistence(25));
console.log(persistence(999));
/*output: 3
0
2
4
*/

You've got a few issues here:
let div = parseInt(num.toString().split("")); You're casting an array to a number, assuming you're trying to extract the individual numbers into an array, you were close but no need for the parseInt.
function persistence(input, count = 0) {
var output = input;
while (output >= 10) {
var numbers = (output + '').split('');
output = numbers.reduce((acc, next) {
return Number(next) * acc;
}, 1);
count += 1;
}
​
return count;
};
For something that needs to continually check, you're better off using a recurssive function to check the conditions again and again, this way you won't need any sub loops.
Few es6 features you can utilise here to achieve the same result! Might be a little too far down the road for you to jump into es6 now but here's an example anyways using recursion!
function recursive(input, count = 0) {
// convert the number into an array for each number
const numbers = `${input}`.split('').map(n => Number(n));
// calculate the total of the values
const total = numbers.reduce((acc, next) => next * acc, 1);
// if there's more than 1 number left, total them up and send them back through
return numbers.length > 1 ? recursive(total, count += 1) : count;
};
console.log(recursive(39),3);
console.log(recursive(4),0);
console.log(recursive(25),2);
console.log(recursive(999),4);

function persistance (num) {
if (typeof num != 'number') throw 'isnt a number'
let persist = 0
while(num >= 10) {
let size = '' + num
size = size.length
// Get all number of num
const array = new Array(size).fill(0).map((x, i) => {
const a = num / Math.pow(10, i)
const b = parseInt(a, 10)
return b % 10
})
console.log('here', array)
// actualiser num
num = array.reduce((acc, current) => acc * current, 1)
persist++
}
return persist
}
console.log(persistance(39))
console.log(persistance(999))

console.log() can take many argument...
So for example, console.log("A", "B") will output "A" "B".
So all those zeros are the output of your persistence function... And the other number is just the number you provided as second argument.
So I guess you still have to "persist"... Because your function always returns 0.
A hint: You are making this comparison: div.length > 1...
But div is NOT an array... It is a number, stringified, splitted... And finally parsed as integer.
;) Good luck.
Side note, the calculation you are attempting is known as the Kaprekar's routine. So while learning JS with it... That history panel of the recreational mathematic wil not hurt you... And may be a good line in a job interview. ;)
My best hint
Use the console log within the function to help you degug it. Here is your unchanged code with just a couple of those.
function persistence(num) {
let div = parseInt(num.toString().split(""));
let t = 0;
console.log("div.length", div.length)
if (Number.isInteger(num) == true) {
if (div.length > 1) {
for (let i = 0; i < div.length; i++) {
div = div.reduce((acc, number) => acc * number);
t += 1;
div = parseInt(div.toString().split(""));
if (div.length == 1) {
console.log("return #1")
return t;
} else {
continue;
}
}
console.log("return #2")
return t;
} else {
console.log("return #3")
return t;
}
} else {
console.log("return #4")
return false;
}
}
console.log(persistence(39), 3);
console.log(persistence(4), 0);
console.log(persistence(25), 2);
console.log(persistence(999), 4);

Related

Iterate over uneven array

So I have a dataset of 16 items, I want to loop through them every 5 items after the first set of 6 so the columns are 6 5 5.
Initially I tried something like this, but then I remembered I had that one orphaned item.
if(thisI <= 6) {
y = prevtitle.position[0];
} elseif(thisI % 5 == 0) {
y = prevtitle.position[0] + w + (p *3);
} else {
y = prevtitle.position[0];
}
Not sure if there is a simple way to do the first 6 and then the next ones in five without a bunch of nested if statements.
Using Array#splice:
const splitArr = (arr = []) => {
const array = [...arr];
const res = array.length ? [array.splice(0, 6)] : [];
while(array.length) res.push(array.splice(0, 5));
return res;
}
console.log( splitArr([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]) );
Would a simple ternary expression work for you?
let num = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
num.forEach((n,i) => {
y = (i<=6 || i % 5 == 0) ? prevtitle.position[0] : prevtitle.position[0] + w + (p *3) ;
})
I presume that you're skipping the first position, and jumps directly to the 6th position.
Just use a normal for loop.
Calculate the remainder for the number of steps that you will make. 16 % 5 results in 1 remainder.
step - countForZero + remainder sets the start point in the for loop.
i += step replaces the typical i++ in the for loop.
The method below can make any kind of leap, and it doesn't matter how many items there are in the array.
let num = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
function getEvery(step, arr) {
let newArr = [],
remainder = arr.length % step,
countForZero = 1;
for (let i = step - countForZero + remainder; i < arr.length; i += step) {
newArr.push(arr[i]);
}
return newArr;
}
console.log( getEvery(5, num) );

How Can I find the first number greater than const M?

I have a problem with this. I have to find the first prime number greater than my const M.
For example, I have M = 11, and I have to find the first prime number greater than M and it is 13.
How Can I do that?
// isPrime
const M = 11
function isPrime(num) {
if (num < 2) return false;
for (let i = 2; i < num; i++) {
if (num % i == 0) return false;
}
return true;
}
console.log(isPrime(M))
And I would like find for M = 11, primeNumber = 13, for M = 15, primeNumber = 17 etc.
You can iterate from M+1 until you find your prime number. You can do the following,
function isPrime(num) {
if (num < 2) return false;
for (let i = 2; i < num; i++) {
if (num % i == 0) return false;
}
return true;
}
findGreaterPrime = (m) => {
let i = m+1;
let found = false;
while(!found) {
if(isPrime(i)) {
found = true;
return i;
}
i++;
}
}
console.log(findGreaterPrime(11));
console.log(findGreaterPrime(13));
By the way, this method will be very slow for larger numbers. You can use some fast prime generators. You can follow the answers in this thread.
Simple and fast solution, via prime-lib (I'm the author).
The example below generates 2 primes, starting with 7 and upward:
import {generatePrimes, stopOnCount} from 'prime-lib';
const i = generatePrimes({start: 7}); // infinite prime-iterator
const s = stopOnCount(i, 2); // stop-iterator
const values = [...s]; // 7, 11
It checks if start is a prime, to be included then. If you need only a prime that follows, just check if the first number matches your M number, then take the next one instead:
if(values[0] === M) {
// use values[1]
} else {
// use values[0]
}

How does this recursion solve explosive sum function

The question asked how many ways you can make a sum of the number. I have been trying to understand the solving process, but I am so confused about how this recursion worked. What is the value of memo[n] and memo[n][m]. It is an empty array. How is it end up with the correct answer?
var memo = [];
function sum(n, m = n) {
// console.log("mmeno0",memo)
if (n == 0) return 1;
if (n < 0 || m == 0) return 0;
if (memo[n] && memo[n][m]) {
return memo[n][m];
}
let total = sum(n, m - 1) + sum(n - m, m);
if (!memo[n]) {
memo[n] = [];
}
memo[n][m] = total;
return total;
}
// sum(1) // 1
//sum(2) // 2 -> 1+1 , 2
console.log(sum(3),memo); // 3 -> 1+1+1, 1+2, 3
memo standards for memorize and stores the result of previous (partial) result in an array of arrays so they can be reused. In literature this approach is called dynamic programming.

Optimizing and finding edge cases that I might have missed - 2 coding interview questions

Background - I took an online coding test and was presented with questions similar to this, I did rather poorly on it compared to the hidden grading criteria and I was hoping to get another pair of eyes to look at it and maybe help point out some of my mistakes.
Practice Test questions -
Task: Given an integer inject the number 5 into it to make the largest possible integer
Conditions: (-80000...80000) range needed to handle
Expected input: int
Expected output: int
Testcase: -999 -> -5999
80 -> 850
var lrgInt = function(num) {
var stringInt = num.toString();
for (let i = 0; i < stringInt.length; i++) {
if (stringInt.charAt(i) === "-") {
return parseInt([stringInt.slice(0, 1), '5', stringInt.slice(1)].join(''));
}else if (stringInt.charAt(i) < 5) {
return parseInt([stringInt.slice(0, i), '5', stringInt.slice(i)].join(''));
}
}
return parseInt([stringInt.slice(0, stringInt.length), '5', stringInt.slice(stringInt.length)].join(''));
};
Task: Determine the number of operations done on a number following the conditions to reduce it to 0.
Conditions:
- If the number is odd, subtract 1
- If the number is even, divide by 2
Expected input: int
Expected output: int
var operations = 0;
var numberOfSteps = function(num) {
if (num === 0){
return operations;
}else if (num % 2 == 0) {
operations++;
return numberOfSteps(num/2);
} else {
operations++;
return numberOfSteps(num-1);
}
};
For the second question, you could add one plus the result of recursion with the adjusted number without having a global counter.
function numberOfSteps(number) {
if (!number) return 0;
if (number % 2) return 1 + numberOfSteps(number - 1);
return 1 + numberOfSteps(number / 2);
}
console.log(numberOfSteps(5)); // 5 4 2 1 0
For the first question, we make the observation that if the number is positive, we want to inject the 5 before the first digit less than 5, but if it's negative then we want to inject it before the first digit greater than 5. For the second problem, we can just use a simple while loop.
function largestNum(num) {
if (num == 0) {
// this edge case is weird but I'm assuming this is what they want
return 50;
}
var negative = num < 0;
var numAsStr = Math.abs(num).toString();
var inj = -1;
for (var i = 0; i < numAsStr.length; i++) {
var cur = parseInt(numAsStr[i], 10);
if ((!negative && cur < 5) || (negative && cur > 5)) {
// we found a place to inject, break
inj = i;
break;
}
}
if (inj == -1) {
// didn't inject anywhere so inject at the end
inj = numAsStr.length;
}
return (
(negative ? -1 : 1) *
parseInt(numAsStr.substr(0, inj) + "5" + numAsStr.substr(inj))
);
}
function numSteps(num) {
var steps = 0;
while (num != 0) {
if (num % 2) {
// it's odd
num--;
} else {
num /= 2;
}
steps++;
}
return steps;
}

Transform this iteration function to recursive

This is a function to display the sum of the input digits with iteration perspective:
function sumOfDigits(number) {
let strNumber = number.toString()
let output = 0;
for(i=0;i<strNumber.length;i++){
let tmp = parseInt(strNumber[i])
output = output + tmp
}
return output
}
// TEST CASES
console.log(sumOfDigits(512)); // 8
console.log(sumOfDigits(1542)); // 12
console.log(sumOfDigits(5)); // 5
console.log(sumOfDigits(21)); // 3
console.log(sumOfDigits(11111)); // 5
I am wondering how we write this function in a recursive way?
Using the modulo operator, you can get the remainder (which in the case of a divison by 10, is the last number) and then add the next iteration.
function sumOfDigits (n) {
if (n === 0) return 0
return (n % 10 + sumOfDigits(Math.floor(n / 10)))
}
console.log(sumOfDigits(512))
If you want to see a more detailed explanation, check https://www.geeksforgeeks.org/sum-digit-number-using-recursion/
I have not tested it, but you can try the following without casting to string
function sumOfDigits(number)
{
if (number === 0) {
return 0;
}
return (number % 10 + sumOfDigits(Math.floor(number / 10)));
}
Make sure that the input is indeed in number format
Here you go
function sumOfDigitsRecursive(number){
let strNumber = number.toString()
if(strNumber.length<=0)
return 0
return parseInt(strNumber[0])+sumOfDigitsRecursive(strNumber.slice(1,strNumber.length))
}

Categories

Resources