Javascript if/else statements not working - javascript

I am pretty new to Javascript, and it seems like i didnt understand the if else statements correctly.
I have a script which will make the visitor go to 1 of 4 websites, but the 2 last sites in my code does not work.
<script>
setTimeout(function() {
var r = Math.random();
if(r > 0.49) {
window.location.replace("1.html");
}
else if(r < 0.48) {
window.location.replace("2.html");
}
if (r == 0.48){
window.location.replace("maybe.html");
}
else if (r == 0.49){
window.location.replace("4.html");
}
}, 1);
</script>
Is how my code looks like right now. How would it need to look to make it work?

Update
I originally said this looked fine, but I just noticed a problem. There is no branch for r > 0.48 && r < 0.49. Values in this range, such as 0.48342... are more likely than hitting 0.48 or 0.49 exactly, and these are completely unaccounted for, which I assume was not your intention. A simple else branch is always a good idea, or you should account for these cases explicitly.
Original
Your logic looks fine to me. Reduce your problem:
function randomizeText() {
var r = Math.random();
var result = '';
if (r > 0.49) {
result = 'A';
}
else if (r < 0.48) {
result = 'B';
}
else if (r == 0.48){
result = 'C';
}
else if (r == 0.49){
result = 'D';
}
document.getElementById('output').innerText = result;
document.getElementById('random-number').innerText = 'Number was: ' + r;
}
randomizeText();
<button type="button" onclick="randomizeText();">Randomize!</button><br>
<div id="output"></div>
<div id="random-number"></div>
Note that it's going to be very very unlikely that you'll hit either of the last 2 conditions.

You can replace your entire code block with these 2 lines, and they will do what you want:
var r = Math.floor(Math.random() * 4) + 1;
window.location.replace(r+".html");
Explanation:
Your code is actually working. The problem is that the number returned by Math.random() is a random number between 0 and 1 (it might be 0.5544718541204929 ), and will almost NEVER be exactly 0.48 or 0.49, but will almost always be between those two numbers.
A better solution would be:
var r = Math.floor(Math.random() * 4) + 1;
and then test if number is 1, 2, 3 or 4.
Example:
jsFiddle Demo //jsFiddle temporarily not saving fiddles
var r = Math.floor(Math.random() * 4) + 1;
if(r ==1) {
alert("1.html");
}else if(r==2){
alert("2.html");
}else if(r==3){
alert("3.html");
}else{
alert("4.html");
}
BUT there is no need for the entire IF block. Just do this:
var r = Math.floor(Math.random() * 4) + 1;
window.location.replace(r+".html");
//alert( r + ".html" );
In response to the this question, submitted as a comment: I want it to be page 1 and page 2 has is almost 50/50, and the last 2 is pretty rare
This would give odds of 1% for cases 3 and 4.
var r = Math.floor(Math.random() * 100) + 1; //return number between 1 and 100
if(r <=48) {
alert("1.html");
}else if(r<=98){
alert("2.html");
}else if(r==99){
alert("3.html");
}else{ //r==100
alert("4.html");
}
If you desire slightly larger odds:
if(r <=40) { //40% chance
alert("1.html");
}else if(r<=80){ //40% chance
alert("2.html");
}else if(r<=90){ //10% chance
alert("3.html");
}else{ //r is between 91 and 100, 10% chance
alert("4.html");
}

Related

Persistent Bugger - Help to get rid of some 0

