How does this recursion solve explosive sum function - javascript

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.

Related

How to limit a number between several numbers (get the most nearest small number)? [duplicate]

Example: I have an array like this: [0,22,56,74,89] and I want to find the closest number downward to a different number. Let's say that the number is 72, and in this case, the closest number down in the array is 56, so we return that. If the number is 100, then it's bigger than the biggest number in the array, so we return the biggest number. If the number is 22, then it's an exact match, just return that. The given number can never go under 0, and the array is always sorted.
I did see this question but it returns the closest number to whichever is closer either upward or downward. I must have the closest one downward returned, no matter what.
How do I start? What logic should I use?
Preferably without too much looping, since my code is run every second, and it's CPU intensive enough already.
You can use a binary search for that value. Adapted from this answer:
function index(arr, compare) { // binary search, with custom compare function
var l = 0,
r = arr.length - 1;
while (l <= r) {
var m = l + ((r - l) >> 1);
var comp = compare(arr[m]);
if (comp < 0) // arr[m] comes before the element
l = m + 1;
else if (comp > 0) // arr[m] comes after the element
r = m - 1;
else // arr[m] equals the element
return m;
}
return l-1; // return the index of the next left item
// usually you would just return -1 in case nothing is found
}
var arr = [0,22,56,74,89];
var i=index(arr, function(x){return x-72;}); // compare against 72
console.log(arr[i]);
Btw: Here is a quick performance test (adapting the one from #Simon) which clearly shows the advantages of binary search.
var theArray = [0,22,56,74,89];
var goal = 56;
var closest = null;
$.each(theArray, function(){
if (this <= goal && (closest == null || (goal - this) < (goal - closest))) {
closest = this;
}
});
alert(closest);
jsFiddle http://jsfiddle.net/UCUJY/1/
Array.prototype.getClosestDown = function(find) {
function getMedian(low, high) {
return (low + ((high - low) >> 1));
}
var low = 0, high = this.length - 1, i;
while (low <= high) {
i = getMedian(low,high);
if (this[i] == find) {
return this[i];
}
if (this[i] > find) {
high = i - 1;
}
else {
low = i + 1;
}
}
return this[Math.max(0, low-1)];
}
alert([0,22,56,74,89].getClosestDown(75));
Here's a solution without jQuery for more effiency. Works if the array is always sorted, which can easily be covered anyway:
var test = 72,
arr = [0,56,22,89,74].sort(); // just sort it generally if not sure about input, not really time consuming
function getClosestDown(test, arr) {
var num = result = 0;
for(var i = 0; i < arr.length; i++) {
num = arr[i];
if(num <= test) { result = num; }
}
return result;
}
Logic: Start from the smallest number and just set result as long as the current number is smaller than or equal the testing unit.
Note: Just made a little performance test out of curiosity :). Trimmed my code down to the essential part without declaring a function.
Here's an ES6 version using reduce, which OP references. Inspired by this answer get closest number out of array
lookup array is always sorted so this works.
const nearestBelow = (input, lookup) => lookup.reduce((prev, curr) => input >= curr ? curr : prev);
const counts = [0,22,56,74,89];
const goal = 72;
nearestBelow(goal, counts); // result is 56.
Not as fast as binary search (by a long way) but better than both loop and jQuery grep https://jsperf.com/test-a-closest-number-function/7
As we know the array is sorted, I'd push everything that asserts as less than our given value into a temporary array then return a pop of that.
var getClosest = function (num, array) {
var temp = [],
count = 0,
length = a.length;
for (count; count < length; count += 1) {
if (a[count] <= num) {
temp.push(a[count]);
} else {
break;
}
}
return temp.pop();
}
getClosest(23, [0,22,56,74,89]);
Here is edited from #Simon.
it compare closest number before and after it.
var test = 24,
arr = [76,56,22,89,74].sort(); // just sort it generally if not sure about input, not really time consuming
function getClosest(test, arr) {
var num = result = 0;
var flag = 0;
for(var i = 0; i < arr.length; i++) {
num = arr[i];
if(num < test) {
result = num;
flag = 1;
}else if (num == test) {
result = num;
break;
}else if (flag == 1) {
if ((num - test) < (Math.abs(arr[i-1] - test))){
result = num;
}
break;
}else{
break;
}
}
return result;
}

Persistent Bugger - Help to get rid of some 0

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);

How to convert this O(n^2) algorithm to O(n)?

