Recursive function always returns undefined JS [duplicate] - javascript

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

Related

How to detect math operator on current html page so that my code can assign the correct sum

I have been working on a maths project for my son, and am currently struggling to attach the correct maths sum to the correct math operator currently shown on the website.
The function mathOperator() aims to identify what math operator is currently on page and then supply the correct sum.
Then i am trying to check if the textContent of the chosen clicked answer matches that sum or not using the anonymous function below mathOpertor().
I am getting no errors in the console but the code is annoyingly just adding num1 and num2 together no mater which math operator is currently active.
I figure the problem is within the lines:
let operator = num1 + num2;
if (this.textContent == operator) { }
I figured (let operator) would be mutated to the condition that was met within the mathOperator() function, but this is not the case!
Here is my code below:
//Globals
const arrLength = 10
const randomArr = []
//push random numbers to randomArr.
for (let i=0; i<arrLength; i++) {
randomArr.push(Math.floor(Math.random() * 10));
}
//DOM targets
//first and second numbers.
const num1 = document.getElementById("num1").textContent = randomArr[0];
const num2 = document.getElementById("num2").textContent = randomArr[1];
//Multiple choice answers
let option1 = document.getElementById("option1").textContent = randomArr[2];
let option2 = document.getElementById("option2").textContent = randomArr[3];
let option3 = document.getElementById("option3").textContent = randomArr[4];
//Places the correct asnwer randomly within the 3 multiple choice answers.
const correctAnswerPosition = Math.floor(Math.random() * 3);
document.querySelectorAll(".options h1")[correctAnswerPosition].textContent = num1 + num2;
//function to decide how to calculate equation depending on what HTMLpage you are on.
function mathoperators(sum) {
if (document.querySelector(".wrapper div").children[1].textContent == "+") {
sum = num1 + num2;
} else if (document.querySelector(".wrapper div").children[1].textContent == "-") {
sum = num1 - num2;
} else if (document.querySelector(".wrapper div").children[1].textContent == "*") {
sum = num1 * num2;
} else if (document.querySelector(".wrapper div").children[1].textContent == "/") {
sum = num1 / num2;
}
}
//What do to if you pick right or wrong answer.
for (let a=0; a<document.querySelectorAll(".options").length; a++) {
//targets the 3 divs that contain random incorrect answers plus correct answer.
document.querySelectorAll(".options")[a].addEventListener("click", function() {
let operator = num1 + num2;
if (this.textContent == operator) { //problem here i don't know how to connect this to sum in math operators function.
const correct = new Audio("Sounds/correct.mp3");
correct.play();
document.querySelector(".wrapper").style.display="none";
document.querySelector(".well-done").style.display="block";
setTimeout(function() {
location.reload();
}, 3000);
} else {
const incorrect = new Audio("Sounds/incorrect.mp3");
incorrect.play();
}
mathoperators(operator)
})
}
function reload() {
reload = location.reload();
}
Thankyou for your time in advance.
# bergi, Thanks very much this is the push in the right direction I needed, the changes have been made below:
function mathoperators() {
if (document.querySelector(".wrapper div").children[1].textContent == "+") {
return num1 + num2;
} else if (document.querySelector(".wrapper div").children[1].textContent == "-") {
return num1 - num2;
} else if (document.querySelector(".wrapper div").children[1].textContent == "*") {
return num1 * num2;
} else if (document.querySelector(".wrapper div").children[1].textContent == "/") {
return num1 / num2;
}
}
//What do to if you pick right or wrong answer.
for (let a=0; a<document.querySelectorAll(".options").length; a++) {
document.querySelectorAll(".options")[a].addEventListener("click", function() {
const number = parseFloat(this.textContent)
if (mathoperators() === number) {
const correct = new Audio("Sounds/correct.mp3");
correct.play();
document.querySelector(".wrapper").style.display="none";
document.querySelector(".well-done").style.display="block";
After this I also noticed that the below needed changing so that it was equal to mathOperator() and not num1 + num2;.
//Places the correct asnwer randomy within the 3 multiple choice answers.
const correctAnswerPosition = Math.floor(Math.random() * 3);
document.querySelectorAll(".options h1")[correctAnswerPosition].textContent = mathoperators();
Thanks for your help Bergi.

making a factorial in javascript with recursion beginner

function nFactorial(n) {
// return the factorial for n
// example:
// the factorial of 3 is 6 (3 * 2 * 1)
if (n < 0){
return;
}
if (sum === undefined){
sum = 1;
}
sum *= n;
nFactorial(n - 1);
return sum;
}
nFactorial(3);
I'm doing my first stab at learning recursion in javascript. I'm trying to solve a problem where I'm making a factorial. I error I get right now is
ReferenceError: sum is not defined
Can anyone point me in the right direction? I'm feeling a little lost.
For using a product as return value, you could use tail call optimization of the recursion by using another parameter for the product (which replaces the sum in the question).
function nFactorial(n, product) {
product = product || 1; // default value
if (n < 0) { // exit condition without value
return;
}
if (n === 0) { // exit condition with result
return product;
}
return nFactorial(n - 1, n * product); // call recursion at the end of function
}
console.log(nFactorial(3));
This approach minimizes the stack length, because the last call does not extend the stack, as opposite of the standard approach of the following recursion without a product parameter.
function nFactorial(n) {
if (n < 0) {
return;
}
if (n === 0) {
return 1;
}
return n * nFactorial(n - 1);
}
console.log(nFactorial(3));
the way you write your code will result always in 0 , here is the correct way for a factorial with recursion, also you need to check if n is a number or the code will trow an error
const factorial =(n)=> {
if(isNaN(n)){
console.log("enter a number")
return 0
}
if(n === 0) {
return 1
} else {
return n * factorial(n - 1);
}
}
console.log(factorial(5));
A simple implementation:
function factorial(n) {
if (n === 1 || n === 0) {
return n;
}
return n * factorial(n-1);
}

How to return null in Javascript function

Learning Javascript functions, and having trouble with the problem below.
Modify this function so that if it’s called with 1 or 0 arguments, it returns null.
function divide(num1, num2) {
return num1 / num2;
}
let num1 = null;
let num2 = null;
let answer = divide(1,1)
console.log(answer);
TL;DR
Assuming we only need to apply a straight forward modification, I would avoid too much syntactical sugar and just write it this way:
function divide(num1, num2) {
if (arguments.length < 2) {
return null;
}
return num1/num2;
}
If we want to make it simple and elegant, I would write it this way (requires ES6 features):
const divide = (...args) => args.length < 2 ? null : args[0] / args[1];
Explanation
Improvement steps in vanilla JS (ES5 and before)
Using function arguments: this is simply an array like object that will magically appear inside your function, which contains the arguments you have passed to the function.
function divide(num1, num2) {
if (arguments.length < 2) {
return null;
}
return num1/num2;
}
While this is a great solution for the problem there are a downsides to it, if you wanted to switch to arrow function arguments object doesn't appear.
**Using ternary operator**you can farther more reduce the code by using the ternary ? which is best suitable for simple if statements
function divide(num1,num2) {
return arguments.length < 2 ? null : num1 / num2;
}
Improvement steps in ES6
Using spread (in this case it is actually called rest): the ... can be used to either collect items into an array known as rest, or expand an array known as spread.
function divide(...args) {
return args.length < 2 ? null : args[0] / args[1];
}
JavaScript will collect all the arguments passed to the function and put them into an array called args, I like this better since the reader can see where is args defined.
using arrow function: there are many difference between arrow and normal function, but many prefer it since it is shorter, and since we have a one-liner function why not use it.
const divide = (...args) => args.length < 2 ? null : args[0] / args[1];
On a final note all the previous solutions has a downside that we are only checking for length of arguments but not contents of arguments, lets assume that someone sent undefined into one of the first two arguments, you'll have 2 arguments but one of them is kinda missing and you'll get NaN since number of arguments is 2.
function divide(num1, num2) {
if (num1 === undefined || num2 === undefined) {
return null;
}
return num1/num2;
}
Demo
function divide1(num1, num2) {
if (arguments.length < 2) {
return null;
}
return num1/num2;
}
function divide2(num1,num2) {
return arguments.length < 2 ? null : num1 / num2;
}
function divide3(...args) {
return args.length < 2 ? null : args[0] / args[1];
}
const divide4 = (...args) => args.length < 2 ? null : args[0] / args[1];
const test = (cb) => {
console.log("-------->" + cb.name)
console.log(cb());
console.log(cb(1));
console.log(cb(1, 2));
console.log(cb(1, undefined));
console.log(cb(1, null));
console.log(cb(1, 2, 3));
};
test(divide1);
test(divide2);
test(divide3);
test(divide4);
Peep this.
function divide(num1, num2) {
if(arguments.length < 2) return null;
return num1 / num2;
}
The arguments object is available in all (non-arrow) function and represents all the arguments passed into the function. It has a length property that tells you how many arguments there are.
Technically passing in null would be calling it with two arguments so your example doesn't exactly represent that anyway. If you want an answer that's safe for arrow functions as well (they don't have the arguments object) you could just check to see if the second argument is a number. This would catch a lot of it.
function divide(num1, num2) {
if (typeof num2 !== 'number') return null;
return num1 / num2;
}
If you wanted to handle the edge case that the first passed argument was undefined you could check both arguments.
function divide(num1, num2) {
if (typeof num1 !== 'number' || typeof num2 !== 'number') return null;
return num1 / num2;
}
If you want to get fancy it could be a one line arrow:
const divide = (num1, num2) => typeof num2 !== 'number' ? null : num1 / num 2;

Finding remainder of two number without modulus

Instructions: Write a function called "modulo". Given 2 numbers, "modulo" returns the remainder after dividing num1 by num2.
This is my code so far. When I run it on repl.it it gives the correct remainder, but when I submit the program it goes into an infinite loop and I have no clue why. I figure the return functions in the for loop would just automatically exit it. Any help would be appreciated, thanks. Basically I'm adding number2 constantly until it either hits number 1 or goes higher than it. If it goes higher, I subtract number 2 once, and find the difference.
function modulo(num1, num2) {
if(num1 === 0) {
return 0;
}
if(num2 === 0) {
return NaN;
}
if(isNaN(num1) === true || isNaN(num2) === true) {
return NaN;
}
var i = 0;
for( i = 0; i <= num1;) {
i += num2;
if(i === num1) {
return 0;
}
else if(i > num1) {
i = i - num2;
console.log(i, num1);
return num1 - i;
}
}
}
var output = modulo(25, 4);
console.log(output);
function modulo(num1, num2) { var div = num1/num2;
var remainder = div - Math.floor(div); // gives the decimal point value left out from the division
return Math.round(remainder * num2); // multiplies the remainder with num2 and gives a whole number value
}
This is pretty simpler and should work all times
I'm not entirely sure where the infinite loop is showing up; I've plugged your code into console and I can call the function just fine. What site are you using to validate?
Also, without altering too much of your exercise, I'd like to point out a couple of tiny areas where you can consolidate your code to improve readability:
if(num2 === 0) {
return NaN;
}
if(isNaN(num1) === true || isNaN(num2) === true) {
return NaN;
}
can be distilled down into
if (num2 === 0 || isNaN(num1) || isNaN(num2)) {
return NaN;
}
because in JavaScript, booleans work in such a way that everything with a real value is considered to be true, i.e. isNaN(num1) and isNaN(num2) are "true" by default.
Also, remember that you can use all your assignment operators; it's completely optional, but since you used one (i += num2;), I figured I'd point out that you could use another further down the code (i -= num2;).
Happy coding! :)
It could be another option:
function modulo(num1, num2) {
if(isNaN(num1) || isNaN(num2) ) {
return NaN;
}
var strResult = (num1/num2).toString();
var decimalPart =
parseFloat(strResult.substr(strResult.indexOf(".")));
var remainder = Math.round(decimalPart*num2);
return remainder;
}
console.log(modulo(77,9), (77%9)); // 5
console.log(modulo(549,123), (549%123)); // 57
console.log(modulo(33,6), (33%6)); // 3

Javascript find max number from 3 inputs

I've just began Javascript in college. One task is to define and call a function to find the maximum number from 3 numbers entered by the user. I know there is a max() function but we were told to do it manually using if and else if.
I'm going wrong somewhere as you can see. It's just telling me the max is 0 everytime.
function maxNum(num1, num2, num3){
var max = 0;
if(num1 > num2){
if(num1 > num3){
num1 = max;
}
else{
num3 = max;
}
}
else{
if(num2 > num3){
num2 = max;
}
}
return max;
}
for(i=0;i<3;i++){
parseInt(prompt("Enter a number"));
}
document.write(maxNum());
Or you can use ES6 syntax, to compute largest of three numbers in easier way,
const largest = a => F = b => G = c => ((a > b && a > c) ? a : (b > a && b > c) ? b : c)
console.time()
console.log(largest(53)(30907)(23333))
console.timeEnd()
One problem you have is that you do not save the number the user inputs. You prompt them, parse it as an int and then nothing. You have to pass the 3 numbers into maxNum()
Here is a working example that uses proper left hand assignment and saves the number. Also it is a good idea to use >= instead of > because the user can enter 2 of the same number
function maxNum(num1, num2, num3){
var max = 0;
if((num1 >= num2) && (num1 >= num3)){
max = num1;
}
else if((num2 >= num1) && (num2 >= num3)){
max = num2;
}
else{
max = num3;
}
return max;
}
var arr = [];
for(i=0;i<3;i++){
arr[i] = parseInt(prompt("Enter a number"));
}
document.write(maxNum.apply(this, arr));
easiest way:
function maxNum(num1, num2, num3){
var tmp = 0;
if(num1 < num2 && num3 < num2) {
tmp = num2;
} else if(num3 < num1){
tmp = num1;
} else {
tmp = num3;
}
return tmp;
}
var arr = [];
for(var i = 0; i < 3; i++) {
arr[i] = prompt("Enter a number");
}
console.log(maxNum.apply(this, arr));
First in javascript and most modern programming language assignment like a = b copies the value of b into the variable a. It is not equivalent to b = a (which copies the value of a into the variable b). It's common to write a = 1, but a syntax error in most languages to write 1 = a. Thus, you don't want to write num1 = max, but instead write max = num1.
Second, your logic is incorrect as it won't treat the case maxNum(1,2,3) correctly. (Work through the logic when num1 < num2 and num2 < num3. The following code would work:
function maxNum(num1, num2, num3){
var max = 0;
if(num1 > num2){
if(num1 > num3){
max = num1;
}
else{
max = num3;
}
}
else{
if(num2 > num3){
max = num2;
} else {
max = num3;
}
}
return max;
}
Granted, I would probably write something like
function max3num(num1, num2, num3) {
var max_so_far = num1;
if (num2 > max_so_far) {
max_so_far = num2;
}
if (num3 > max_so_far) {
max_so_far = num3;
}
return max_so_far;
}
as the logic is very clear and it will be easy to extend to a max function with a larger number of elements to compare if necessary. (Adding in a for loop could make it variadic fairly easily). It is straightforward to see the logic works, because we start with the first element being the maximum so far (max_so_far), then consider if the second element is larger -- if so we assign that as max_so_far, and keep continuing until we have compared all the elements to the max_so_far. After we have considered each element once, we then return the max_so_far which will now be the maximum of all of them.
No real need for a function here, just compare them as the come in!
var max = 0;
for(var i=0;i<3;i++){
var val = parseInt(prompt("Enter a number"));
max = max > val ? max : val;
}
alert(max);
The updated direct answer is this :
function maxNum(num1, num2, num3){
return [num1, num2, num3].sort(function (a, b) { return b - a })[0];
}
If written like this, it can easily be modified to take any amount of numbers by passing it an array of said numbers.
var numArray = [num1, num2, num3, num4, ...];
function maxNum(numArray){
return numArray.sort(function (a, b) { return b - a })[0];
}
The details :
Take an array :
[5,42,16]
Now sort it.
[5,42,16].sort()
But this wont work because javascript .sort requires a function to be passed in. This function tells it how to sort the array.
This will sort it highest to lowest, e.g. a is less then b.
function (a, b) { return b - a }
This will sort it lowest to highest, e.g. b is less then a.
function (a, b) { return a - b }
So we add it in :
[5,42,16].sort(function (a, b) { return b - a })
But this returns the sorted array, not the maximum number.
So we pick the first element in the array :
[5,42,16].sort(function (a, b) { return b - a })[0]
Lastly, you can pull out the sort function. This is mostly for demo purposes though.
var maxSorter = function (a, b) { return b - a };
function maxNum(numArray){
return numArray.sort(maxSorter)[0];
}
//Raihan
// program to find the largest among three numbers
// take input from the user using Prompt
let num1 = parseFloat(prompt("Enter first number: "));
let num2 = parseFloat(prompt("Enter second number: "));
let num3 = parseFloat(prompt("Enter third number: "));
let largest = Math.max(num1, num2, num3);
// display the result
document.write("The largest number is " + largest);
**//another way**
const num1 = parseFloat(prompt("Enter first number: "));
const num2 = parseFloat(prompt("Enter second number: "));
const num3 = parseFloat(prompt("Enter third number: "));
// check the condition
if(num1 >= num2 && num1 >= num3) {
document.write("Largest Number : " + num1)
}
else if (num2 >= num1 && num2 >= num3) {
document.write("Largest Number : " + num2)
}
else {
document.write("Largest Number : " + num3)
}

Categories

Resources