How to refactor IF statements into ternary operators in javascript? - javascript

Hello I am trying to refactor my function but it doesn't seem to be working properly. It works fine normally which is the commented code. Am I writing this wrong or is there a fundamental flaw in my code?
function isPrime(num) {
// if (num <= 1){
// return false
// } else {
// for(var i = 2; i < num; i++){
// if(num % i === 0) return false;
// }
// }
num <= 1 ? false : {
for(let i = 2; i < num; i++){
num % 1 === 0 ? false
}}
return true;
}
Thanks

As far as I can tell, no language having the ternary operator allows running a block of statements, which is what you are doing. The ternary operator is a shorthand version of:
let result;
if (<condition>)
result = resultTrue;
else
result = resultFalse;
Unless JavaScript stabs be in the back on this one, for is a statement that doesn't return anything, and therefore cannot be used the way you want.
The best you could do, I guess, would be:
function isPrime(num) {
if (num <= 1) {
return false;
}
for(var i = 2; i < num; i++) {
if(num % i === 0) return false;
}
}
The else part omitted since hitting the line after the if necessarily means that the condition for it was not met.

Technically what you have can be brought to life with an IIFE:
function isPrime(num) {
return num <= 1 ? false :
(n => {
for (let i = 2; i < n; i++) {
if (n % i === 0) return false;
}
return true;
})(num)
}
for (let i = 0; i < 10; i++) {
console.log(i, isPrime(i));
}
Now it works and there is a ternary operator inside.
Even the attempt without return can be done, just you need isPrime made into an arrow function:
let isPrime = num => num <= 1 ? false :
(n => {
for (let i = 2; i < n; i++) {
if (n % i === 0) return false;
}
return true;
})(num);
for (let i = 0; i < 10; i++) {
console.log(i, isPrime(i));
}
Tadaam, the num <= 1 ? false : part is literally there in the first line, without that nasty return.
But realistically this is not how isPrime should be implemented, your very first attempt is the best one so far.
If you want an actual improvement, use the fact that divisors come in pairs. If x is a divisor of num, then num/x is also divisor of num. So if you were looking for all divisors of num, you would find them in pairs as soon as x=num/x=sqrt(num), so it's enough to check numbers between 2 and Math.floor(Math.sqrt(num)), inclusive. As you preferably don't want JS to calculate this number in every iteration (when checking the condition), you could count downwards, so
for (let i = Math.floor(Math.sqrt(num)); i >= 2; i--)

Related

Calculating complexity of js alghortim

I'm trying to caluclate complexity of below method in Big O notation
function algorithm(n,m){
let result = [];
for (let i = 0; i < n.length; i++) {
const total = m.filter((x) => x === n[i]).length;
if (PrimalityTest(total)) {
result.push(n[i]);
}
}
return result;
};
function PrimalityTest(c){
if (c <= 1) {
return false;
} else if (c === 2) {
return true;
} else {
for (let i = 2; i * i <= c; i++) {
if (c % i === 0) {
return false;
}
}
return true;
}
}
So, firstly there is loop which have O(n) and then there is nested loop and primality test function so that means complexity of all is O(n * m * sqrt(c))?
Can you please confirm If my understanding is correct?
The loop for (let i = 0; i < n.length; i++) is executed n times. The function m.filter((x) => x === n[i]).length checks every element in m, so executes m-times. So we have an execution time of O(n*m).
Considering
if (PrimalityTest(total)) {
result.push(n[i]);
}
is executed n times because it is in the same loop as above. So at worst it is O(n*sqrt(c))
To sum it up: It is O(n*m)+O(n*sqrt(c)). Because O(n*m) surpasses O(n*sqrt(c)) we get as result: O(n*m).
Your solution would mean that the filter function integrates the PrimalityTest method.

Euler's Totient Function in JavaScript