https://www.codewars.com/kata/is-my-friend-cheating/train/javascript
My goal is to devise a function that finds number pairs (a, b) which satisfy the equation a * b == sum(1, 2, 3 ..., n-2, n-1, n) - a - b.
The following code finds all the pairs, but is too slow and times out. I have seen in the comments for this challenge that the algorithm needs to have O(n) complexity to pass. How is this done?
function removeNb (n) {
if(n===1) return null;
let sum = (n * (n+1))/2;
let retArr = [];
let a = n;
while( a !== 0){
let b = n;
while( b !== 0){
if(b != a && a*b == ((sum - b) - a) ){
retArr.push([a,b]);
}
b--;
}
a--;
}
retArr.sort( (a,b) => a[0] - b[0]);
return retArr;
}
Thanks to all for the assistance! Here is my final solution:
function removeNb (n) {
let retArr = [];
let a = 1;
let b = 0;
let sumN = (n * (n+1))/2;
while( a <= n){
b = parseInt((sumN - a) / (a + 1));
if( b < n && a*b == ((sumN - b) - a) )
retArr.push([a,b]);
a++;
}
return retArr;
}
I think my main issue was an (embarrassing) error with my algebra when I attempted to solve for b. Here are the proper steps for anyone wondering:
a*b = sum(1 to n) - a - b
ab + b = sumN - a
b(a + 1) = sumN - a
b = (sumN - a) / (a + 1)
You can solve for b and get: b = (sum - a)/(a + 1) (given a != -1)
Now iterate over a once -> O(n)
let n = 100;
let sumOfNum = n => {
return (n * (n + 1)) / 2;
};
let sum = sumOfNum(n);
let response = [];
for (let i = 1; i <= 26; i++) {
let s = (sum - i) / (i + 1);
if (s % 1 == 0 && s * i == sum - s - i && s <= n) {
response.push([s, i]);
}
}
// this is O(N) time complexity
Here's an implementation:
function removeNb(n){
var sum = (1 + n) * n / 2;
var candidates = [];
// O(n)
for(var y = n; y >= 1; y--){
x = (-y + sum) / (y + 1);
/*
* Since there are infinite real solutions,
* we only record the integer solutions that
* are 1 <= x <= n.
*/
if(x % 1 == 0 && 1 <= x && x <= n)
// Assuming .push is O(1)
candidates.push([x, y]);
}
// Output is guaranteed to be sorted because
// y is iterated from large to small.
return candidates;
}
console.log(removeNb(26));
console.log(removeNb(100));
https://jsfiddle.net/DerekL/anx2ox49/
From your question, it also states that
Within that sequence, he chooses two numbers, a and b.
However it does not mention that a and b are unique numbers, so a check is not included in the code.
As explained in other answers, it is possible to make a O(n) algorithm solving for b. Moreover, given the symmetry of solution -- if (a,b) is a solution, also (b,a) is -- it is also possible to save some iterations adding a couple of solutions at a time. To know how many iterations are required, let us note that b > a if and only if a < -1+sqrt(1+sum). To prove it:
(sum-a)/(a+1) > a ; sum-a > a^2+a ; sum > a^2+2a ; a^2+2a-sum < 0 ; a_1 < a < a_2
where a_1 and a_2 comes from 2-degree equation solution:
a_1 = -1-sqrt(1+sum) ; a_2 = -1+sqrt(1+sum)
Since a_1 < 0 and a > 0, finally we proved that b > a if and only if a < a_2.
Therefore we can avoid iterations after -1+sqrt(1+sum).
A working example:
function removeNb (n) {
if(n===1) return null;
let sum = (n * (n+1))/2;
let retArr = [];
for(let a=1;a<Math.round(Math.sqrt(1+sum));++a) {
if((sum-a)%(a+1)===0) {
let b=(sum-a)/(a+1);
if(a!==b && b<=n) retArr.push([a,b],[b,a]);
}
}
retArr.sort( (a,b) => a[0] - b[0]);
return retArr;
}
However, with this implementation we still need the final sort. To avoid it, we can note that b=(sum-a)/(a+1) is a decreasing function of a (derive it to prove). Therefore we can build retArr concatenating two arrays, one adding elements to the end (push), one adding elements at the beginning (unshift). A working example follows:
function removeNb (n) {
if(n===1) return null;
let sum = (n * (n+1))/2;
let retArr = [];
let retArr2 = [];
for(let a=1;a<Math.round(Math.sqrt(1+sum));++a) {
if((sum-a)%(a+1)===0) {
let b=(sum-a)/(a+1);
if(a!==b && b<=n) {
retArr.push([a,b]);
retArr2.unshift([b,a]); // b>a and b decreases with a
}
}
}
retArr=retArr.concat(retArr2); // the final array is ordered in the 1st component
return retArr;
}
As a non-native speaker, I would say that the phrase from the reference "all (a, b) which are the possible removed numbers in the sequence 1 to n" implies a!=b,
so I added this constraint.

A code wars challenge

