What does var prime = num != 1; mean? - javascript

I know this is similar to another SO question, but the variable prime is supposed to be any number other than 1, and it looks to me like it would be assigned the boolean value of num != 1. Can anyone tell me what this line of code is actually doing?
Here's the code where it's being used
function isPrime( num ) {
var prime = num != 1; // Everything but 1 can be prime
for ( var i = 2; i < num; i++ ) {
if ( num % i == 0 ) {
prime = false;
break;
}
}
return prime;
}
EDIT:
I assume that this line does something like this:
if( num != 1) {
prime = num;
}
But I still want to know why or how this line of code does this.

As you were thinking correctly, the statement var prime = num != 1; assigns the result of the boolean expression (num != 1) to the variable prime. This special case is included in kind of every prime checking code because 1 itself is not a prime number.
Your algorithm could be even faster if you only checked for divisors up to the square root of the input value. You can read about this here and may notice that it's far more efficient to check if num > i*i than sqrt(num) > i.
Additionally the algorithm you have could still return wrong values if you feed it negative or zero values.

In other words:
If num == 1, set prime to false and skip the loop.
Otherwise, enter the loop and use the standard logic to determine the value of prime.
This is done because the standard logic (inside the loop) will not work on the number 1.
Therefore, as pst says, you check for the edge case outside the loop.
This helps keep the logic clean inside the loop.
To make it more readable (and correct for all values) I would re-write it like this:
function isPrime( num ) {
if (num <= 1) {
return false;
}
for ( var i = 2; i < num; i++ ) {
if ( num % i == 0 ) {
return false;
}
}
return true;
}
You could also exit the loop once i is greater than num / 2 to make it more efficient.

1 is not a prime number
That is an edge-case check because for(i = 2;..) (below) "skips" 1: because the loop never runs, prime is only set once to false (which is the evaluation of i != 1, when i = 1).
However, I find it confusing and would have used:
if (i <= 1) {
return false;
} else {
// other stuff
}

The point of that line of code is to achieve two goals in one:
Firstly, they need to create a boolean variable
Second, they need to check if the number is 1, then it's not prime
They are just doing both at the same time.

Related

Each digit differs from the next one by 1