I am trying to implement Euler's Totient Function (phi) in Javascript. So far this is what I have:
function phi(n) {
var result = n;
for (let i=2; i*i<=n; i++) {
if (n % i === 0) {
while (n % i === 0) {
n /= i;
result -= result / i;
}
}
}
if (n > 1) {
result -= result / n;
}
return result;
}
Unfortunately it all goes wrong when it comes up to multiples of 4. How do I improve this?
Inspired by https://www.geeksforgeeks.org/eulers-totient-function/
function phi(n) {
// return Greater Common Denominator of two given numbers
function gcd(a, b) {
if (a === 0) {
return b;
}
return gcd(b % a, a);
}
// init
var result = 1;
// walk through all integers up to n
for (let i = 2; i < n; i++) {
if (gcd(i, n) === 1) {
result++;
}
}
return result;
}
You should implement result = 1, then result ++ whenever you encounter a number coprime to the number you input. For that, you have to find the gcd function and that can be done with various methods, such as ArrayLists (like in Java) or with recursive functions.
Not the most eficient way, but rather straightforward:
function phi(n) {
let divArr = []; // this is an array for the common divisors of our n
let primeCount = 0; // this is a counter of divisors
for (let i = 0; i <= n - 1; i++) {
if (n % i === 0) {
divArr.push(i);
}
}
for (let j = n - 1; j > 0; j--) { //j is all potential coprimes
for (let k = divArr.length - 1; k >= 0; k--) { //we get the indeces of the divArr and thus we can loop through all the potentail divisors
//here we check if our potential coprimes are comprimes or not
//run possible coprimes through the list of divisors
if (j % divArr[k] === 0 && divArr[k] !== 1) { //if a potential coprime can be divided by any element of the array of n's divisors we break the arra's loop i. e. k and go the j++
break
} else if (j % divArr[k] !== 0) { //if a potential coprime j cannot be divided by any element of divArray then it's ok and we simply stick to the next k and waiting for 2 possible cases: either it will reach 1 and we primeCount++ or eventually be divided and then we break the loop
continue
} else if (divArr[k] === 1) { //if can be divided without a remainder, greatest common divisor is not zero so we should break the loop
primeCount++;
}
}
}
console.log(divArr, primeCount)
}

Codewars Javascript Problem- my code with a double for loop times out

I'm trying to solve a problem on Codewars which involves seeing if one string includes all the letters in a second string. I think I've found a decent solution, but my code times out (12000ms) and I can't figure out why. Could anyone shed some light on this issue?
function scramble(str1, str2) {
let i;
let j;
let x = str2.split();
for (i = 0; i < str1.length; i++) {
for (j = 0; j < str2.length; j++) {
if (str1[i] == str2[j]) {
x.splice(j, 1);
j--;
}
}
}
if (x.length == 0) {
return true;
} else {
return false;
}
}
If your strings have sizes N and M then your algorithm is O(N*M). You can get O(NlogN + MlogM) by sorting both strings and then do a simple comparison. But you can do even better and get O(N+M) by counting the letters in one string and then see if they are present in the other. E.g. something like this:
function scramble(str1, str2) {
let count = {}
for (const c of str1) {
if (!count[c])
count[c] = 1
else
count[c]++
}
for (const c of str2) {
if (!(c in count))
return false
count[c]--
}
for (let k in count) {
if (count.hasOwnProperty(k) && count[k] !== 0)
return false
}
return true
}
You created an infinite loop by both incrementing and decrementing j. The value of j gets stuck whenever str1[i] == str2[j]
Reducing your code snippet to the simplest form would look something like this:
for (j = 0; j < 10; j++) {
j--;
console.log(j) // always -1
}
You're adjusting x but then referring to str2 as if it has been changed. Because you never adjust str2, you're always comparing the same two letters, so you get stuck in a loop. That's one problem. Then, your question's wording suggests that we're checking if every letter in str2 is in str1, but you're going through every letter in str1 and checking it against str2. str1 should be the inner loop.
function scramble(str1, str2) {
var x = str2.split("");
for (var i = 0; i < x.length; i++) {
for (var j = 0; j < str1.length; j++) {
if (str1[j] == x[i]) {
x.splice(i--, 1);
}
}
}
return x.length === 0;
}
console.log(scramble("dirty rooms", "dormitory"));
console.log(scramble("cat", "dog"));
Because x.length === 0 is already a boolean value, you can just return that. No need for the if statements there. The triple equals checks the variable's type and value, and double equals only checks value. I tend to always use triple when I'm checking against 0 and 1 because you don't want unintended consequences like this:
console.log(false == 0, true == 1);
console.log(false === 0, true === 1);
Also, because i-- means "i = i - 1 after execution", you can put that directly in your call to splice, and it won't execute until after splice is finished. --i, on the other hand, would be evaluated before execution.
This is all great, but using indexOf is a simpler solution:
function scramble(str1, str2) {
for (let i = 0; i < str2.length; i++) {
if (str1.indexOf(str2[i]) == -1) return false;
}
return true;
}
console.log(scramble("forty five", "over fifty"));
console.log(scramble("cat", "dog"));