I need some help with a task which is about creating a function that only accepts integer numbers to then multiply each other until getting only one digit. The answer would be the times:
Example: function(39) - answer: 3
Because 3 * 9 = 27, 2 * 7 = 14, 1 * 4 = 4 and 4 has only one digit
Example2: function(999) - answer: 4
Because 9 * 9 * 9 = 729, 7 * 2 * 9 = 126, 1 * 2 * 6 = 12, and finally 1 * 2 = 2
Example3: function(4) - answer: 0
Because it has one digit already
So trying to figure out how to solve this after many failures, I ended up coding this:
function persistence(num) {
let div = parseInt(num.toString().split(""));
let t = 0;
if(Number.isInteger(num) == true){
if(div.length > 1){
for(let i=0; i<div.length; i++){
div = div.reduce((acc,number) => acc * number);
t += 1;
div = parseInt(div.toString().split(""))
if(div.length == 1){
return t } else {continue}
} return t
} else { return t }
} else { return false }
}
console.log(persistence(39),3);
console.log(persistence(4),0);
console.log(persistence(25),2);
console.log(persistence(999),4);
/*
output: 0 3
0 0
0 2
0 4
*/
It seems I could solve it, but the problem is I don't know why those 0s show up. Besides I'd like to receive some feedback and if it's possible to improve those codes or show another way to solve it.
Thanks for taking your time to read this.
///EDIT///
Thank you all for helping and teaching me new things, I could solve this problem with the following code:
function persistence(num){
let t = 0;
let div;
if(Number.isInteger(num) == true){
while(num >= 10){
div = (num + "").split("");
num = div.reduce((acc,val) => acc * val);
t+=1;
} return t
}
}
console.log(persistence(39));
console.log(persistence(4));
console.log(persistence(25));
console.log(persistence(999));
/*output: 3
0
2
4
*/
You've got a few issues here:
let div = parseInt(num.toString().split("")); You're casting an array to a number, assuming you're trying to extract the individual numbers into an array, you were close but no need for the parseInt.
function persistence(input, count = 0) {
var output = input;
while (output >= 10) {
var numbers = (output + '').split('');
output = numbers.reduce((acc, next) {
return Number(next) * acc;
}, 1);
count += 1;
}
​
return count;
};
For something that needs to continually check, you're better off using a recurssive function to check the conditions again and again, this way you won't need any sub loops.
Few es6 features you can utilise here to achieve the same result! Might be a little too far down the road for you to jump into es6 now but here's an example anyways using recursion!
function recursive(input, count = 0) {
// convert the number into an array for each number
const numbers = `${input}`.split('').map(n => Number(n));
// calculate the total of the values
const total = numbers.reduce((acc, next) => next * acc, 1);
// if there's more than 1 number left, total them up and send them back through
return numbers.length > 1 ? recursive(total, count += 1) : count;
};
console.log(recursive(39),3);
console.log(recursive(4),0);
console.log(recursive(25),2);
console.log(recursive(999),4);
function persistance (num) {
if (typeof num != 'number') throw 'isnt a number'
let persist = 0
while(num >= 10) {
let size = '' + num
size = size.length
// Get all number of num
const array = new Array(size).fill(0).map((x, i) => {
const a = num / Math.pow(10, i)
const b = parseInt(a, 10)
return b % 10
})
console.log('here', array)
// actualiser num
num = array.reduce((acc, current) => acc * current, 1)
persist++
}
return persist
}
console.log(persistance(39))
console.log(persistance(999))
console.log() can take many argument...
So for example, console.log("A", "B") will output "A" "B".
So all those zeros are the output of your persistence function... And the other number is just the number you provided as second argument.
So I guess you still have to "persist"... Because your function always returns 0.
A hint: You are making this comparison: div.length > 1...
But div is NOT an array... It is a number, stringified, splitted... And finally parsed as integer.
;) Good luck.
Side note, the calculation you are attempting is known as the Kaprekar's routine. So while learning JS with it... That history panel of the recreational mathematic wil not hurt you... And may be a good line in a job interview. ;)
My best hint
Use the console log within the function to help you degug it. Here is your unchanged code with just a couple of those.
function persistence(num) {
let div = parseInt(num.toString().split(""));
let t = 0;
console.log("div.length", div.length)
if (Number.isInteger(num) == true) {
if (div.length > 1) {
for (let i = 0; i < div.length; i++) {
div = div.reduce((acc, number) => acc * number);
t += 1;
div = parseInt(div.toString().split(""));
if (div.length == 1) {
console.log("return #1")
return t;
} else {
continue;
}
}
console.log("return #2")
return t;
} else {
console.log("return #3")
return t;
}
} else {
console.log("return #4")
return false;
}
}
console.log(persistence(39), 3);
console.log(persistence(4), 0);
console.log(persistence(25), 2);
console.log(persistence(999), 4);

Optimizing and finding edge cases that I might have missed - 2 coding interview questions

