Javascript IIFE changes result - javascript

I'm looking at projecteuler.net's 4th problem, and have come across a curious feature that I'm wondering if anyone could explain.
The following code returns 10001
var n = 999 * 999; //biggest product with 3 digit numbers
var x;
while (n>10000) { //smallest product of 3 digit numbers
if (n.toString() === n.toString().split('').reverse().join('')) {
x = Math.floor(Math.sqrt(n));
while (n % x !== 0 && x >= 100 && n/x <= 999) {
x--;
}
if (n % x === 0 && x>= 100 && n/x <= 999) {
n;
}
}
n--;
}
whereas when wrapped in an IIFE, it returns 906609 which is the correct answer.
(function euler4() {
var n = 999 * 999; //biggest product with 3 digit numbers
var x;
while (n>10000) { //smallest product of 3 digit numbers
if (n.toString() === n.toString().split('').reverse().join('')) {
x = Math.floor(Math.sqrt(n));
while (n % x !== 0 && x >= 100 && n/x <= 999) {
x--;
}
if (n % x === 0 && x>= 100 && n/x <= 999) {
return n;
}
}
n--;
}
}());
Does anybody know why? I can't find an explanation online. Cheers!

The lone n in the first does not terminate the algorithm, whereas the return n in the second does. This can be fixed by replacing n in the first with a simple break
var n = 999 * 999; //biggest product with 3 digit numbers
var x;
while (n>10000) { //smallest product of 3 digit numbers
if (n.toString() === n.toString().split('').reverse().join('')) {
x = Math.floor(Math.sqrt(n));
while (n % x !== 0 && x >= 100 && n/x <= 999) {
x--;
}
if (n % x === 0 && x>= 100 && n/x <= 999) {
break;
}
}
n--;
}
console.log(n);

Related

Conditional exercise addWithSurcharge

I can't figure why b arguments greater than 20 don't work here. See results
Exercise:
Write a function addWithSurcharge that adds two amounts with surcharge. For each amount less than or equal to 10, the surcharge is 1. For each amount greater than 10 and less than or equal to 20, the surcharge is 2. For each amount greater than 20, the surcharge is 3.
Example: addWithSurcharge(10, 30) should return 44.
function addWithSurcharge(a,b) {
let sur1 = 0
if (a <= 10) {
sur1 = 1;
} else if (10 < a <= 20) {
sur1 = 2;
} else if (a > 20) {
sur1 = 3;
}
let sur2 = 0
if (b <= 10) {
sur2 = 1;
} else if (10 < b <= 20) {
sur2 = 2;
} else if (b > 20) {
sur2 = 3;
}
return a + b + sur1 + sur2;
}
Issue
The reason is that you condition else if (10 < a <= 20) evaluates to true.
10 < a will be evaluated to true
true <= 20 will be evaluated to true.
So the number will evaluated as boolean and every number greater than 0 evaluates to true. That's the reason why true <= 20 evaluates to true
You can check this by this snippet
console.log(true <= 20)
console.log(true <= 0)
console.log(true <= -3)
Solution
To define a range you should use the && operator like this
else if (10 < b && b <= 20)
Then it will
check if 10 < 30 evaluate to true
check if 30 <= 20 evaluate to false
true && false will evaluate to false
function addWithSurcharge(a,b) {
let sur1 = 0
if (a <= 10) {
sur1 = 1;
} else if (10 < a && a <= 20) {
sur1 = 2;
} else if (a > 20) {
sur1 = 3;
}
let sur2 = 0
if (b <= 10) {
sur2 = 1;
} else if (10 < b && b <= 20) {
sur2 = 2;
} else if (b > 20) {
sur2 = 3;
}
return a + b + sur1 + sur2;
}
console.log(addWithSurcharge(10,30))

Why is my FizzBuzz code not outputting correctly?

function counter(numOne, numTwo) {
for (let i = 0; i <= 100; i++) {
if (i % numOne === 0) {
console.log("Fizz");
}
if (i % numTwo === 0) {
console.log("Buzz");
}
if (i % numOne === 0 && i % numTwo === 0) {
console.log("FizzBuzz");
}
else if (i <= 100 && i !== i % numOne === 0 || i !== i % numTwo === 0) {
console.log(i);
}
}
}
counter(3, 5);
For the else if loop, it should console.log all numbers that are <=100, but are not i % numOne === 0 and i % numTwo === 0. So why are only Fizz, Buzz, and FizzBuzz showing up in the output?
Ok, I didn't want to write an answer but since you're new here, I'll put this in a more meaningful way:
function counter(numOne, numTwo) {
for (let i = 0; i <= 100; i++) {
const isFizz = i % numOne === 0
const isBuzz = i % numTwo === 0
if (isFizz && isBuzz) {
console.log("FizzBuzz");
}
else if (isFizz) {
console.log("Fizz");
}
else if (isBuzz) {
console.log("isBuzz")
}
else {
console.log(i);
}
}
}
counter(3, 5);
In your example, you had:
i !== i % numOne === 0
as stated above, there are two issues here:
i !== i can never be true, it's the same value, it's always i === i or in your case false
Since the above is false, you'll have a math equation of: false % numOne this will result in a NaN and NaN does not equal 0
Hope this and the comments above helps understand your issue

How to print the right name in the code below?

