why doesn't this backtracking recursion go to other branches? - javascript

Given an array, and a goal (number), I have to determine if it is possible to reach goal by adding elements from the array.
Here is my code (in javascript), and some results:
function check(goal,array) {
function add(sum, array) {
if (sum == goal)
return true;
else if ((sum > goal)||(!array[0]))
return false;
else
console.log(sum); // check where we are
return add(sum + array.shift(),array) || add(sum,array);
}
return add(0,array);
}
What I expect to happen to the stack of add() after calling check(6,[1,3,5])
add(0,[1,3,5]) // log 0
add(1,[3,5]) //log 1
add(1+3,[5]) //log 4
add(1+3+5,[]) //return false
add(1+3,[]) //return false
add(1,[5]) //log 1
add(1+5,[]) //return true
add(1,[])
add[0,[3,5])
add(0+3,[5])
add(0+3+5,[])
add(0+3,[])
add(0,[5])
add(0+5,[])
add(0,[])
Actual results:
check(6,[1,3,5])
false
0
1
4
check(3,[1,3,5])
false
0
1
1
It never leaves the first branch!
Why ?
Edit:
Ok, based on the suggestions, I guess it's better to avoid passing array as an argument:
function check(goal,array) {
function add(sum, i) {
if (sum == goal)
return true;
else if ((sum > goal)||(i==array.length))
return false;
else
console.log(sum);
return add(sum + array[i],i+1) || add(sum,i+1);
}
return add(0,0);
}
It works fine here.

It's the same array that's passed around, and after the first branch it'll become empty so the recursion will finish. Try it with a copy:
function check(goal,array) {
function add(sum, array) {
if (sum == goal)
return true;
else if ((sum > goal)||(!array[0]))
return false;
else
print(sum);
array = array.slice();
return add(sum + array.shift(),array) || add(sum,array);
}
return add(0,array);
}

Related

Function that takes a number as an argument and returns a boolean javascript

I am new to coding and I have this exercise where I have to write a function that takes a number as argument and returns a boolean. This is the code I wrote but is not working and I am getting the warning
"The function should only have a return statement in its body. You can evaluate a boolean expression an return immediately its value"
var even = function(x) {
if ((x % 2) === 0) {
return true;
} else
return false;
};
The response you get from the code submission has an important point:
The expression (x%2)===0 is already a boolean, so you can return that expression:
return x%2 === 0;
In general you should avoid this pattern:
if (some_boolean_expression) {
return true;
} else {
return false;
}
... since the boolean you return is exactly the same as the boolean expression that is evaluated in the if condition. So it should be just:
return some_boolean_expression;
you can just write your function like this
var even = function(x)
{
return x % 2 === 0
}
var even = function(x) {
if (typeof x === "number") {
if (x % 2 === 0) {
return true
} else {
return false
}
} else {
return false
}
}
This covers all the edge cases

Why does function return undefined when it explicitly is told to return true?

I was trying to solve the following coding exercise.
We have two special characters. The first character can be represented
by one bit 0. The second character can be represented by two bits (10
or 11).
Now given a string represented by several bits. Return whether the
last character must be a one-bit character or not. The given string
will always end with a zero.
example:
Input: bits = [1, 0, 0] Output: True
Below is my solution for the above challenge. Why is this returning undefined? If I use [1,0,1,0] as input, it should return true but I am getting undefined. I am explicitly writing true in the return statement and not the results of a variable.
var isOneBitCharacter = function(bits) {
console.log(bits);
var length = bits.length;
if (length == 1) {
return true;
}
if (length == 0) {return false;}
if (length == 2 && bits[0] === 1) {
return false;
}
if (bits[0] === 1) {
isOneBitCharacter(bits.slice(1));
} else {
isOneBitCharacter(bits.slice(2));
}
};
isOneBitCharacter([1,0,1,0]);
I guess you are missing returns. Here is adjusted code:
var isOneBitCharacter = function(bits) {
console.log(bits);
var length = bits.length;
if (length == 1) {
return true;
}
if (length == 0) {return false;}
// added return here and next statements
if (length == 2 && bits[0] === 1) {
return false;
}
if (bits[0] === 1) {
return isOneBitCharacter(bits.slice(1));
} else {
return isOneBitCharacter(bits.slice(2));
}
};
isOneBitCharacter([1,0,1,0]);

Javascript program yields undefined (recursion) [duplicate]