Background - I took an online coding test and was presented with questions similar to this, I did rather poorly on it compared to the hidden grading criteria and I was hoping to get another pair of eyes to look at it and maybe help point out some of my mistakes.
Practice Test questions -
Task: Given an integer inject the number 5 into it to make the largest possible integer
Conditions: (-80000...80000) range needed to handle
Expected input: int
Expected output: int
Testcase: -999 -> -5999
80 -> 850
var lrgInt = function(num) {
var stringInt = num.toString();
for (let i = 0; i < stringInt.length; i++) {
if (stringInt.charAt(i) === "-") {
return parseInt([stringInt.slice(0, 1), '5', stringInt.slice(1)].join(''));
}else if (stringInt.charAt(i) < 5) {
return parseInt([stringInt.slice(0, i), '5', stringInt.slice(i)].join(''));
}
}
return parseInt([stringInt.slice(0, stringInt.length), '5', stringInt.slice(stringInt.length)].join(''));
};
Task: Determine the number of operations done on a number following the conditions to reduce it to 0.
Conditions:
- If the number is odd, subtract 1
- If the number is even, divide by 2
Expected input: int
Expected output: int
var operations = 0;
var numberOfSteps = function(num) {
if (num === 0){
return operations;
}else if (num % 2 == 0) {
operations++;
return numberOfSteps(num/2);
} else {
operations++;
return numberOfSteps(num-1);
}
};
For the second question, you could add one plus the result of recursion with the adjusted number without having a global counter.
function numberOfSteps(number) {
if (!number) return 0;
if (number % 2) return 1 + numberOfSteps(number - 1);
return 1 + numberOfSteps(number / 2);
}
console.log(numberOfSteps(5)); // 5 4 2 1 0
For the first question, we make the observation that if the number is positive, we want to inject the 5 before the first digit less than 5, but if it's negative then we want to inject it before the first digit greater than 5. For the second problem, we can just use a simple while loop.
function largestNum(num) {
if (num == 0) {
// this edge case is weird but I'm assuming this is what they want
return 50;
}
var negative = num < 0;
var numAsStr = Math.abs(num).toString();
var inj = -1;
for (var i = 0; i < numAsStr.length; i++) {
var cur = parseInt(numAsStr[i], 10);
if ((!negative && cur < 5) || (negative && cur > 5)) {
// we found a place to inject, break
inj = i;
break;
}
}
if (inj == -1) {
// didn't inject anywhere so inject at the end
inj = numAsStr.length;
}
return (
(negative ? -1 : 1) *
parseInt(numAsStr.substr(0, inj) + "5" + numAsStr.substr(inj))
);
}
function numSteps(num) {
var steps = 0;
while (num != 0) {
if (num % 2) {
// it's odd
num--;
} else {
num /= 2;
}
steps++;
}
return steps;
}

Function/Do-while to generate random numbers until they are all the same