Project Euler Largest Prime Factor bug in Javascript

I am new to javascript and struggling mightily to understand why this doesn't work.
function largestPrimeFactor(num) {
var primeFactors = [];
for (var i = 2; i < num; i++) {
// check if iter i is prime
if (checkIfPrime(i)) {
// if so, see if its a factor of num
while (num % i === 0) {
num /= i;
primeFactors.push(i);
console.log(primeFactors);
console.log(num);
}
}
if (num === 1) {
// return Math.max.apply(Math, primeFactors)
console.log(primeFactors);
console.log(Math.max.apply(Math, primeFactors));
}
}
}
function checkIfPrime(num) {
for (var i = 2; i < num; i++) {
if (num % i === 0) {
return false;
}
}
return true;
}
console.log(largestPrimeFactor(13195));
The final console.log never goes off for the last prime number 29. I never enter the last if(num === 1) case either, which I also don't know why...
When I iterate up to 29, checkIfPrime(i) should be true, and then after 29 / 29 sets num to 1, the last if case should work too.
Why is this not working??
Second Q - is
return Math.max.apply(Math, primeFactors)
the right way to return the max value from an array of integers?
Thanks!
for(var i = 2; i < num; i++) { // line 3
So if num is 29, i can only go to 28. Should change the < to <=.

Why is this function creating an infinite looop?

The first function determines if a number is prime. The second function is supposed to create an array with all prime numbers up to and including the max value, but it gives me an infinite loop for some reason.
function isPrime(num) {
for (i = 2; i < num; i++) {
if (num % i === 0) {
return false
}
}
if (num <= 1) {
return false;
}
return true;
}
function primes(max) {
var all = [];
for (i = 2; i <= max; i++) {
if (isPrime(i)) {
all.push(i);
}
}
}
primes(17);
Your i variable is global, so both functions use the same i. This means the first function changes it while the second one is looping.
As the first function will have set i to num-1 when it finishes, and num was the value of i before executing it, it effectively decrements i with one. And so i will get the same value in the next iteration of the loop in the second function, never getting forward.
Solve this by putting the var keyword in both functions.
for(var i=2; // ...etc)
The variable i in your two loops are global variables and they overwrite each other so the first loop never ends.
In ur code problem is with the scope of variable i, In prime no calculation, u can check upto the sqrt of no, if no is not divisible by any no upto its sqrt, then it will a prime no, Try this:
function isPrime(num) {
let k = Math.sqrt(num);
for (let i = 2; i <= k; i++) {
if (num % i === 0) {
return false
}
}
return true;
}
function primes(max) {
let all = [];
for (let i = 2; i <= max; i++) {
if (isPrime(i)) {
all.push(i);
}
}
console.log(all)
}
primes(17);
primes(25);

Categories