Script has to work this way:
isJumping(9) === 'JUMPING'
This is a one digit number
isJumping(79) === 'NOT JUMPING'
Neighboring digits do not differ by 1
isJumping(23454) === 'JUMPING'
Neighboring digits differ by 1
I have:
function isJumping(number) {
let str = number.toString();
for (let i = 1; i < str.length; i++) {
if (Math.abs(str[i+1]) - Math.abs(str[i]) == 1){
return 'JUMPING';
}
}
return 'NOT JUMPING';
}
console.log(isJumping(345));
Help please, where is mistake?
Loop over the characters and early return with "NOT JUMPING" if the condition is violated & if the condition is never violated return "JUMPING".
function isJumping(num) {
const strNum = String(Math.abs(num));
for (let i = 0; i < strNum.length - 1; i++) {
if (Math.abs(strNum[i] - strNum[i + 1]) > 1) {
// replace `> 1` with `!== 1`, if diff 0 is not valid!
return "NOT JUMPING";
}
}
return "JUMPING";
}
console.log(isJumping(9));
console.log(isJumping(79));
console.log(isJumping(23454));
There are a couple of issues:
You're not handling single digits.
You're returning too early. You're returning the first time you see a difference of 1 between digits, but you don't know that subsequent differences will also be 1.
You're not checking the difference between the first and second digits, and you're going past the end of the string.
You're using Math.abs as a means of converting digits to numbers.
Instead (see comments):
function isJumping(number) {
let str = number.toString();
for (let i = 1; i < str.length; i++) {
// Convert to number, do the difference, then
// use Math.abs to make -1 into 1 if necessary
if (Math.abs(+str[i] - str[i-1]) !== 1) {
// Found a difference != 1, so we're not jumping
return "NOT JUMPING";
}
}
// Never found a difference != 1, so we're jumping
return "JUMPING";
}
console.log(isJumping(345)); // JUMPING
console.log(isJumping(9)); // JUMPING
console.log(isJumping(79)); // NOT JUMPING
console.log(isJumping(23454)); // JUMPING
In that, I use +str[i] to convert str[i] to number and implicitly convert str[i-1] to number via the - operator, but there are lots of ways to convert strings to numbers (I list them here), pick the one that makes sense for your use case.
You might also need to allow for negative numbers (isJumping(-23)).
A clumsy way would be if (Math.abs(Math.abs(str[i+1]) - Math.abs(str[i])) == 1). Right now you are using Math.abs() to convert digits to numbers. Also, indexing is off, you start from 1, which is good, but then you should compare [i] and [i-1]. And the usual mismatch: you can say "JUMPING", only at the end. So you should check for !==1, and return "NOT JUMPING" inside the loop, and "JUMPING" after. That would handle the 1-digit case too.
It's a more readable practice to use parseInt() for making a number from a digit, otherwise the implementation of the comment:
function isJumping(number) {
let str = number.toString();
for (let i = 1; i < str.length; i++) {
if (Math.abs(parseInt(str[i-1]) - parseInt(str[i])) !== 1){
return 'NOT JUMPING';
}
}
return 'JUMPING';
}
console.log(isJumping(345));
console.log(isJumping(3));
console.log(isJumping(79));
You just need to check your single digit case, and then see if all the digits vary by just 1
function isJumping(number) {
let str = number.toString();
if(str.length == 1)
return 'JUMPING'
const allByOne = str.substring(1).split('').every( (x,i) => {
var prev = str[i];
return Math.abs( +x - +prev) == 1
})
return allByOne ? 'JUMPING' : 'NOT JUMPING';
}
console.log(isJumping(9));
console.log(isJumping(79));
console.log(isJumping(23454));
A vaguely functional approach... The find gets position of the first character pair where the gap is more than one. The .filter deals with negatives (and other extraneous characters) by ignoring them.
// default b to a, so that last digit case, where b===undefined, gives true
const gapIsMoreThanOne = (a,b=a) => ( Math.abs(a-b)>1);
const isDigit = n => /[0-9]/.test(n);
const isJumping = n => n.toString()
.split("")
.filter(isDigit)
.find((x,i,arr)=>gapIsMoreThanOne(x,arr[i+1]))
=== undefined
? "JUMPING" : "NOT JUMPING"
;
console.log(isJumping(1)); // JUMPING
console.log(isJumping(12)); // JUMPING
console.log(isJumping(13)); // NOT JUMPING
console.log(isJumping(21)); // JUMPING
console.log(isJumping(21234565)); // JUPING
console.log(isJumping(-21234568)); // NOT JUMPING
console.log(isJumping("313ADVD")); // NOT JUMPING
PS: To me "JUMPING" implies that there is a gap greater than one, not that there isn't: but I've gone with how it is in the question.

Can't detect the cause of infinite loop in a 'while loop' in JS

