javascript value coming up empty not sure how to handle it - javascript

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.

Related

functions result is NaN

I am really new in coding therefore I am coding currently a Taximeter. Unfortunately is the result of my code when executing NaN in the console. I tried some ways to rectify my problem but those attempts did not work. I think that some variables are not in the right scope but I do not know how to fix that.
function Taximeter() {
const y = 3.9;
const km = prompt("How far is your target");
if (km <= 7) {
var routePrice = 2.3;
} else if (km > 7) {
let routePrice = 1.65;
var subtractedLength = (km -= 7);
var partialExpenses = (subtractedLength *= routePrice);
var tosevenExpenses = 7 * 2.3;
var combinedExpenses = (tosevenExpenses += partialExpenses);
}
const persons = prompt("How much persons are driving with you?");
if (persons > 8) {
console.log("Only 8 persons can drive with you.");
} else if (8 >= persons >= 5) {
var personsExpenses = 5;
} else if (0 >= persons >= 4) {
personExpenses = 0;
}
if (km <= 7) {
var wholeExpenses = y + km * routePrice + personsExpenses;
} else {
var wholeExpenses = combinedExpenses + y + personsExpenses;
}
console.log(wholeExpenses);
}
It would be helpful to know where exactly NaN is coming up and whether or not you are seeing NaN as the result of an Exception (if an error message was logged to the console) or if NaN is coming up as a result of your own console.log() statements. Part of the issue could be that the function prompt() returns a String, meaning that your variable km is going to be a String and not a Number. Use this line of code instead and it might fix your problem:
const km = parseInt(prompt("How far is your target"));
EDIT:
In response to your comment, there are a couple other issues I see here. There is the issue with your first if and else if clauses where the indentation is a little off. This, as far as I can tell, should not actually affect your code, but it does make it harder to read. Here is how it should look:
if (km <= 7) {
var routePrice = 2.3;
} else if (km > 7) {
let routePrice = 1.65
var subtractedLength = km -= 7;
var partialExpenses = subtractedLength *= routePrice ;
var tosevenExpenses = 7 *2.3;
var combinedExpenses = tosevenExpenses += partialExpenses;
};
Second, in those same if and else if clauses, you use the -=, *=, and += operators when they are unnecessary and may cause errors. I've never seen them used the way that you have before, so I don't know if they actually cause errors, but I would edit those clauses one more time for readability at least:
if (km <= 7) {
var routePrice = 2.3;
} else if (km > 7) {
let routePrice = 1.65
var subtractedLength = km - 7;
var partialExpenses = subtractedLength * routePrice ;
var tosevenExpenses = 7 *2.3;
var combinedExpenses = tosevenExpenses + partialExpenses;
};
Like with km I would also edit your persons declaration to turn that variable into a Number so that the logic operators that you use on it later work properly:
const persons = parseInt(prompt("How much persons are driving with you?"));
Another thing, like a commenter earlier pointed out, 8 >= persons >= 5 will not work the way you think it will - just edit those if and else if clauses like so to fix that error:
if (persons > 8) {
console.log("Only 8 persons can drive with you.");
} else if(persons >= 5 && persons <= 8) {
var personsExpenses = 5;
} else if (persons <= 4 && persons >= 0) {
personExpenses = 0;
};
Finally, your variable declaration of personsExpenses is such that the variable will only be declared if that first else if clause resolves. You need personsExpenses to be declared no matter what, so I would declare it before and outside of any of those conditional clauses:
var personsExpenses
if (persons > 8) {
console.log("Only 8 persons can drive with you.");
} else if(persons >= 5 && persons <= 8) {
personsExpenses = 5;
} else if (persons <= 4 && persons >= 0) {
personExpenses = 0;
};
That's everything that I noticed, so good luck!

Caesar Cipher technique and reverse case in javascript

