So I'm trying to familiarize myself with recursion and Javascript. So I wrote a simple method to try it out. I'm pretty new to Javascript syntax so I'm not really sure where I'm going wrong. Here is the method.
export const IsEven = (n) => {
if(n > 1){
n -= 2;
IsEven(n);
}
else{
var bool = NumberToBool(n);
return bool;
}
}
When stepping through, n does reach 0 or 1 and defines it as true or false. However, the method does not stop at the return statement. Instead, it turns around and starts adding 2 to n. I cannot understand how that is even possible, does anyone have an idea on what is going on?
Thanks
You can use mathematical induction to solve the vast majority of recursive problems -
if n is negative, return the result of isEven(-n)
(inductive) n is zero or greater. if n is greater than one, return the result of the recursive sub-problem, isEven(n - 2)
(inductive) n is neither negative nor greater than 1. this means n is zero or one. zero is even, one is odd. return n == 0 gives us the correct result for both.
const isEven = (n) => {
if (n < 0) return isEven(n * -1) // 1. n is negative
else if (n > 1) return isEven(n - 2) // 2. n is 2 or more
else return n == 0 // 3. n is 0 or 1
}
for (let i = -10; i<10; i++)
console.log(i, isEven(i))
Recursion is a functional heritage and so using it with functional style yields the best results. if statements do not evaluate to a value and instead rely on side effects like return to compute the result. Below we use expressions which evaluate to a value and it allows us to skip a lot of the syntactic noise that comes with imperative style. Now isEven reads more like a formula -
const isEven = n =>
n < 0
? isEven(n * -1) // 1. n is negative
: n > 1
? isEven(n - 2) // 2. n is 2 or more
: n == 0 // 3. n is 0 or 1
for (let i = -5; i < 5; i++)
console.log(i, isEven(i))
n
isEven(n)
-5
false
-4
true
-3
false
-2
true
-1
false
0
true
1
false
2
true
3
false
4
true
isEven can be defined using a synergistic counterpart, isOdd, where each can be defined in terms of the other. This technique is called mutual recursion -
const isEven = n =>
n < 0
? isEven(-n)
: n == 0
? true
: isOdd(n - 1)
const isOdd = n =>
n < 0
? isOdd(-n)
: n == 0
? false
: isEven(n - 1)
for (let i = -5; i < 5; i++)
console.log(`i:${i} isEven:${isEven(i)} isOdd:${isOdd(i)}`)
n
isEven(n)
isOdd(n)
-5
false
true
-4
true
false
-3
false
true
-2
true
false
-1
false
true
0
true
false
1
false
true
2
true
false
3
false
true
4
true
false
Related
as x is constant so it is positive or negative.
because we are checking the value of x which is constant, so it doesn't matter if we put a negative sign before it.
so it will cause an infinity loop as x is still positive.
I'm going to rewrite your code for better readability.
const reversed = (x) => {
if (x < 0) {
return -1 * reversed(-x);
}
}
If we call reversed with x >= 0, then reversed returns undefined because of an implicit return in the JS function.
e.g. reversed(1) // --> undefined
If x < 0, then we return -1 * reversed(-x). x < 0 -> -x > 0.
We already know that reversed called with x >= 0 is undefined, so we get -1 * undefined which results in NaN (Not a Number).
TLDR:
x >= 0 -> reversed(x) -> undefined
x < 0 -> reversed(x) -> NaN
I am trying to wrap my head around recursive functions. I've tried a number of entry level exercises with no success. For example, I put this code into JS fiddle. I intended for it to take the sum of all numbers from 1 to n.
function sumAll(n) {
if (n == 1 ) {
return 1;
} else if (n > 1) {
return sumAll(n--) + n;
}
}
console.log(sumAll(3));
feeding 3 to the function should give me '6'. I get an error, though.
The -- suffix operator will evaluate to the original value of n, and the subtraction from n will happen afterwards (which is also not desired as you still want to do + n). That means the recursive call gets the same value for n as the caller, and so you don't get closer to the end...
Don't use -- here, but -1:
function sumAll(n) {
if (n == 1 ) {
return 1;
}
else if (n > 1) {
return sumAll(n-1) + n;
}
}
console.log(sumAll(3));
Perhaps you will enjoy a repeatable technique that can guide you through designing your recursive function. Let's solve sumAll using inductive reasoning -
If n is zero, return the empty sum, zero
(inductive) n is negative or positive. If n is negative, return the negative result of the subproblem sumAll(-n)
(inductive) n is positive. Return n plus the result of the subproblem sumAll(n - 1)
function sumAll(n) {
if (n == 0) // 1
return 0
else if (n < 0) // 2
return -sumAll(-n)
else
return n + sumAll(n - 1) // 3
}
console.log(sumAll(-10), sumAll(0), sumAll(10))
// -55 0 55
Here is sumAll written using a switch instead. It behaves identically but maybe you will find the syntax nicer to read -
function sumAll(n) {
switch (true) {
case n == 0: return 0 // 1
case n < 0: return -1 * sumAll(-n) // 2
default: return n + sumAll(n - 1) // 3
}
}
console.log(sumAll(-10), sumAll(0), sumAll(10))
// -55 0 55
Here is sumAll again as a pure, functional expression -
const sumAll = (n = 0) =>
n == 0 // 1
? 0
: n < 0 // 2
? -1 * sumAll(-n)
: n + sumAll(n - 1) // 3
console.log(sumAll(-10), sumAll(0), sumAll(10))
// -55 0 55
I'm learning TypeScript, and in the getting started page, they talk about how unexpected javascript is.
Source: https://www.typescriptlang.org/docs/handbook/typescript-from-scratch.html
if ("" == 0) {
// It is! But why??
}
if (1 < x < 3) {
// True for *any* value of x!
}
But I still don't understand why 1<x<3 is always true? For example if I let x=10, it will not be true by logic, but why they said it always true?
1 < x < 3 actually is doing this:
(1 < x) < 3
Or even more long form:
const tempVarA = 1 < x
const tempVarB = tempVarA < 3
So 1 < x is either true or false. Then the next step is true < 3 or false < 3. Those don't make much sense as comparisons, but let's see what javascript does with that:
console.log(true < 3) // true
console.log(false < 3) // true
Weird, but let's dig deeper:
console.log(true >= 0) // true
console.log(true >= 1) // true
console.log(true >= 2) // false
console.log(false >= 0) // true
console.log(false >= 1) // false
console.log(false >= 2) // false
It seems that true is being treated as 1 and false is being treated as 0. To verify that let's compare with == (instead of ===) so that it coerces the type of the data for us.
console.log(true == 1) // true
console.log(true == 0) // false
console.log(false == 1) // false
console.log(false == 0) // true
So 1 < x < 3 is always true because false becomes 0 or true becomes 1, and both 0 and 1 always less than 3.
Explanation:
in javascript, comparison operators <, <=, >, >=, ==, and != coerce their operands to make them comparable when they are different types. So when comparing a boolean to a number it coverts the boolean to a number, 0 or 1.
This is why you should almost always use === instead of ==, and why this is a type error in typescript:
const a = true < 3
// Operator '<' cannot be applied to types 'boolean' and 'number'.(2365)
Short version
Javascript and typescript lack a chainable comparison operator.
Did you mean to do this?
1 < x && x < 3
in other words: true is 1 and false is 0. Therefore 1 < x < 3 with x = 5 is as if it executes (1 <5) <3 and writes to 1 <5 = 1 (true) and then 1 <3 = 1 (true). If instead x were 0? Ok 1 <0 is false (0) consequently 0 <3 is true (1)
Zero is even.
One is odd.
For any other number N, its evenness is the same as N - 2.
Define a recursive function isEven corresponding to this description. The function should accept a single parameter (a positive, whole number) and return a Boolean.
Here is my implementation of isEven:
let isEven = function(n){
even = 0;
odd = 1;
if(n == even){
return true;
}
else if (n == odd) {
return false;
}
else{
n -= 2;
console.log(n); //Used to see value of n through each call
isEven(n);
}
};
When I call this function, it returns undefined
document.write(isEven(50)); //prints `undefined`
The output from console.log(n) is the following:
Failed to load resource: net::ERR_FILE_NOT_FOUND
48
46
...
0
I am not sure why Failed to load resource: net::ERR_FILE_NOT_FOUND is the first output, but after that n is hitting 0, so why is
if(n == even){
return true;
}?
not executing?
You need to return the result from the recursive call.
let isEven = function(n){
const // declare local variables/constants
even = 0,
odd = 1;
if(n == even){
return true;
}
else if (n == odd) {
return false;
}
else{
//n -= 2; no need to reassign a value for a single use
return isEven(n - 2); // return here
}
};
console.log(isEven(50));
console.log(isEven(21));
A better style without else parts, because this is not necessary if returned before.
use values directly, if used only once,
use strict comparison (Identity/strict equality operator ===), because not strict can led to wrong assumptions
take a calculation for the parameter directly without reassign a value to the variable which is not used anymore
let isEven = function(n){
if (n === 0) return true;
if (n === 1) return false;
return isEven(n - 2);
};
console.log(isEven(50));
console.log(isEven(21));
But don't miss out on the opportunity to learn about mutual recursion!
const isEven = (n = 0) =>
n === 0
? true
: isOdd (n - 1)
const isOdd = (n = 0) =>
n === 0
? false
: isEven (n - 1)
console .log
( isEven (0) // true
, isEven (1) // false
, isEven (2) // true
, isEven (3) // false
, isEven (99) // false
)
console .log
( isOdd (0) // false
, isOdd (1) // true
, isOdd (2) // false
, isOdd (3) // true
, isOdd (99) // true
)
Is there a more effective way to return true if n is a power of two or false if not?
function isPowerOfTwo(n) {
return Math.pow(2, Math.round(Math.log(n) / Math.log(2)));
}
You can actually use ECMAScript5 Math.log:
function powerOfTwo(x) {
return (Math.log(x)/Math.log(2)) % 1 === 0;
}
Remember, in math, to get a logarithm with an arbitrary base, you can just divide log10 of the operand (x in this case) by log10 of the base. And then to see if the number is a regular integer (and not a floating point), just check if the remainder is 0 by using the modulus % operator.
In ECMAScript6 you can do something like this:
function powerOfTwo(x) {
return Math.log2(x) % 1 === 0;
}
See the MDN docs for Math.log2.
Source: Bit twiddling Hacks,
function powerOf2(v) {
return v && !(v & (v - 1));
}
You just bitwise AND the previous number with the current number. If the result is falsy, then it is a power of 2.
The explanation is in this answer.
Note:
This will not be 100% true for programming, mathematical, [also read 'interviewing']. Some edge cases not handled by this are decimals (0.1, 0.2, 0.8…) or zero values (0, 0.0, …)
Using bitwise operators, this is by far the best way in terms of efficiency and cleanliness of your code:
function PowerofTwo(n){
return ((x != 0) && !(x & (x - 1)));
}
what it does is checks the bits that make up the number, i.e. 8 looks like this:
1 0 0 0
x-1 or 7 in this case looks like this
0 1 1 1
when the bitwise operator & is used it invokes an && on each bit of the number (thus 1 & 1 = 1, 1 & 0 = 0, 0 & 1 = 0, 0 & 0 = 1):
1 0 0 0
-0 1 1 1
=========
0 0 0 0
since the number turns into an exact 0 (or false when evaluted as a boolean) using the ! flag will return the correct answer
if you were to do this with a number like 7 it would look like this:
0 1 1 1
-0 1 1 0
=========
1 1 1 0
returning a number greater than zero causing the ! flag to take over and give the correct answer.
A number is a power of 2 if and only if log base 2 of that number is whole. The function below computes whether or not that is true:
function powerOfTwo(n){
// Compute log base 2 of n using a quotient of natural logs
var log_n = Math.log(n)/Math.log(2);
// Round off any decimal component
var log_n_floor = Math.floor(log_n);
// The function returns true if and only if log_n is a whole number
return log_n - log_n_floor == 0;
}
Making use of ES6's Math.clz32(n) to count leading zeros of a 32-bit integer from 1 to 2³² - 1:
function isPowerOf2(n) {
return Math.clz32(n) < Math.clz32(n - 1);
}
/**
* #param {number} n
* #return {boolean}
*/
const isPowerOfTwo = function(n) {
if(n == 0) return false;
while(n % 2 == 0){
n = n/2
}
return n === 1
};
function PowerOfTwo(n){
// Exercise for reader: confirm that n is an integer
return (n !== 0) && (n & (n - 1)) === 0;
}
console.log(PowerOfTwo(3))
console.log(PowerOfTwo(4))
This is for a specific online course that requires an answer in a specific way.
Without using libraries and other methods just loops and .push.
you need to create an inner loop using while
it should start with 1
keep multiplying it with 2 until i,j,k or whatever is greater than the current number(array) so it will have to do 2 4 6 8 10 12 14 16 18 until it is greater than the number
then it will go to the outer loop then repeat again until
const numbers = [5, 3, 9, 30];
const smallestPowerOfTwo = arr => {
let results = new Array;
// The 'outer' for loop -
for (let i = 0; i < arr.length; i++) {
number = arr[i];
// The 'inner' while loop
j = 1;
while (j < number) { //starting from 1 then multiplied by 2 then by 2 again untill it is more than the number
j = j * 2;
}
results.push(j);
}
return results
}
console.log(smallestPowerOfTwo(numbers))