I've got an infinite loop inside my while loop and I can't find the cause.
It's a simple function that returns the sum of the argument's digits. I use a while loop because it needs to add up the digits until it lands at a one digit number.
I made sure that I added a statement that would make sure that at a certain point the loop will break., But it obviously doesn't.
function digital_root(n) {
num = n;
sum = 0;
while (num.toString().length>1){
for (i=0; i<num.toString().length; i++) {
sum += parseInt(num.toString()[i])
}
num = sum;
}
return sum;
}
digital_root(456)
I get a warning that I have an infinity loop on line 4 (while loop).
I hoped that num=sumwould reassign the new integer (with reduced number of digits) to the numvariable and thus at some point break out of the loop. Is this wrong?
What further confuses me is that most of the JS editors I've used to debug the problem return an output, but it takes ages. So is it an infinite loop or is it not?
You have a nested loop structure where the first condition is always true.
For getting only a number below 10, you could call the function again as recursion.
function digital_root(n) {
var num = n.toString(), // declare and use the string value
sum = 0,
i;
for (i = 0; i < num.length; i++) {
sum += parseInt(num[i], 10)
}
return sum > 9
? digital_root(sum)
: sum;
}
console.log(digital_root(456));
After re-reading the question I noticed that you're trying to reduce an integer down to a single number. The issue with your code was that sum was set to 0, only before the while loop. Meaning that it didn't reset for the second, third, ... run.
Moving sum = 0 into the while loop resolves this issue. I've also added variable declarations at the top to avoid setting global variables.
function digital_root(n) {
var num, sum, i;
num = n;
while (num.toString().length > 1) {
sum = 0;
for (i = 0; i < num.toString().length; i++) {
sum += parseInt(num.toString()[i]);
}
num = sum;
}
return sum;
}
console.log(digital_root(456));
Here written in a recursive manner, a style that I personally more prefer:
function digital_root(integer) {
// guard against things that might result in an infinit loop, like floats
if (!Number.isInteger(integer) || integer < 0) return;
const chars = integer.toString().split("");
if (chars.length == 1) return integer;
return digital_root(
chars.map(char => parseInt(char))
.reduce((sum, digit) => sum + digit)
);
}
console.log(digital_root(456));
Since you already got the answer, here is another way to meet the result
function digital_root(n) {
// convert the number to string
// use split to create an array of number viz ['4','5','6']
// use reduce to sum the number after converting to number
// 0 is the initial value
return n.toString().split('').reduce((a, c) => a + parseInt(c, 10), 0)
}
console.log(digital_root(456))
Avoiding all the nested loops that lead to a situation such as that you're facing, I'd rather do it in a more readable way.
function digital_root(n) {
sum = n;
while(sum.toString().length > 1) {
sum = sum.toString()
.split('')
.map(digit => parseInt(digit, 10))
.reduce((acc, cur) => acc + cur);
}
return sum;
}
console.log(digital_root(456));

Assigning a variable = to any number between these two numbers

is there any way of assigning a variable lets say,
var between = any number between 5 and 10?
So when I call something like,
if(between === 6){
//do this
}
it ends up being true and running the code?
You would use two parts to a comparison. There is no single operand in Javascript that checks for "betweenness". You could build your own function to do that if you wanted. Here's an if statement that requires two conditions to be true before the statement is true:
if (val >= 5 && val <= 10) {
// val is between 5 and 10 (including both 5 and 10)
}
Or, you could build yourself a little function:
function isBetween(val, min, max) {
return val >= min && val <= max;
}
if (isBetween(val, 5, 10)) {
// val is between the two numbers
}
If you prefer jQuery and have between numbers in the array, one of the way to solve this kind of task is by using jQuery.inArray().
for example:
var between = [5,6,7,8,9,10];
if($.inArray(6, between)) {
// do somethings
}

Need help writing code to convert decimal to binary without the use of the toString

I'm trying to create my own decimal to binary converter with the method of decrementing the inputted variable (decimal value), by dividing it by 2 and storing the remainder (like 2nd grade math remainder), which is always either 0 or 1. Each of the remainder values i thin should be stored in an array and I think maybe put in backwards so that the most significant digit is first in the array (this is because when decrementing the remainer values are filled in left to right). Soooo yea i dont really know how to store the remainder values in an array using a function
Thanks in advance and if something is confusing then feel free to ask because im not even sure if this is the best method of doing this its just what i came up with
function decimalToBinary(num) {
var bin = 0;
while (num > 0) {
bin = num % 2 + bin;
num >>= 1; // basically /= 2 without remainder if any
}
alert("That decimal in binary is " + bin);
}
Your code is almost correct. The main problem is that bin starts out as 0; when you add a digit, they are added numerically, so your code ends up just counting the binary 1s: in this manner, 10 is initial 0, and +1+0+1+0, resulting in 2. You want to handle it as a string: ""+1+0+1+0 results in 1010. So, the only needed change is:
var bin = "";
If you want to solve it using arrays, with minimal changes to your code, it would be:
function decimalToBinary(num) {
var bin = [];
while (num > 0) {
bin.unshift(num % 2);
num >>= 1; // basically /= 2 without remainder if any
}
alert("That decimal in binary is " + bin.join(''));
}
Here, I use .unshift to add an element to the head of the array (and renumbering the remaining elements); .join() to collect them all into a string.
Or this:
function decimalToBinary(num) {
var bin = [];
while (num > 0) {
bin[bin.length] = num % 2;
num >>= 1; // basically /= 2 without remainder if any
}
alert("That decimal in binary is " + bin.reverse().join(''));
}
This is not as good, but illustrates some more things you can do with arrays: taking their length, setting an arbitrary element, and flipping them around.
I have written a custom Decimal to Binary method:
function toBinary (input) {
let options = [1];
let max = 0;
let i = 1;
while(i) {
max = Math.pow(2, i);
if (max > input) break;
options.push(max);
i++;
}
let j = options.length;
let result = new Array(j);
result.fill("0");
while(j >= 0) {
if (options[j] <= input) {
result[j] = "1"
input = input - options[j];
}
j--;
}
return [...result].reverse().join("");
}
//Test the toBin method with built-in toString(2)
toBinary(100) === (100).toString(2) // true
toBinary(1) === (1).toString(2) // true
toBinary(128) === (128).toString(2) // true