(Javascript) My goal is to generate 3 random numbers assigned to a,b, and c. I want to do this over and over until a b and c all are the same number while also keeping track of how many tries it takes. However, the only outcome is my "Error" part that I have added for debugging. Any ideas on where I possibly went wrong?
var a = Math.floor(Math.random() * 6) + 1;
var b = Math.floor(Math.random() * 6) + 1;
var c = Math.floor(Math.random() * 6) + 1;
var runs = 0;
function tripleNumbers() {
while(a!=b && c !=b) {
a = Math.floor(Math.random() * 6) + 1;
b = Math.floor(Math.random() * 6) + 1;
c = Math.floor(Math.random() * 6) + 1;
runs++;
}
if(a == b && a == c) {
document.write("A: "+a);
document.write("B: "+b);
document.write("C: "+c);
document.write("Total Runs: "+runs);
}
else {
document.write("Error");
}
}
tripleNumbers();
In the while loop, you have to use an OR operator (||) instead of AND, because you want to run the loop until either of the inequalities is true:
while(a!=b || c!=b){/*...*/}
Or negate the entire expression, and use positive equality checks:
while(!(a==b && c==b)){/*...*/}
while(a!=b && c !=b) {
The issue is that your logic is being short circuited. a != b && c != b says that you should perform the loop so long as both those conditionals are true.
However, if the first conditional is false, the second one is not evaluated.
So, logically, the most we can assert after that conditional ends is that a == b.
If you want to make sure the loop continues so long as any of the values are different, you should change it to use an OR. That way, for the loop to end, it has to be true that a == b and c == b.

Convert huge if else statement into a loop in Javascript

I'm trying to format a number to be displayed in a more friendly way. At the moment, the code is really difficult to update and it's huge and clumsy.
function abb(){
if(m>=1 && m<999){
gold_display = m;
}else if(m>999 && m<999999){
var b = (m / 1000).toFixed(3);
gold_display = b+"k";
}else if (m>999999 && m<999999999){
var b = (m / 1000000).toFixed(3);
gold_display = b+"m";
}else if (m>999999999 && m<999999999999){
var b = (m / 1000000000).toFixed(3);
gold_display = b+"b";
}else if (m>999999999999 && m<99999999999999){
var b = (m / 1000000000000).toFixed(3);
gold_display = b+"t";
}
}
EDIT: THIS WOULD BE THE CODE:
function abb(){
if(m>=1 && m<1000){
gold_display = m;
}else if(m>999 && m<1000000){
var b = (m / 1000).toFixed(3);
gold_display = b+"k";
}else if (m>999999 && m<1000000000){
var b = (m / 1000000).toFixed(3);
gold_display = b+"m";
}else if (m>999999999 && m<1000000000000){
var b = (m / 1000000000).toFixed(3);
gold_display = b+"b";
}else if (m>999999999999 && m<100000000000000){
var b = (m / 1000000000000).toFixed(3);
gold_display = b+"t";
}
}
Yeah it's akward but it was the only solution that came up into my mind, is there a way to convert this into a loop and shrink the code?
I'm thinking in saving the letters "k", "m", "b","t" in an array because I want to go higher to "q", "qi","s", etc.
Thanks and sorry if the question is kinda stupid :(
Count how many times you need to divide by 1000 before you are under 1000
function bigNumber(big) {
let divisor = 1,
steps = 0,
small = big;
while (small >= 1000) {
divisor *= 1000;
small = big / divisor;
++steps;
}
return {steps, divisor, small};
}
let gold = 123456789,
foo = bigNumber(gold);
foo.small.toFixed(3) + ['', 'k', 'm', 'b', 't'][foo.steps];
// "123.457m"
It's not much but one simplification of your code is to eliminate the lower-bound checking since the if/else-if structure will take care of that:
function abb(m) {
if (m < 1) {
// some kind of error?
} else if (m < 1000) {
return m;
} else if (m < 1000000) {
return (m/1000).toFixed(3) + "k";
} else if (m < 1000000000) {
return (m/1000000).toFixed(3) + "m";
} else {
// and so on
}
}
You could do something more clever but I think it is probably best to be simple about it.
But if I understand your code correctly, you're trying to format numbers as thousands ("k"), millions ("m"), billions ("b") etc. Why not look at a library for this such as http://numeraljs.com/?
Specifically, you can use this code:
var numeral = require('numeral').language('en');
to import the numeral.js library, and then this code to perform the formatting:
var str = numeral(12345678).format("0.0a");// "12.3m"
var str = numeral(1234).format("0.0a");// "1.2k"
etc.
Full disclosure: this solution comes with the benefit of no for loop, but it does have some added complexity.
Take the logarithm of m. If 1 <= m< 999 then 0 <= exponent < 3. Similarly, if 1000 <= m < 999999 then 3 <= exponent < 6, and so on. You can see the pattern here, every prefix covers a range of 3 in the logarithmic scale. So you could do something like the following:
function abb(m){
var prefixes = ["","k","m","b","t"];
var log = Math.log10(m);
var prefixRange = parseInt(log/3, 10);
var prefix = prefixes[prefixRange];
return (m / Math.pow(1000, prefixRange)).toFixed(3) + prefix;
}
Actually, in the case of very large numbers, the above will break, so prefixRange = parseInt(log/3, 10) needs to be changed to prefixRange = Math.min(parseInt(log/3, 10), 4),to ensure we don't read beyond the length of array prefixes.
Also, notice that toFixed is not really to be trusted for large numbers in this case. 999999999 / 1000000 gives 1000.000, which I guess is not what you want. Better to round with floor in this case. Since you are only interested in the first digits (3 for the integer and 3 for the decimal part), you can first get those 6 digits and then divide by 1000.
A better function, addressing both issues is:
function abb(m){
var prefixes = ["","k","m","b","t"];
var log = Math.log10(m);
var prefixRange = Math.min(parseInt(log/3, 10), 4);
var prefix = prefixes[prefixRange];
return Math.floor((m / Math.pow(1000, prefixRange - 1)))/1000 + prefix;
}

javascript value coming up empty not sure how to handle it

function updategeneral() {
//tmp = "fine_" + tmp + "_";
var actual = doc.findItem("1speed").value;
var posted = doc.findItem("2speed").value;
amt = "";
if (1speed != "" && 2speed != "") {
var a = 1 * 1speed;
var b = 1 * 2speed;
if (a - b <= 9) {
alert(amt);
amt = doc.getDefault("general_spb_1_to_15");
} else if (a - b <= 15) {
amt = doc.getDefault("general_spb_16_to_25");
} else if (a - b <= 25) {
amt = doc.getDefault("general_spb_15_to_19");
} else if (a - b <= 29) {
amt = doc.getDefault("general_spb_26+");
}
doc.findItem("mcare_amount").value = amt;
alert(doc.findItem("mcare_amount").value = amt);
}
}
Default values are:
general_spb_1_to_15=30.00 || general_spb_16_to_25=40.00 || general_spb_26+=50.00
My problem is when amt is empty or 0 it is always going to general_spb_1_to_15=30.00. I am not sure how to fix this- can someone please help? The values that I am using are 1speed = 20 and 2speed = 25 which is negative or empty.
Assuming your browser engine is interpreting 1speed and 2speed as variables (some will, some won't -- variable names aren't supposed to start with numbers so it would probably be wise to replace these with speed1 and speed2)...
But assuming that, then the case that you describe is seeing a value of a - b = -5 when processing your if statements, which means that it is being caught by
if (a - b <= 9) {
alert(amt);
amt = doc.getDefault("general_spb_1_to_15");
}
To change the result you are getting, you should add another option to the if statement structure. Perhaps:
if (b > a)
{
//do something for this special case
} else if (a - b <= 9) {
alert(amt);
amt = doc.getDefault("general_spb_1_to_15");
} else if ...
You may also want to specifically handle the case where one or both of speed1/speed2 are empty as an else on the outer if block.

Categories

Resources