for (var i = 1; i <= 50; i++) {
if (i % 15 === 0 || i % 10 === 0) {
console.log("Donkey!");
} else if (i % 2 !== 0 && (i - 1) % 10 === 0) {
console.log("Monkey!");
} else if (i % 7 === 0) {
continue;
} else {
console.log(i);
}
}
emphasized textIf the number is not divisible by 2 and the previous number is divisible by 10, How do I print Monkey!?
This a very random question with no context but has a rather simple solution. Use modulus check if the remainder of the current number divided by 2 is not 0 and check if the remainder of the last number divided by 10 is 0:
function check(n) {
if (n % 2 !== 0 && (n - 1) % 10 === 0) {
console.log('Monkey!');
}
}
check(11)

How does (else) if and || work and which is better?

I don't know how these 2 block of codes executes,they have different outputs, do I have to use else if on the first block, if so, which is faster?
demo
var output = 0;
for (var n = 0; n < 100; n++) {
if (n % 3 === 0) {
output += n;
}
if (n % 5 === 0) {
output += n;
}
}
console.log(output);
/* ------------------------- */
var sum = 0;
for (var x = 0; x < 100; x++) {
if (x % 3 === 0 || x % 5 === 0) {
sum += x;
}
}
console.log(sum);
If you use else if instead of the second if in the first block, you should get the same results.
For example, n=15:
in the first block of code:
you check n%3 === 0 is true, so output is increased by 15
you check n%5 === 0 is true, so output is increased by 15 again
in the second block of code:
you check n%3 === 0 is true, no other checks are done, sum is increased by 15
if you use else if:
you check n%3 === 0 is true, so output is increased by 15
no other checks are done
I believe || and else if speeds are pretty the same. Hope it helps
In the first block of code, for the numbers divisible by 15(lowest common multiple of 3 and 5), sum was getting added twice.
In the second block of code, as its a || statement. Only once sum was added if its a multiple of 15.
Check the third block of code, I added. I am just looking for the sum of the multiples of 15. See its the exact diff you were finding.
var output = 0;
for (var n = 0; n < 100; n++) {
if (n % 3 === 0) {
output += n;
}
if (n % 5 === 0) {
output += n;
}
}
console.log(output);
/* ------------------------- */
var sum = 0;
for (var x = 0; x < 100; x++) {
if (x % 3 === 0 || x % 5 === 0) {
sum += x;
}
}
console.log(sum);
/* ------------------------- */
sum = 0;
for (x = 0; x < 100; x++) {
if (x % 15 === 0) {
sum += x;
}
}
console.log(sum);

Javascript Fizzbuzz Issue

I'm trying to do some simple tests to help further my javascript knowledge (which is quite fresh). Goal 1 is to print numbers from 1-100 that aren't divisible by 5 or 3.
I tried the following:
for (var i = 1; i <= 100; i ++)
{
if (i%3 !== 0 || i%5 !== 0){
console.log(i);
}
}
This logs EVERY number from 1-100, and I can't tell why. Probably the simplest simplest questions here but it's doing my head in!
I think you mean &&, not ||. With ||, you're basically testing to see if the number is not divisible by 3 or by 5 - only if a number is divisible by both do you reject it (in other words, multiples of 15).
The typical answer to FizzBuzz is:
if( i%3 == 0 && i%5 == 0) FizzBuzz
elseif( i % 3 == 0) Fizz
elseif( i % 5 == 0) Buzz
else number
So to get directly to the number you need for i%3==0 to be false AND i%5==0 to be false. Therefore, you want if( i%3 !== 0 && i%5 !== 0)
Here's a quite simple FizzBuzz function that accepts a range of numbers.
function fizzBuzz(from, to) {
for(let i = from; i <= to; i++) {
let msg = ''
if(i % 3 == 0) msg += 'Fizz'
if(i % 5 == 0) msg += 'Buzz'
if(msg.length == 0) msg = i
console.log(msg)
}
}
fizzBuzz(1, 25)
As for a more complex solution, that's one way you could define a higher order function which generates customized FizzBuzz functions (with additional divisors and keywords)
function fizzBuzzFactory(keywords) {
return (from, to) => {
for(let i = from; i <= to; i++) {
let msg = ''
Reflect.ownKeys(keywords).forEach((keyword) => {
let divisor = keywords[keyword]
if(i % divisor == 0) msg += keyword
})
if(msg.length == 0) msg = i
console.log(msg)
}
}
}
// generates a new function
const classicFizzBuzz = fizzBuzzFactory({ Fizz: 3, Buzz: 5 })
// accepts a range of numbers
classicFizzBuzz(1, 25)
const extendedFizzBuzz = fizzBuzzFactory({ Fizz: 3, Buzz: 5, Bazz: 7, Fuzz: 11 })
extendedFizzBuzz(1, 25)
I attacked this the same was as Niet the Dark Absol:
for (var n = 1; n <= 100; n++) {
if (n % 3 == 0 && n % 5 == 0)
console.log("FizzBuzz");
else if (n % 3 == 0)
console.log("Fizz");
else if (n % 5 == 0)
console.log("Buzz");
else
console.log(n);
}
However, you can also do it this way:
for (var n = 1; n <= 100; n++) {
var output = "";
if (n % 3 == 0)
output += "Fizz";
if (n % 5 == 0)
output += "Buzz";
console.log(output || n);
}
One of the hardest parts of learning JavaScript - or any language - for me is understanding solutions can come in many ways. I like the first example more, but it's always good to keep thinking and look at other options.

Categories

Resources