Javascript Recursion -> what does the return trace look like?

So, I'm just starting to explore recursion and am a little stuck on a concept. Here is a solution I located for a sum digits function ( f(126) = 1 + 2 + 6 = 9 ):
function sumDigits(num, sum){
if (num === 0) {
return sum;
} else {
sum += num % 10;
num = Math.floor(num / 10);
return sumDigits(num, sum);
}}
I traced it down to the base, so far everything makes sense:
**Trace**
f(126, 0)
{
sum = 6
num = 12
f(12, 6)
}
f(12, 6)
{
sum = 8
num = 1
f(1, 8)
}
f(1, 8)
{
sum = 9
num = 0
f(0, 9)
}
f(0, 9) = 9
I guess what doesn't make sense to me is HOW the base case is being passed back through during unwinding? How exactly is it traveling?
I'm expecting a facepalm, but until I understand I don't think I could replicate this solution.
Thanks for your help!
The sum is accumulated and passed forward in each call to sumDigits. It's this value that's returned whenever the first argument equals 0. I find that it helps to write out the recursion explicitly:
sumDigits(123, 0);
return sumDigits(12, 3);
return sumDigits(1, 5)
return sumDigits(0, 6) // the base case (sum = 6)
return sum;
The final call returns 6. The previous call returns the result of the final call. The call before that returns the call before the final call (and so on). So they all end up unraveling the final sum.
Note that each call returns the result of the next call in the chain. What stops this is the base case (i.e. a condition that results in the return of a concrete value (i.e. no additional calls)).
I'd suggest
function sumDigits(num) {
if (num < 0)
return sumDigits(Math.abs(num)) //handle negative numbers
least_sig_digit = num % 10
if (num < 10)
return least_sig_digit //in case num is a float)
else
return least_sig_digit + sumDigits(Math.floor(num / 10))
}
This way you will drill down until sumDigits returns the base case, and then bubble the result. By the time you reach the top of the call stack, you should have the sum of all digits.
Here's how this works:
sumDigits(126)
= 6 + sumDigits(12)
= (6+2) + sumDigits(1)
= (6+2+1)
= 9
The function calls are made from top-to-bottom order.
The return value bubbles up in bottom-to-top order, eventually returning the value 9 for the expression sumDigits(126).
The best way to think about recursion is defining the behavior to move from one layer to the next, and not worry about the big picture. As long as you're satisfied when someone tells you 5! = 5*4!, it's a lot easier to conceptualize recursion.
What is sumDigits(126)? It's 6 + sumDigits(12). But what is sumDigits(12)? It's (6+2) + sumDigits(1). etc.
It's returning sum += num % 10 recursively.
Another way to think about it, it's returning sum but each call modifies sum (the += operator) such that when it gets to the base case the value of sum in the innermost loop is the actual sum. So just return that value through all the returns.
If you just want to print you don't even need to return anything. Just have the base case print the value of sum and return null.
The summing is done on the way in to the base case, not on the way out.

Categories

Resources