I have been struggling with this challenge and can't seem to find where I'm failing at:
Some numbers have funny properties. For example:
89 --> 8¹ + 9² = 89 * 1
695 --> 6² + 9³ + 5⁴= 1390 = 695 * 2
46288 --> 4³ + 6⁴+ 2⁵ + 8⁶ + 8⁷ = 2360688 = 46288 * 51
Given a positive integer n written as abcd... (a, b, c, d... being digits) and a positive integer p we want to find a positive integer k, if it exists, such as the sum of the digits of n taken to the successive powers of p is equal to k * n. In other words:
Is there an integer k such as : (a ^ p + b ^ (p+1) + c ^(p+2) + d ^ (p+3) + ...) = n * k
If it is the case we will return k, if not return -1.
Note: n, p will always be given as strictly positive integers.
digPow(89, 1) should return 1 since 8¹ + 9² = 89 = 89 * 1
digPow(92, 1) should return -1 since there is no k such as 9¹ + 2² equals 92 * k
digPow(695, 2) should return 2 since 6² + 9³ + 5⁴= 1390 = 695 * 2
digPow(46288, 3) should return 51 since 4³ + 6⁴+ 2⁵ + 8⁶ + 8⁷ = 2360688 = 46288 * 51
I'm new with javascript so there may be something off with my code but I can't find it. My whole purpose with this was learning javascript properly but now I want to find out what I'm doing wrong.I tried to convert given integer into digits by getting its modulo with 10, and dividing it with 10 using trunc to get rid of decimal parts. I tried to fill the array with these digits with their respective powers. But the test result just says I'm returning only 0.The only thing returning 0 in my code is the first part, but when I tried commenting it out, I was still returning 0.
function digPow(n, p){
// ...
var i;
var sum;
var myArray= new Array();
if(n<0)
{
return 0;
}
var holder;
holder=n;
for(i=n.length-1;i>=0;i--)
{
if(holder<10)
{
myArray[i]=holder;
break;
}
myArray[i]=holder%10;
holder=math.trunc(holder/10);
myArray[i]=math.pow(myArray[i],p+i);
sum=myArray[i]+sum;
}
if(sum%n==0)
{
return sum/n;
}
else
{
return -1;
}}
Here is the another simple solution
function digPow(n, p){
// convert the number into string
let str = String(n);
let add = 0;
// convert string into array using split()
str.split('').forEach(num=>{
add += Math.pow(Number(num) , p);
p++;
});
return (add % n) ? -1 : add/n;
}
let result = digPow(46288, 3);
console.log(result);
Mistakes
There are a few problems with your code. Here are some mistakes you've made.
number.length is invalid. The easiest way to get the length of numbers in JS is by converting it to a string, like this: n.toString().length.
Check this too: Length of Number in JavaScript
the math object should be referenced as Math, not math. (Note the capital M) So math.pow and math.trunc should be Math.pow and Math.trunc.
sum is undefined when the for loop is iterated the first time in sum=myArray[i]+sum;. Using var sum = 0; instead of var sum;.
Fixed Code
I fixed those mistakes and updated your code. Some parts have been removed--such as validating n, (the question states its strictly positive)--and other parts have been rewritten. I did some stylistic changes to make the code more readable as well.
function digPow(n, p){
var sum = 0;
var myArray = [];
var holder = n;
for (var i = n.toString().length-1; i >= 0; i--) {
myArray[i] = holder % 10;
holder = Math.trunc(holder/10);
myArray[i] = Math.pow(myArray[i],p+i);
sum += myArray[i];
}
if(sum % n == 0) {
return sum/n;
} else {
return -1;
}
}
console.log(digPow(89, 1));
console.log(digPow(92, 1));
console.log(digPow(46288, 3));
My Code
This is what I did back when I answered this question. Hope this helps.
function digPow(n, p){
var digPowSum = 0;
var temp = n;
while (temp > 0) {
digPowSum += Math.pow(temp % 10, temp.toString().length + p - 1);
temp = Math.floor(temp / 10);
}
return (digPowSum % n === 0) ? digPowSum / n : -1;
}
console.log(digPow(89, 1));
console.log(digPow(92, 1));
console.log(digPow(46288, 3));
You have multiple problems:
If n is a number it is not going to have a length property. So i is going to be undefined and your loop never runs since undefined is not greater or equal to zero
for(i=n.length-1;i>=0;i--) //could be
for(i=(""+n).length;i>=0;i--) //""+n quick way of converting to string
You never initialize sum to 0 so it is undefined and when you add the result of the power calculation to sum you will continually get NaN
var sum; //should be
var sum=0;
You have if(holder<10)...break you do not need this as the loop will end after the iteration where holder is a less than 10. Also you never do a power for it or add it to the sum. Simply remove that if all together.
Your end code would look something like:
function digPow(n, p) {
var i;
var sum=0;
var myArray = new Array();
if (n < 0) {
return 0;
}
var holder;
holder = n;
for (i = (""+n).length - 1; i >= 0; i--) {
myArray[i] = holder % 10;
holder = Math.trunc(holder / 10);
myArray[i] = Math.pow(myArray[i], p + i);
sum = myArray[i] + sum;
}
if (sum % n == 0) {
return sum / n;
} else {
return -1;
}
}
Note you could slim it down to something like
function digPow(n,p){
if( isNaN(n) || (+n)<0 || n%1!=0) return -1;
var sum = (""+n).split("").reduce( (s,num,index)=>Math.pow(num,p+index)+s,0);
return sum%n ? -1 : sum/n;
}
(""+n) simply converts to string
.split("") splits the string into an array (no need to do %10 math to get each number
.reduce( function,0) call's the array's reduce function, which calls a function for each item in the array. The function is expected to return a value each time, second argument is the starting value
(s,num,index)=>Math.pow(num,p+index+1)+s Fat Arrow function for just calling Math.pow with the right arguments and then adding it to the sum s and returning it
I have created a code that does exactly what you are looking for.The problem in your code was explained in the comment so I will not focus on that.
FIDDLE
Here is the code.
function digPow(n, p) {
var m = n;
var i, sum = 0;
var j = 0;
var l = n.toString().length;
var digits = [];
while (n >= 10) {
digits.unshift(n % 10);
n = Math.floor(n / 10);
}
digits.unshift(n);
for (i = p; i < l + p; i++) {
sum += Math.pow(digits[j], i);
j++;
}
if (sum % m == 0) {
return sum / m;
} else
return -1;
}
alert(digPow(89, 1))
Just for a variety you may do the same job functionally as follows without using any string operations.
function digPow(n,p){
var d = ~~Math.log10(n)+1; // number of digits
r = Array(d).fill()
.map(function(_,i){
var t = Math.pow(10,d-i);
return Math.pow(~~((n%t)*10/t),p+i);
})
.reduce((p,c) => p+c);
return r%n ? -1 : r/n;
}
var res = digPow(46288,3);
console.log(res);

JS:checking if number belongs to Fibonacci sequence(without loop)

Is there an efficient way to check if number belongs to Fibonacci sequence?
I've seen many examples with a loop that creates the sequence in an array and checks every time if newly generated number of the sequence is equal to the input number. Is there another way?
http://www.geeksforgeeks.org/check-number-fibonacci-number/
This link details that there is a special quality about fibonacci numbers that means that a number is Fibonacci if and only if one or both of (5*n2 + 4) or (5*n2 – 4) is a perfect square.
So,
function (num) {
if (isSquare(5*(num*num)-4) || isSquare(5*(num*num)+4)) {
return true;
} else { return false; }
}
Then isSquare would just be a simple checking function.
Edit: Worth noting that while this is a much more efficient and easy way to find fibonacci numbers, it does have an upper bound. At about the 70th Fibonacci number and above, you may see issues because the numbers are too large.
function isFibonacci(num, a = 0, b = 1) {
if(num === 0 || num === 1) {
return true;
}
let nextNumber = a+b;
if(nextNumber === num) {
return true;
}
else if(nextNumber > num) {
return false;
}
return isFibonacci(num, b, nextNumber);
}
function isPerfectSquare(n) {
return n > 0 && Math.sqrt(n) % 1 === 0;
};
//Equation modified from http://www.geeksforgeeks.org/check-number-fibonacci-number/
function isFibonacci(numberToCheck)
{
// numberToCheck is Fibinacci if one of 5*n*n + 4 or 5*n*n - 4 or both
// is a perferct square
return isPerfectSquare(5*numberToCheck*numberToCheck + 4) ||
isPerfectSquare(5*numberToCheck*numberToCheck - 4);
}
for(var i = 0; i<= 10000; ++i) {
console.log(i + " - " + isFibonacci(i));
}
This will most likely fail for larger numbers though.
def is_squared(number):
temp_root = math.sqrt(number);
temp_root = int(temp_root);
return (temp_root * temp_root == number);
def check_all_fibo(test_number_list):
result_fibo_list = [];
for item in test_number_list:
if item==0 or item == 1 or item == 2:
result_fibo_list.append(item);
continue;
if is_squared(5 * item * item - 4) or is_squared(5 * item * item + 4):
result_fibo_list.append(item);
return result_fibo_list;
this is a python implementation by me. But keep in mind, the formula only works when the fib is not too large.
The Fibonacci sequence is a series of numbers where a number is the addition of the last two numbers, starting with 0, and 1. Th following js function is explaining this.
function isFabonacci(n) {
if (n === 1 || n === 0) {
return true;
}
let firstPrevNumber = n - 1;
let secondPrevNumber = n - 2;
return (firstPrevNumber + secondPrevNumber === n);
}
// isFabonacci(2) -> false
// isFabonacci(3) -> true

Categories

Resources