This question already has answers here:
Simple Recursive Javascript Function Returns Undefined
(2 answers)
Closed 4 years ago.
Hello I am a newbie learning Js
I am trying to learn about recursion but I stuck in here
var isEven = (number) =>{
number = Number(number)
if(number === 0){
console.log('it is even')
return true;
}
else if(number === 1){
return false;
}
else{
number = number - 2;
isEven(number);
}
}
console.log(isEven(50) === true)
why the end result becomes undefined? Thank you for the help
Add return in recursion call:
function isEven(number){
number = Number(number)
if(number === 0){
console.log('it is even');
return true;
}
else if(number === 1){
return false;
}
else{
number = number - 2;
return isEven(number);
}
}
console.log(isEven(50));
You must use return in recursion call .If u do not use return the isEven(50) function will run but do not return isEven(48) so your function isEven(50) get undefined.So always use return.
Example
function factorial( n ) {
if ( n === 1 ) {
return 1;
}
return n * factorial( n - 1 );
}
In above example you can when we call factorial(n-1); it will return (n-1)*factorial(n-2); but if u remove the return then result is undefined as factorial(n-1); do not return anything.
Always remember in recursion focus is on returning function again and again till we get the result.

How can I extend this AngularJS filter to sort alphabetically by object property?

I have an array of objects called cases, with 3 methods of sorting: by length of case.keywords, or alphabetically by case.reason or case.category. The selected sort order is stored on $scope.currentSort, which is switched with a select drop-down.
Here is my filter so far, which reads the value of $scope.currentSort and calls the relevant sort function. It currently works for the default/keyword sort. All the console.logs are triggered when expected.
How do I return an alphabetical sort for the Reason & Category sorts?
.filter('orderBySelected', function() {
function compareKeywords(a, b) {
//Sorts by length of array keywords
if (a.keywords && b.keywords) {
if (a.keywords.length < b.keywords.length)
return 1;
if (a.keywords.length > b.keywords.length)
return -1;
return 0;
} else if (a.keywords && !b.keywords) {
return -1;
} else {
return 1;
}
}
function compareReason(a, b) {
//What do I put here to sort alphabetically by property .reason?
}
return function (input, currentSort) {
//Input is all the cases. Check which sort is desired based on value of currentSort:
if (currentSort.value == 1) {
console.log("Current sort is default :" + currentSort.name)
return input.sort(compareKeywords); //calls that sorting method above
} else if (currentSort.value == 2) {
console.log("Current sort is Reason: " + currentSort.name)
return input.sort(compareReason)
} else if (currentSort.value == 3) {
console.log("Current sort is Category: " + currentSort.name)
}
}
});
This works:
function compareReason(a, b) {
if (a.reason && b.reason) {
var nameA=a.reason.toLowerCase(), nameB=b.reason.toLowerCase()
if (nameA < nameB) //sort string ascending
return -1
if (nameA > nameB)
return 1
return 0 //default return value (no sorting)
} else if (a.reason && !b.reason) {
return -1;
} else {
return 1;
}
}

Function supposed to return a boolean returns undefined

Trying to come up with a function to check if a number is prime and I'm running into trouble. I'm sure there's a simpler way to do this, but why would this function not return false, for the number 9? It returns false for even numbers but for any other type of composite number it returns undefined, but since it prints NOT PRIME it should also be returning false.
function isPrime(n, i) {
document.writeln(i);
var nextNum = i + 1;
var number = n;
if (i < n) {
if ((n % i) === 0) {
document.writeln("NOT PRIME");
return false;
} else {
document.writeln(nextNum);
isPrime(number, nextNum);
}
} else if (i === n) {
document.writeln("Recursion ends");
return true;
} else {
document.writeln("Confused" + typeof i + typeof n);
}
}
You need to return the value of the recursive call, i.e., change
isPrime(number, nextNum);
to
return isPrime(number, nextNum);
You are missing a return in this branch after the recursive call to isPrime:
if ((n % i) === 0) {
document.writeln("NOT PRIME");
return false;
} else {
document.writeln(nextNum);
isPrime(number, nextNum);
}
I think that you want to change it to:
if ((n % i) === 0) {
document.writeln("NOT PRIME");
return false;
} else {
document.writeln(nextNum);
return isPrime(number, nextNum);
}
Because you aren't returning anything in that branch, the true/false calls are disappearing.
It should just need one parameter to check if prime.
Try this out:
function isPrime(num){
// An integer is prime if it is not divisible by any prime less than or equal to its square root
var squareRoot = parseInt(Math.sqrt(num));
var primeCountUp = function(divisor){
if(divisor > squareRoot) {
// got to a point where the divisor is greater than
// the square root, therefore it is prime
return true;
}
else if(num % divisor === 0) {
// found a result that divides evenly, NOT prime
return false;
}
else {
// keep counting
return primeCountUp(++divisor);
}
};
// start # 2 because everything is divisible by 1
return primeCountUp(2);
}
Adding the high of the "square root" from here

Categories