I am beginner and want to make my own function.
I want to hash the password by shifting every character by given x
positions and reverse to lowercase/uppercase.
I think the code below should return "EFGH7654" but it return 55 with no error message.
How can I fix it? Is it because of I put a function in a function?
Or I type wrong any thing?
function hashPassword(password, x) {
// password is a string, x is a number
// return a string
// (ex. password = 'ab1By', x = 3 so it should return "DE4eB")
function shift(text, s) {
result = "";
for (let i = 0; i < text.length; i++) {
let char = text[i];
if (char.toUpperCase(text[i])) {
let ch = String.fromCharCode((char.charCodeAt(0) + s - 65) % 26 + 65);
result += ch;
} else {
let ch = String.fromCharCode((char.charCodeAt(0) + s - 97) % 26 + 97);
result += ch;
}
}
return result;
}
function reversecase(x) {
var output = '';
for (var i = 0, len = x.length; i < len; i++) {
var character = x[i];
if (character == character.toLowerCase()) {
// The character is lowercase
output = output + character.toUpperCase();
} else {
// The character is uppercase
output = output + character.toLowerCase();
}
}
return output
}
var str = "";
var result = "";
var charcode = "";
for (var i = 0; i < password.length; i++) {
if (typeof password[i] === typeof str) {
char = shift(password[i], x)
charcode = reversecase(char)
result += charcode;
} else {
num = password[i] + x
number = num % 10
result += number.toString()
}
}
return result
};
console.log(hashPassword("abcd4321", 4))
There a quite some problems in your code.
The first problem here is not only the nesting, but the fact that you're defining the result variable in the outer function scope using the var keyword. Then you use (read/write) that variable in different places.
In function shift() (also in return statement)
In the outer function (also in return statement)
The thing you have to understand is, that you're referring to the same variable result every time. To ensure that your variables are scoped, i.e. are only valid within a block (if statement, function body, etc.), you should use the let or const keywords. This makes your code a lot safer.
The second problem are some assumptions you make regarding data types. If you have a string let s = "my string 123", the expression typeof s[x] === 'string' will be true for every x in s.
Another problem is the algorithm itself. The outer function hashPassword() iterates over all characters of the input string. Within that loop you call function shift(password[i], x), passing a single character. The first parameter of shift() is called text - and there is another for loop (which is confusing and does not make sense).
To make things short, please have a look at this simplified version:
function shift(char, x) {
let result;
const code = char.charCodeAt(0);
if (code >= 65 && code < 91) {
result = String.fromCharCode((code + x - 65) % 26 + 65);
}
else if (code >= 48 && code <= 57) {
result = String.fromCharCode((code + x - 48) % 10 + 48);
}
else {
result = String.fromCharCode((code + x - 97) % 26 + 97);
}
return result;
}
function reverseCase(character) {
if (character === character.toLowerCase()) {
return character.toUpperCase();
}
else {
return character.toLowerCase();
}
}
function hashPassword(password, x) {
let result = "";
for (let i = 0; i < password.length; i++) {
const char = shift(password[i], x);
result += reverseCase(char);
}
return result;
}
console.log(hashPassword("abcd4321", 4)); // Output: EFGH8765

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;
}

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;
}

Determine Document Order from Nodes

If I have two nodes in an HTML document, how can I tell which one comes first in HTML document order in Javascript using DOM methods?
For example,
function funstuff(a, b) {
//a and b can be any node in the DOM (text, element, etc)
if(b comes before a in document order) {
var t = b; b = a; a = t;
}
// process the nodes between a and b. I can handle this part
// when I know that a comes before b.
}
Resig to the rescue:
// Compare Position - MIT Licensed, John Resig
function comparePosition(a, b){
return a.compareDocumentPosition ?
a.compareDocumentPosition(b) :
a.contains ?
(a != b && a.contains(b) && 16) +
(a != b && b.contains(a) && 8) +
(a.sourceIndex >= 0 && b.sourceIndex >= 0 ?
(a.sourceIndex < b.sourceIndex && 4) +
(a.sourceIndex > b.sourceIndex && 2) :
1) +
0 :
0;
}
You can use the DOM function compareDocumentPosition which will return different numbers based on the two nodes' relationships:
DOCUMENT_POSITION_DISCONNECTED = 0x01;
DOCUMENT_POSITION_PRECEDING = 0x02;
DOCUMENT_POSITION_FOLLOWING = 0x04;
DOCUMENT_POSITION_CONTAINS = 0x08;
DOCUMENT_POSITION_CONTAINED_BY = 0x10;
Potentially the result could be the sum of more than one of these codes as the answer is a bitmask, but I can't imagine a situation where two of these conditions would be true at the same time. Also note that the "disconnected" result would be returned for instance with nodes that have been created but not added to the document tree yet
Rather difficult, I personally would itterate up each tree till I found a common ansester, then check which parent node(or the actual node if that low) comes first starting with firstChild and working through siblings, something like:
function OrderCheck(node1, node2){
var ar1 = [null, node1];
var ar2 = [null, node2];
for(var i = 1; ar1[i] != null; i++)
ar1[i+1]=ar1[i].parentNode;
for(var i = 1; ar2[i] != null; i++)
ar2[i+1]=ar2[i].parentNode;
ar1.reverse(); ar2.reverse(); // easier to work with.
i = 0;
while( ar1[i] === ar2[i] ){
if(ar1[i] === null)
return 0;
else
i++
}
if(ar1[i] === null)
return 2;
if(ar2[i] === null)
return 1;
if(i != 0){
var n = ar1[i-1].firstChild;
do{
if(n === ar1[i])
return 1;
if(n === ar2[i])
return 2;
}while(n = n.nextSibling);
}
return -1;// Shouldn't happen.
}
var order = OrderCheck(document.body, document.body.previousSibling);
if( order == 1){
// element 1 first
}else if(order == 2){
// element 2 first
}else{
// there was an error.
}
I did just edit this code in an attempt to fix two possible problems, I haven't tested this new edit however, so if something breaks I shall have to try again. (Edited again to fix a "doesn't even run" style bug).

Categories

Resources