I understand the first part of the if, but isn't the second part stating "since 'n' is not equal to zero, return 'n' in the even function modified with the logical NOT(!) operator."?
Doesn't that return 4 if I were to pass 5 as the argument to fn();?
var fn = function even (n)
{
if (n === 0)
{
return true;
}
else
{
return !even(n - 1)
}
};
fn(5); //=> false
even(n) is always the opposite of even(n-1).
As even(0) is true, even(1) is false and so on : all multiples of 2 give true and odd numbers give false.
A simple way to see it might be to log [0,1,2,3,4,5].map(even).
Just in case you were really looking for a way to know if a positive integer is even, the solution you show is very very inefficient and the recursion results in a call stack explosion for any big number. Here's a more reasonable solution :
function even(n){
return !(n%2);
}
Not the even function is modified with the boolean NOT, but the NOT is applied on the result of invoking the even function with n - 1. Not 4 is returned, but !(even(4)).
If we simplify the function to
function even(n) { return n==0 || !even(n-1); }
we get the following expansion of your call:
even(5)
5==0 || !even(5-1)
!even(4)
!(4==0 || !even(4-1))
!!even(3)
!!(3==0 || !even(3-1))
!!!even(2)
!!!(2==0 || !even(2-1))
!!!!even(1)
!!!!(1==0 || !even(1-1))
!!!!!even(0)
!!!!!(0==0 || !even(0-1))
!!!!!(true || !even(0-1))
!!!!!true
!!!!false
!!!true
!!false
!true
false
I think it's best explained by showing what would happen without the ! in the return. If we have:
var fn = function even (n){
if (n === 0) return true;
else return even(n - 1)
}
It's always going to return true, because it will eventually hit 0. If we call fn(3), the call stack will look something like this:
fn(3)
-> fn(2)
-> fn(1)
-> fn(0)
true
true
true
true
true
The ! in the recursive call negates the previous value, so the new call stack looks like:
fn(3)
-> fn(2)
-> fn(1)
-> fn(0)
true
!true
!(!true)
!(!(!true))
!(!(!(!true)))
!(!(!(!true))) === true
This is an inefficient but valid way of recursively calculating whether a positive integer (see note at end) is even. Basically, each time you're checking a non-zero number, you rely on the fact that whether n is even is the same as whether n-1 is not even. So even(5) is the same as !even(4), and !even(4) is the same as !!even(3) (or even(3)). So by the end, you're calculating even(5) as !!!!!even(0). We know even(0) returns true, so since !! negates itself, we're left with !true, or false.
As per the comments - since this is a recursive function that expects to end when it reaches zero, it will cause an infinite recursion if it were given an input value which was a good way to check whether a number is even.
Related
I know this might be basic and simple but since I am self-learning, so I wanted to know what was wrong and I thought this is the best place to learn from.
I am trying to write a recursive code that returns true or false. The condition to check is if the set of words can make the given target word.
The error I keet getting is :
if (targetString.indexOf(dictionary[i]) == 0) {
^
RangeError: Maximum call stack size exceeded
at String.indexOf (<anonymous>)
I am pretty sure that the problem with code is in a way I am returning because I always find it confusing.
my code is:
let targetString = "furniture";
let dictionary = ["fur", "ure", "nit"];
const tableData = {};
const canConstructRecursive = (targetString, dictionary) => {
if (targetString == "") {
return true
}
for (let i = 0; i < dictionary.length; i++) {
if (targetString.indexOf(dictionary[i]) == 0) {
shorterTargetString = targetString.slice(0, dictionary[i].length);
return canConstructRecursive(shorterTargetString, dictionary);
}
}
return false;
}
console.log(canConstructRecursive(targetString, dictionary));
I am learning recursion and from time to time I feel I don't understand the logic of return to next/previous recursive call.
I would really appreciate it if someone could help me with what I am doing wrong and change my way of thinking.
My way of thinking is that:
the base case is returned if it is reached at that stage otherwise loop go through all the option and the inner node or upper stack need to return value to lower stack so I am doing return canConstructRecursive() inside for. If even in all options which is all iteration of for loop, it is not returned, there is return false at the end.
Thank you in advance
The reason is that although your variable is named shorterTargetString, it is not guaranteed to be really shorter. If i is the index of the shortest word in dictionary, then there is no way your string will ever get shorter by recursing with it.
The mistake is that the slice should not start at 0, but after the part that was matched, so remove the first argument from the slice call.
This will solve the stack overflow error.
Secondly, if the recursive call returns false you should not give up, but keep trying with the next word. So only return out of the loop when you got true from recursion:
let targetString = "furniture";
let dictionary = ["fur", "ure", "nit"];
const tableData = {};
const canConstructRecursive = (targetString, dictionary) => {
if (targetString == "") {
return true
}
for (let i = 0; i < dictionary.length; i++) {
if (targetString.indexOf(dictionary[i]) == 0) {
shorterTargetString = targetString.slice(dictionary[i].length);
if (canConstructRecursive(shorterTargetString, dictionary)) {
return true;
};
}
}
return false;
}
console.log(canConstructRecursive(targetString, dictionary));
More on the second fix.
Your code will unconditionally return the value of the recursive call, even when it is false. This is not good: in case the recursive call returns false, the caller should continue with its for loop to try alternatives.
Let's for instance add a word to your example dictionary: you'll agree that adding a dictionary word should not change the outcome for the input "furniture". So here it is:
["furn", "fur", "ure", "nit"]
But surprise: your code now returns false for "furniture"! This is because "furn" mathes, but the recursive call with "iture" as first argument does not find further matches, so it returns false, and now the caller also returns false. This is wrong. It should give up on "furn", but not on the whole exercise. It should have continued and tried with "fur". This is why the exit out of the for loop should only happen upon success, not upon failure. Failure can only be confirmed when all dictionary words have been tried, so the for loop must continue for as long as there is no recursive success.
User trincot already explained what was wrong with your code. Here, I just want to point out that your structure, which is something like for (...) {if (...) { if (...) {return true} } } return false, might be better handled with Array.prototype.some and an && statement. Combining this with the fact that t .indexOf (s) == 0 might more clearly be expressed as t .startsWith (s), and sprinkling in a conditional statement instead of an if statement, we can arrive at what I think is a more elegant formulation:
const canConstruct = (t = '', ss = []) =>
t == ''
? true
: ss .some ((s) => t .startsWith (s) && canConstruct (t .slice (s .length), ss))
console .log (canConstruct ('furniture', ['fur', 'ure', 'nit'])) //=> true
console .log (canConstruct ('furniture', ['furn', 'fur', 'ure', 'nit'])) //=> true
console .log (canConstruct ('banana', ['b', 'ana'])) //=> false
console .log (canConstruct ('banana', ['ba', 'na'])) //=> true
I am pretty new at this stuff, and I am solving a series of questions, but I've got lost in this one.
I have to verify if a number can be divided by other, and the answer must be true or false.
I got his
function solucao(numero, x) {
solucao(numero % x);
if (solucao === 0) {
resultado = true;
}else{
resultado = false;
}
}
But I'm getting runtime error and can't see whats is missing.
So you want to check if a number numero is divisible by x. The modulo operator can help. Try this:
function solucao(numero, x){
if (numero % x == 0){
return true
}
else {
return false
}
}
function solucao(numero, x) {
let resultado;
if (numero % x === 0) {
resultado = true;
}else{
resultado = false;
}
return resultado;
}
I think you get confused at some point. You are calling the function, inside of itself. You should do like this, and also, declare the result variable.
I am sure this will help:
function checkIfDivided(){
// in this section the variables come from an html document
var number=parseInt(document.getElementById("number").value);
var divisor=parseInt(document.getElementById("divisor").value);
if(number%divisor==0)
return true;
else return false;
}
or
function checkIfDivided(number,divisor){
//in the function the variable are given as parameters
if(number%divisor==0)
return true;
else return false;
}
Looks like two things to me:
You haven't declared your 'resultado' variable ( this can be as simple as just typing 'let resultado;' without the single quotes
You haven't returned your 'resultado' variable after the if/else statement
Right now, your function is using an undeclared variable and not returning anything, so that is why you are getting an error. Fix the two above steps and you should be good! :)
You clearly understand that the modulus operator is the way to go. Using it we discover that 12 is divisible by 3 because 12 % 3 return zero. Zero is considered a "falsy" value while any other number is considered "truthy".
Given this then if 12 % 3 returns a "falsey" value (zero) we can't use the result directly. But what if we can "flip" false to true? We can, using the not operator (!).
Using the ! operator on the result of a math problem requires the use of parentheses around the math problem itself.
So the problem in code becomes (12 % 3) and to 'flip' it with the ! operator it becomes
!(12 % 3).
This is proven below with:
console.log(!(12 % 3)) --> logs true
console.log(!(12 % 5)) --> logs false
The function implementation of that is simple and also proven:
console.log(isDivisible(12,3)); --> logs true
console.log(isDivisible(12,5)); --> logs false
console.log(!(12 % 3))
console.log(!(12 % 5))
function isDivisible(number, x){
return !(number % x);
}
console.log(isDivisible(12,3));
console.log(isDivisible(12,5));
There is one other way to do so and i think its much cleaner.
console.log(Number.isInteger(10/2)) //true
console.log(Number.isInteger(4/2)) // false
//a must be greater than b
function check(a,b) {
console.log(Number.isInteger(a/b))
return Number.isInteger(a/b)
}
check(10,5)//true
check(8,3)//false
I found this function to put numbers in fractions and I am trying to figure out what everything means. There is one thing I can't figure out.
Here's the code:
function reduce(numerator,denominator) {
var gcd = function gcd (a,b) {
if (b) {
return gcd(b, a%b);
} else {
return a;
}
};
gcd = gcd(numerator,denominator);
return [numerator/gcd, denominator/gcd];
}
What does the if (b) mean. I know that if there is just the variable in the if statement it is checking if the variable is true or false. How would this apply to a number? When would this go to the else statement?
This is to do with how things get converted to Boolean, i.e. whether something is truthy or not
if (0 || NaN || undefined) { // these are "falsy"
// this never happens
} else if (1 /* or any other number*/ ){ // these are "truthy"
// this happens
}
If b is:
0
null
undefined
NaN
Or an empty string ""
it will be evaluated as false. Otherwise, it will be evaluated as true.
In javascript you can check if the variable is assigned by putting it in an if statement. If it has a value it will be true (well unless its value is false or 0). If it has no value or evaluates at null it will return false. Looks like they are verifying it has a value before passing it into the function.
Any expression in if statement will be implicitly converted to boolean before evaluated.
In the code you posted, it's usually used to check if a parameter is passed, in which case undefined is a falsy value and will be converted to false. AJPerez has given an answer on the falsy values (except for he forgot NaN).
function reduce(numerator,denominator){
var gcd = function gcd(a,b){
if (b) {
// if two arguments are passed, do something
return gcd(b, a%b);
}
else {
// only one argument passed, return it directly
return a;
}
};
gcd = gcd(numerator,denominator);
return [numerator/gcd, denominator/gcd];
}
However, this approach may be buggy if the argument you're checking is indeed passed by falsy.
When having a simple boolean, it is simple to use it in a condition :
var running = true;
if(running) {/*do something*/}
Is there some trick to do this with a boolen array? something like this:
var running = [false,false,true,false];
if(running[]){/*do something*/}
At the moment I do it like this :
var uploading = false
for(i=0; i< running.length ; i++)
{
if(running[i]) uploading = true;
}
if(uploading)
But I feel like this is not really perfectly written code and that their could be some trick, shorthand method.. Could be plain javascript, could be Jquery
jQuery has the $.inArray method:
uploading = $.inArray(running, true) !== -1;
The name is slightly misleading, it returns the index of the element that matched (-1 if none).
JavaScript has Array#indexOf, but it's missing in IE8 and earlier:
uploading = running.indexOf(true) !== -1;
JavaScript as of ES5 has the Array#some method, but it's overkill if you can look for the specific value with either of the above. Still, it's useful if you need to massage the values at all. For instance, if any "truthy" value is okay rather than specifically true:
uploading = running.some(function(entry) { return !!entry; });
You can just use this:
uploading = running.indexOf(true) !== -1;
If the array doesn't contain a true, indexOf will return -1, resulting in a false from !== -1. If the array contains a true, indexOf will return it's index, resulting in a true.
A slightly shorter option:
uploading = !!~running.indexOf(true);
The ~ is a bitwise NOT, this inverts the value from indexOf: -1 -> 0, 0 -> -1, 1 -> -2, etc. Then the double ! first casts this value to a boolean, then inverts it again, resulting in a boolean output that's true then the array contains a true.
I just thought about little trick that can work in this situation:
uploading = !!Math.max.apply(null, [false, true, false, false]); // => true
Basically without !! path you will get 1 (if there is at least one true) or false (for all false in array). Max calls ToNumber for each passed argument, so true => 1.
Note: you'd better use indexOf, this is just for fun and to demonstrate another unobvious way.
Is there any JavaScript value that makes a comparison always true?
Example with lower than operator:
true < 10 true
false < 10 true
null < 10 true
Example with greater than operator:
true > 10 false
false > 10 false
null > 10 false
What I'm looking for:
alwaysTrue < 10 true
alwaysTrue > 10 true
I want to use this to make one part of an if statement return true by default and true or false when the first comparison value is changed.
This is probably not existent but I want to be completely sure.
You may want to consider leveraging "or" in your condition with another variable that can trump whether it returns true or not.
returnTrue || testVariable < 10
This will always return true when returnTrue is set to true, otherwise it will fall back on the comparison. If you are just looking for a change in a variable you can do so by storing the old value. If you know it will never be null you can check on this, otherwise you can use the the "or" with a flag similar to above.
oldValue === null || currentValue === oldValue
I'm not exactly sure if this is what you are asking, but this is a way of doing it with a few more statements:
var rtn = true;
if (oldCompareValue != newCompareValue) {
// next you'll want to insert your return expression
// i'm not sure you've specified what this should be
rtn = (newCompareValue > 10)? true: false;
}
return rtn;
You can also do this using the AND operator as you've requested:
rtn = true;
if ((oldCompareValue != newCompareValue) && true) {
rtn = (newCompareValue > 10)? true: false;
}
return rtn;
The if statement does the following for us:
if oldCompareValue is the same as newCompareValue then the whole statement is false
if oldCompareValue is not the same as newCompareValue then the whole statement is true
In either case the right part of the test expression always evaluates to true, and you'll only enter the if when the left part passes as well. However, keeping that true in place seems excessive to me.
Once you got you're logic in place this can go into one line.