Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed last month.
Improve this question
I'm studying recursive functions, and one I came across is the greatest common divisor. I was working through a very long and complicated piece of code that was going nowhere, and when I looked up the solution, I see it's super short:
function gcd(num1, num2) {
if (num2 === 0) {
return num1;
}
return gcd (num2, num1 % num2);
}
I'm struggling to wrap my brain around how this works in the recursive return function call. Num2 becomes the first parameter for some reason, and how does the second parameter work? Is num1 % num2 the new value of num1? How is num2 going to get to 0? I don't see how it's value changes.
I'm struggling to wrap my brain around how this works in the recursive return function call. Num2 becomes the first parameter for some reason, and how does the second parameter work? Is num1 % num2 the new value of num1? How is num2 going to get to 0? I don't see how it's value changes.
num2 becomes the first argument to a new function call. We're not changing the value of the num1 we have, but telling JS that in the next call, the first parameter will get the value from what's currently in num2. Similarly, we calculate the next value of the second parameter as num1 % num2. (To understand how the math works, you might read up on the Euclidean algorithm, but the basic point is that for positive integers a and b, gcd (a, b) is precisely the same as gcd (b, a % b).)
So now we have two new numbers to test, and we call gcd with these two numbers, and, crucially, when that function returns, we return its result as our own:
return gcd (num2, num1 % num2);
//^^^^^^
This process stops when num2 is zero. Then we can simply return num1.
We can add some logging to your function, using an additional parameter, depth to track the recursion depth, initializing it at first to 0. That could give us output like this:
in gcd (120, 42)
num2 <> 0
value of num1 for the next call is num2: 42
calculating value of num2 for next call: num1 % num2: 120 % 42 ==> 36
calling gcd (42, 36)
in gcd (42, 36)
num2 <> 0
value of num1 for the next call is num2: 36
calculating value of num2 for next call: num1 % num2: 42 % 36 ==> 6
calling gcd (36, 6)
in gcd (36, 6)
num2 <> 0
value of num1 for the next call is num2: 6
calculating value of num2 for next call: num1 % num2: 36 % 6 ==> 0
calling gcd (6, 0)
in gcd (6, 0)
num2 == 0
returning 6
returning 6
returning 6
returning 6
which you can see by expanding and running this snippet:
const log = (depth, s) => console .log (' ' .repeat (depth) + s)
function gcd (num1, num2, depth = 0) {
log (depth, `in gcd (${num1}, ${num2})`)
if (num2 === 0) {
log (depth, `num2 == 0`)
log (depth, `returning ${num1}`)
return num1
}
log (depth, `num2 <> 0`)
log (depth, `value of num1 for the next call is num2: ${num2}`)
log (depth, `calculating value of num2 for next call: num1 % num2: ${num1} % ${num2} ==> ${num1 % num2}`)
log (depth, `calling gcd (${num2}, ${num1 % num2})`)
const result = gcd (num2, num1 % num2, depth + 1)
log (depth, `returning ${result}`)
return result
}
console .log (gcd (120, 42))
.as-console-wrapper {max-height: 100% !important; top: 0}
It might be tricky to understand without going through examples with pen and paper. num1 % num2 becomes the new value of num1 for each recurring call of the function.
If you try it with gcd(14,4),
4 != 0, 14 % 4 = 2 then next call is gcd(4, 2).
2 != 0, 4 % 2 = 0 then next call is gcd(2, 0).
0 == 0 then greatest common divisor of 14 and 4 is 2. This value is returned all the way up the call stack.
Another example with gcd(5,3):
3 != 0, 5 % 3 = 1 then next call is gcd(3,1).
1 != 0, 3 % 1 = 0 then next call is gcd(1, 0).
0 == 0 then greatest common divisor of 5 and 3 is 1.
An exact equivalent but more clear (to me) code is:
function gcd(num1, num2) {
if (num2 === 0) return num1;
else return gcd (num2, num1 % num2);
}
Now do a few by hand:
console.log(gcd(15, 6));
num2 (6) is not 0 so return gcd(6, 15%6) or gcd(6,3)
num2 (3) is not 0 so return gcd(3, 6%3) or gcd(3,0)
num2 (0) is now 0 so return 3
console.log(gcd(6, 15));
num2 (15) is not 0 so return gcd(15, 6%15) or gcd(15,6)
num2 (6) is not 0 so return gcd(6, 15%6) or gcd(6,3)
num2 (3) is not 0 so return gcd(3, 6%3) or gcd(3,0)
num2 (0) is now 0 so return 3
Or, you can let the code tell you what's going on:
This is for factorial(n) but you could do the same for gcd():
The important point is that "k" is different for each call:
console.log("FINALLY, factorial(5) = ", factorial(5));
function FACTORIAL(num) { // this is without the BS
if (num == 1) return 1;
else return num * factorial(num-1);
}
function factorial(num) { // this shows all
console.log("getting factorial(" + num + ")");
if (num == 1) {
console.log("factorial of 1 is just 1");
return 1;
} else {
console.log("need to get factorial(" + (num-1) + ")");
let k = num * factorial(num - 1);
console.log("got factorial(" + num + ") = " + k);
return k;
}
}
Related
It's a function that returns the sum of all of the odd Fibonacci numbers that are less than or equal to the given number.
I am stuck with the last of the tests, all of them work besides this one.
sumFibs(75025) should return 135721, I've been trying many things but none worked.
function sumFibs(num) {
let f1 = 1;
let f2 = 1;
let fiboNums = [];
while (f1 <= num && f2 <= num) {
if (f1 % 2 !== 0) fiboNums.push(f1);
if (f2 % 2 !== 0) fiboNums.push(f2);
f1 += f2;
f2 += f1;
}
return fiboNums.reduce((pV, cV) => pV + cV);
}
console.log(sumFibs(75025));
Instructions: Given a positive integer num, return the sum of all odd Fibonacci numbers that are less than or equal to num.
The first two numbers in the Fibonacci sequence are 1 and 1. Every additional number in the sequence is the sum of the two previous numbers. The first six numbers of the Fibonacci sequence are 1, 1, 2, 3, 5 and 8.
For example, sumFibs(10) should return 10 because all odd Fibonacci numbers less than or equal to 10 are 1, 1, 3, and 5.
I tried changing the boolean statement of the while loop as well as the if-statements by adding a condition that evaluates to true if f1 or f2 are less than or equal to the given number
The issue is that once f2 is bigger than num, the loop ends even though f1 is not bigger than num, therefore skipping the last relevant number in the series and excluding it from the results. Here's a revised version that fixes the problem:
function sumFibs(num) {
let f1 = 1;
let f2 = 1;
let fiboNums = [];
while (f1 <= num) {
if (f1 % 2 !== 0) fiboNums.push(f1);
if (f2 <= num && f2 % 2 !== 0) fiboNums.push(f2);
f1 += f2;
f2 += f1;
}
return fiboNums.reduce((pV, cV) => pV + cV);
}
console.log(sumFibs(75025));
I am trying to learn python and I have tried to convert a code snippet in js to python. I have created a function in js to calculate GCD as follows:
// program to find the GCD of two integers
let gcd
function GCD() {
// take input
const number1 = prompt('Enter a first positive integer: ')
const number2 = prompt('Enter a second positive integer: ')
// looping from 1 to number1 and number2
for (let i = 1; i <= number1 && i <= number2; i++) {
if( number1 % i == 0 && number2 % i == 0) {
gcd = i
}
}
// display the gcd
document.write(`GCD of ${number1} and ${number2} is ${gcd}.`)
}
GCD()
If I supply the first integer as 9 and the second integer of 3, I get the GCD as 3.
I have tried to convert this to a python program as follows:
def gcd():
gcd = 0
num1 = int(input("Enter a first positive integer: "))
num2 = int(input("Enter a second positive integer: "))
for i in range(1, i<=num1 and i<=num2):
if num1 % i == 0 and num2 % i == 0:
gcd = i
print(f"GCD of: {num1} and: {num2} is {gcd}")
gcd()
But I don't know how to get the for loop in python quite right. If I change the for statement to:
def gcd():
gcd = 0
num1 = int(input("Enter a first positive integer: "))
num2 = int(input("Enter a second positive integer: "))
for i in range(1, num1 and num2):
if num1 % i == 0 and num2 % i == 0:
gcd = i
print(f"GCD of: {num1} and: {num2} is {gcd}")
gcd()
and I give the same input as before of 9 and 3, I get GCD of 1
You can't have an equivalent syntax as i <= number1 && i <= number2 as it is a boolean expression that works as stop condition which is checked at every iteration.
While a for loop in python code generates values with boudaries, to do the same, iterate until the lowest value:
for i in range(1, min(num1, num2) + 1):
if num1 % i == 0 and num2 % i == 0:
gcd = i
To use the condition of the JS code, you need a while loop:
i = 1
while i <= num1 and i <= num2:
if num1 % i == 0 and num2 % i == 0:
gcd = i
i += 1
this is a solution based on while loop
def gcd():
gcd=0
num1 = int(input("Enter a first positive integer: "))
num2 = int(input("Enter a second positive integer: "))
i = 1
while(i <= num1 and i <= num2):
if(num1 % i == 0 and num2 % i == 0):
gcd = i
i = i + 1
print("GCD : ", gcd)
gcd()
This question already has answers here:
Return value from recurring function
(2 answers)
Closed 3 years ago.
I've managed to create a script that has to count the LCF (Largest Common Factor ). My task was to create the script for exact this algorithm, so, I couldn't choose another one. But I always get undefined on return. What am I doing wrong?
I've checked the whole function with the console.log and it works right. It founds the right LCF, comes to if statement where it should return the variable value and this value even the number.
I've checked the value of this variable, I've checked the type of this var, everything should be ok, but it doesn't work.
const checking = (num1, num2, t) => {
if (num1 % t === 0) {
if (num2 % t === 0) {
return t;
} else {
checking(num1, num2, t - 1);
}
} else {
checking(num1, num2, t - 1);
}
}
const bruteforce = (num1, num2) => {
//Checking if numbers are equal
if (num1 === num2) return num1;
//If no, defining minimal one
let t = 0;
num1 > num2 ? t = num2 : t = num1;
let answer = checking(num1, num2, t);
}
I expect the output of var t value, but the actual output is always undefined
When using a recursive function you should always return the call so the answer can travel up the stack:
const checking = (num1, num2, t) => {
if (num1 % t === 0) {
if (num2 % t === 0) {
return t;
} else {
return checking(num1, num2, t - 1);
}
} else {
return checking(num1, num2, t - 1);
}
}
When you recursive function recurses, it doesn't return anything. It just calls itself:
checking(num1, num2, t - 1);
But does nothing with the result of that call. Return that result:
return checking(num1, num2, t - 1);
For a homework assignment, I need to return the remainder after dividing num1 by num2 WITHOUT using the built-in modulo (%) operator. I'm able to get most tests to pass with the following code, but I'm stuck on how to account for -/+ signs of the given numbers. I need to carry over whichever sign is on num1, and also return a positive number if the num2 is negative - it's blowing my mind how to do this... :) Any clarity would be greatly appreciated! I'm not exactly looking for the straight up answer here, more that I seem to be missing something obvious... Maybe I need a new approach?
function modulo(num1, num2) {
if (num1 === 0) {
return 0;
}
if (num2 === 0 || isNaN(num1) || isNaN(num2)) {
return NaN;
}
if (num1 < num2) {
return num1;
}
if (num1 > 0 && num2 > 0) {
var counter = num1;
while (counter >= Math.abs(num2)) {
counter = counter - num2;
}
return counter;
}
}
var output = modulo(25, 4);
console.log(output); // 1
If you think about the mathematical process to calculate modulus you might be able see how you can do this without having to resort to a bunch of case statements. Instead think of it this way, you're just calculating a remainder:
Given 2 numbers a and b, you can compute mod(a,b) by doing the following:
q = a / b; //finding quotient (integer part only)
p = q * b; //finding product
remainder = a - p; //finding modulus
Using this idea, you should be able to transfer it to JS. You said you're not looking for the straight up answer so that's all I'll say!
Edit: here is the code, like I said in the comments it's exactly the pseudocode I posted above:
function modulo(a,b){
q = parseInt(a / b); //finding quotient (integer part only)
p = q * b; //finding product
return a - p; //finding modulus
}
This will return the exact same values as using %
You might be overthinking this. You basically stated the solution in your question:
I need to carry over whichever sign is on num1, and also return a positive number if the num2 is negative
The second part isn't accurate, but I suspect you just misspoke. A positive number should be returned when num2 is negative unless num1 is negative.
At any rate, the important takeaway is that if num1 is negative the result will be negative, and otherwise the result will be positive. The sign of num2 is discarded.
Starting the code you've written (which others will be quick to point out isn't the simplest solution), the fix is to compute the remainder using both numbers' absolute values, and then apply num1's original sign to the result.
function modulo(num1, num2) {
var sign = num1 < 0 ? -1 : 1;
var dividend = Math.abs(num1);
var divisor = Math.abs(num2);
if (dividend === 0) {
return 0;
}
if (dividend === 0 || isNaN(dividend) || isNaN(divisor)) {
return NaN;
}
if (dividend < divisor) {
return sign * dividend;
}
var counter = dividend;
while (counter >= divisor) {
counter = counter - divisor;
}
return sign * counter;
}
console.log( 25 % 4, modulo( 25, 4));
console.log(-25 % 4, modulo(-25, 4));
console.log( 25 % -4, modulo( 25, -4));
console.log(-25 % -4, modulo(-25, -4));
.as-console-wrapper{min-height:100%;}
This is the basic formula:
dividend = divisor * quotient + remainder
From this equation you can calculate the remainder.
hello I'm new learning recursive but i don't know to solve with this problem,
cause this one using 2 parameters, I don't know how to return with 2 arguments.
this is the normal loop ,not a recursive yet cause i dunno how to change it to recursive:
function deret2(num,num2){
var tampung = 1;
for (var i= num; i >= 1 ; i-= num2){
tampung = tampung * i ;
}
console.log(tampung);
}
deret2(12,5); //12* 7 * 2 = 168
Edit : the recursive I made :
function deret(num,num2) {
//var tampung = 1;
if (num <= 0) { // terminal case
return 1;
} else
{ // block to execute
return num * deret(num-num2,num2);
}
};
deret(12,5);
it won't work cause number* deret(2 arguments here) ?? that's why i don't know how to make this a recursive with 2 parameters, how could u save it and multiply it against 2 arguments ?
You could use a recursive function with check.
You need for a recursive function a check if the recursion should stop, or if the function should call again with same or changed paramters. Then you need a value to return in both cases.
Rule of thumb, for multiplications return as last value 1 and for addition 0.
num num2 return
--- ---- ------------------
12 5 12 * deret2(7, 5)
7 5 7 * deret2(2, 5)
2 5 2 * deret2(-3, 5)
-3 5 1
function deret2(num, num2) {
return num >= 1 ? num * deret2(num - num2, num2) : 1;
}
console.log(deret2(12, 5)); //12* 7 * 2 = 168
With if syntax.
function deret2(num, num2) {
if (num >= 1) {
return num * deret2(num - num2, num2);
} else {
return 1;
}
}
console.log(deret2(12, 5)); //12* 7 * 2 = 168
Bonus: The shortest version.
function deret2(num, num2) {
return +(num < 1) || num * deret2(num - num2, num2);
}
console.log(deret2(12, 5)); //12* 7 * 2 = 168
A recursive function calls itself, and with an extra parameter, we don't need to keep track of a mutating variable. Looping and recursion are very closely related, to the point where the transformation is mechanical.
function deret2(num,num2,tampung){
if (num >= 1) {
deret2(num - num2, num2, tampung * num);
} else {
console.log(tampung);
}
}
deret2(12,5,1); //12* 7 * 2 = 168
Note that we're passing in the initial value of tampung directly now, instead of encoding it into the recursion. If you don't want the caller to pass the base value of tampung, it's fairly common to make a helper function to encode that base case and then start the recursion.
A recursive function should have itself declared inside the function AND a stop if condition:
function deret2(startNumber,step){
if(startNumber>= 1){
return startNumber * deret2(startNumber - step, step);
}else{
return 1;
}
}
deret2(12,5); //12* 7 * 2 = 168