Evaluate triangle by its side - javascript

My question is about using Javascript to do triangle evaluation by its sides. The following code is very initial version even it works. I'd like to know whether it could be more simplifying or there is other way to achieve the same result.
Thanks!
let a = Number(prompt('Please input the the first side (a)'))
let b = Number(prompt('Please input the the second side (b)'))
let c = Number(prompt('Please input the the third side (c)'))
if (a + b <= c || b + c <= a || c + a <= b || Number.isNaN(a) || Number.isNaN(b) || Number.isNaN(c) || a == "" || b == "" || c == ""){
console.log("invalid")
}
else if ((a > 0 && b >0 && c >0 ) && (a == b && b == c && c == a)){
console.log("equilateral triangle")
}
else if ((a > 0 && b >0 && c >0 ) && (a == b || b == c || c == a)){
console.log("isosceles triangle")
}
else {
console.log("scalene triangle")
}

Another way could be to explicitly convert the lengths to a number (0 for NaN) and sort them first. And a ternary operator can be useful here also:
let [d, e, f] = [a, b, c].map(a => +a || 0).sort((a, b) => a-b);
let result = d + e <= f ? "invalid"
: d === f ? "equilateral"
: d < e && e < f ? "scalene"
: "isosceles";
console.log(result);
This will not be the fastest when doing many thousands of them, but I like the look of it.
Explanation
[a, b, c] turns the three values into an array.
.map is a method available for arrays. For each original value in [a, b, c] the following (arrow) function is executed,
a => +a || 0
map creates a new array consisting of the results of calling that function on each separate value (so first with a, then with b and finally with c)
+a uses the unary plus as a short way of turning a value into a number, which means that you could omit the Number() calls you did in the first three lines of your code. When the result of this is NaN or 0, then || 0 will kick in: instead of NaN or 0, 0 will be taken instead (|| is a logical OR operator and 0 will only be used when the left side is considered "falsy"). This practically means that NaN is replaced by 0.
So up to now the code has roughly done something similar to the following:
let newarray = [];
newarray[0] = +a;
if (Number.isNaN(newarray[0])) newarray[0] = 0;
newarray[1] = +b;
if (Number.isNaN(newarray[1])) newarray[1] = 0;
newarray[2] = +c;
if (Number.isNaN(newarray[2])) newarray[2] = 0;
Then another array method is called on that array returned by .map(): the method .sort(). That method will use the provided callback function (a, b) => a-b to make comparisons in the array and sort it based on the values returned by such calls. It is up to the sort method to decide for which pairs this function is called. When the returned value is negative, it means the compared values are already in increasing order. When positive, they should be rearranged. When zero, they should be considered equal to the sort algorithm.
So... we now have an array that consists of numbers which are guaranteed to no longer have a NaN, and which are sorted in ascending order.
Then that array is assigned using so-called destructuring:
let [d, e, f] =
This means that the individual values of the sorted array are assigned one by one to three new variables. So this is roughly short for:
let d = new_sorted_array[0];
let e = new_sorted_array[1];
let f = new_sorted_array[2];
Because these values are now ordered, we can use them for much simpler comparisons to decide on the shape of the triangle. What follows is an expression using a chain of ternary operators which much resemble an if (...) ... else if ... chain. So:
let result = d + e <= f ? "invalid"
: d === f ? "equilateral"
: d < e && e < f ? "scalene"
: "isosceles";
... is short for this:
let result;
if (d + e <= f) result ="invalid"
else if (d === f) result = "equilateral"
else if (d < e && e < f) result = "scalene"
else result = "isosceles";

You can reduce alot of bulk and change the implementation:
You can make the user input a function call
You can place the input into an array
You can use every to make sure every value is greater than 0
You can use a new Set to remove duplicates, if the size is 1, then all sides are the same, if it's 2, then 2 sides are the same, if it's 3, all sides are different
const getSide = l => Number(prompt(`Please input the the second side (${l})`))
const sides = [getSide('a'), getSide('b'), getSide('c')]
if (sides.every(el => el > 0)) {
const size = new Set(sides).size
if (size === 1) console.log("equilateral triangle")
else if (size === 2) console.log("isosceles triangle")
else console.log("scalene triangle")
} else {
console.log("invalid")
}
Test cases:
const test = sides => {
if (sides.every(el => el > 0)) {
const size = new Set(sides).size
if (size === 1) console.log("equilateral triangle")
else if (size === 2) console.log("isosceles triangle")
else console.log("scalene triangle")
} else {
console.log("invalid")
}
}
test([0,1,2]) // invalid
test([NaN,NaN,NaN]) // invalid
test(['',1,2]) // invalid
test([3,3,3]) // eq
test([2,2,3]) // iso
test([1,2,3]) // sca

Related

Generic rules to build numeric multipliers from truth tables

I have some truth tables, mostly AND, based on 0, 1, -1 which I am using for Math operations:
Example 1:
var a,b,c;
if(a == 1 && b == 1) c = 0;
if(a == 1 && b == 0) c = 0;
if(a == -1 && b == 1) c = 0;
if(a == -1 && b == 0) c = 1;
Example 2:
var a,b,c;
if(a === 1 && b === 1) c = 1;
if(a === 1 && b === 0) c = 1;
if(a === -1 && b === 1) c = 1;
if(a === -1 && b === 0) c = -1;
For instance, the first one could be expressed as follows:
c = (a>>1)*(b-1);
I would like to convert also the second truth table using only Math or Bitwise Operators, how can it be done?
Is there any generic rule to easily create such kind of one-line expression?
You can use a generic superoptimizer such as this one I wrote (unfortunately not very user friendly): https://github.com/falk-hueffner/sematrope
This will give you (a + b) >>> 31 for your first example and ((a + b) | b) & a for the second.
For a more systematic approach, you can convert -1/1 to 0/1 by (x >> 1) + 1, do regular logic operations with |&^, and then (if needed) convert 0/1 to -1/1 by x ^ (x - 1).
If a is always 1 or -1 and b is always 1 or 0, and you're OK to use a boolean operator (||), then
c = b || a
should do it...
const c = (a, b) => b || a
console.log(c( 1, 1)) // 1
console.log(c( 1, 0)) // 1
console.log(c(-1, 1)) // 1
console.log(c(-1, 0)) //-1

How to return all whole positive values for a+b = c+d while a,b,c, and d are not equal to each other?

Is there a way I can find all the values between certain parameter such as (1,10) that satisfy a+b = c+d while a,b,c, and d are not equal to each other.
var a;
var b;
var c;
var d;
function findValues (lowerbound, upperbound){
if ((a + b) === (c + d) && (a != b != c != d)) {
//some code
return(values)
}
}
findValues(1,10);
So if I insert 1 into the lower bound and ten into the upper bound it will return all values that meat the conditions in a sorted fashion.
Your code is using the assignment operator (=) in the if statement when you are trying to test for equality.
Replace it with the strict equality comparison (===).
if ((a + b) === (c + d) && (a != b != c != d))
Put your function in a loop where you modify the variables, and return true/false based on the logic above.

is it possible to handle 2 variable to changing if/else condition is true on ES6?

Let say I have a code like this
var a, b;
b = 1;
var c = b > 0 ? a = 1 /*and c = 2*/ : a = 0 /*and c = 1*/;
console.log(a + c);
Is there any way to make c = 2 and a = 1 with above code?
You can wrap the expression inside the ternary with brackets, and use the comma operator to return the number you want to assign to c.
var a, b = 1
var c = b > 0 ? (a=1, 2) : (a=0, 1)
console.log(a, c)
With ES6 you can use destructuring assignment to assign the numbers to a and c:
const b = 1
const [a, c] = b > 0 ? [1, 2] : [0, 1]
console.log(a, c)
As an alternate to #Ori Drori's answer, you can even try something like this:
var b = 1
var a = b > 0 ? 1 : 0;
var c = b + a;
console.log(a, c)
I would recommend an old-fashioned
var a, c, b = 1;
if (b > 0) {
a = 1;
c = 2;
} else {
a = 0
c = 1;
}
console.log(a + c);
If your specific case allows it, you might also do
var a = b > 0 ? 1 : 0;
var c = a + 1;
If you're looking for a way to assign multiple values to multiple variables at once, ES6 destructuring is the solution:
var {a, c} = b > 0 ? {a: 1, c: 2} : {a: 0, c: 1};
One more trick is using below code block
var a,b,c;
b=1;
b > 0 ? ((a=1) && (c = 2)) : ((c = 1) && (a=0));
alert(a + " " + c);
This is the methodology used by the code minifier in Javascript. Such type of statements should be used with precautions. Let me explain how it works
Case b = 1
the condition b > 0 is true. So the first part is evaluated. It has 2 parts with && separated. It means both statements will get evaluated because first statement evaluates totrue (unless first statenent returns false, this is where precaution is needed). Assigning value to some variable returns the same value. So this test case passes.
Case b = -1
the condition b > 0 fails. Again we have 2 statements concatinated with &&, so both statements again gets evaluates. Here you see that I have placed a = 0 as second statement. This is because when I assign a = 0 it will return assigned value that is 0 and in Javascript true = 1 and false = 0. So placing it as first statement will lead to unevaluated second statement.
Hope you understand the scenario and usage care.
The most pretty forward way without confusion would be using comma operator as mentioned in previous answers
var a,b,c;
b=1;
b > 0 ? (a=1, c = 2) : (a = 0, c = 1);
alert(a + " " + c);
The && and , technique is used by code minifier altogether.
DRY coding requires;
var a,
b = 1;
var c = (b > 0 ? a = 1 : a = 0) + 1;
console.log(a + c);

Calculating the Modular Inverse in JavaScript

I am trying to take ed = 1 mod((p-1)(q-1)) and solve for d, just like the RSA algorithm.
e = 5, (p-1)*(q-1) = 249996
I've tried a lot of code in javascript such as:
function modInverse(){
var e = 5;
var p = 499;
var q = 503;
var d = e.modInverse((p-1) * (q-1));
DisplayResult(d, "privateKeyResultLabel")
}
or
function modInverse(){
System.out.println(BigInteger.valueOf(5).modInverse(BigInteger.valueOf(249996)));
}
I just can't figure out the correct way to solve for d, the modular inverse, in javascript.
I was just going through the definition of modular multiplicative inverse and from what I understand:
ax = 1 (mod m)
=> m is a divisor of ax -1 and x is the inverse we are looking for
=> ax - 1 = q*m (where q is some integer)
And the most important thing is gcd(a, m) = 1
i.e. a and m are co-primes
In your case:
ed = 1 mod((p-1)(q-1)) //p, q and e are given
=> ed - 1 = z*((p-1)(q-1)) //where z is some integer and we need to find d
Again from the wikipedia entry, one can compute the modular inverse using the extended Euclidean GCD Algorithm which does the following:
ax + by = g //where g = gcd(a,b) i.e. a and b are co-primes
//The extended gcd algorithm gives us the value of x and y as well.
In your case the equation would be something like this:
ed - z*((p-1)(q-1)) = 1; //Compare it with the structure given above
a -> e
x -> d
b -> (p-1)(q-1)
y -> z
So if we just apply that algorithm to this case, we will get the values of d and z.
For ax + by = gcd(a,b), the extended gcd algorithm could look something like (source):
function xgcd(a, b) {
if (b == 0) {
return [1, 0, a];
}
temp = xgcd(b, a % b);
x = temp[0];
y = temp[1];
d = temp[2];
return [y, x-y*Math.floor(a/b), d];
}
This algorithm runs in time O(log(m)^2), assuming |a| < m, and is generally more efficient than exponentiation.
I don't know if there is an inbuilt function for this in javascript. I doubt if there is, and I am a fan of algorithms, so I thought you might want to give this approach a try. You can fiddle with it and change it to handle your range of values and I hope it gets you started in the right direction.
This implementation of modular inverse can accept any type of inputs. If input types are not supported, NaN is returned. Also, it does not use recursion.
function modInverse(a, m) {
// validate inputs
[a, m] = [Number(a), Number(m)]
if (Number.isNaN(a) || Number.isNaN(m)) {
return NaN // invalid input
}
a = (a % m + m) % m
if (!a || m < 2) {
return NaN // invalid input
}
// find the gcd
const s = []
let b = m
while(b) {
[a, b] = [b, a % b]
s.push({a, b})
}
if (a !== 1) {
return NaN // inverse does not exists
}
// find the inverse
let x = 1
let y = 0
for(let i = s.length - 2; i >= 0; --i) {
[x, y] = [y, x - y * Math.floor(s[i].a / s[i].b)]
}
return (y % m + m) % m
}
// Tests
console.log(modInverse(1, 2)) // = 1
console.log(modInverse(3, 6)) // = NaN
console.log(modInverse(25, 87)) // = 7
console.log(modInverse(7, 87)) // = 25
console.log(modInverse(19, 1212393831)) // = 701912218
console.log(modInverse(31, 73714876143)) // = 45180085378
console.log(modInverse(3, 73714876143)) // = NaN
console.log(modInverse(-7, 87)) // = 62
console.log(modInverse(-25, 87)) // = 80
console.log(modInverse(0, 3)) // = NaN
console.log(modInverse(0, 0)) // = NaN

How can one compare string and numeric values (respecting negative values, with null always last)?

I'm trying to sort an array of values that can be a mixture of numeric or string values (e.g. [10,"20",null,"1","bar","-2",-3,null,5,"foo"]). How can I sort this array such that
null values are always placed last (regardless of sorting order, see jsFiddle)
negative numbers are sorted correctly (i.e. they are less than positive numbers and sort correctly amongst themselves)
? I made a jsFiddle with detailed numeric and string examples (using localeCompare and the numeric option), but will paste the numeric version of my sorting algorithm below as a starting point.
// Sorting order
var order = "asc"; // Try switching between "asc" and "dsc"
// Dummy arrays
var numericArr = [10,20,null,1,-2,-3,null,5];
// Sort arrays
$(".output1").append(numericArr.toString());
numericArr.sort(sortByDataNumeric);
$(".output2").append(numericArr.toString());
// Numeric sorting function
function sortByDataNumeric(a, b, _order) {
// Replace internal parameters if not used
if (_order == null) _order = order;
// If values are null, place them at the end
var dflt = (_order == "asc" ? Number.MAX_VALUE : -Number.MAX_VALUE);
// Numeric values
var aVal = (a == null ? dflt : a);
var bVal = (b == null ? dflt : b);
return _order == "asc" ? (aVal - bVal) : (bVal - aVal);
}
The problem with my string sorting algorithm (see jsFiddle) is that I can't find a way to always place null values last and negative values aren't correctly sorted within themselves (e.g. -3 should be less than -2)
Edit
To answer the comments, I expect [10,"20",null,"1","bar","-2",-3,null,5,"foo"] to sort to [-3,"-2","1",5,10,"20","bar","foo",null,null]
You should first check to see if either value is null and return the opposite value.
On a side note:
For your default _order value, you should check if the parameter is undefined instead of comparing its value to null. If you try to compare something that is undefined directly you will get a reference error:
(undefinedVar == null) // ReferenceError: undefinedVar is not defined
Instead, you should check if the variable is undefined:
(typeof undefinedVar == "undefined") // true
Also, it's probably a better idea to wrap your compare function in a closure instead of relying on a global order variable.
Sometime like:
[].sort(function(a, b){ return sort(a, b, order)})
This way you can sort at a per-instance level.
http://jsfiddle.net/gxFGN/10/
JavaScript
function sort(a, b, asc) {
var result;
/* Default ascending order */
if (typeof asc == "undefined") asc = true;
if (a === null) return 1;
if (b === null) return -1;
if (a === null && b === null) return 0;
result = a - b;
if (isNaN(result)) {
return (asc) ? a.toString().localeCompare(b) : b.toString().localeCompare(a);
}
else {
return (asc) ? result : -result;
}
}
function sortByDataString(a, b) {
if (a === null) {
return 1;
}
if (b === null) {
return -1;
}
if (isNumber(a) && isNumber(b)) {
if (parseInt(a,10) === parseInt(b,10)) {
return 0;
}
return parseInt(a,10) > parseInt(b,10) ? 1 : -1;
}
if (isNumber(a)) {
return -1;
}
if (isNumber(b)) {
return 1;
}
if (a === b) {
return 0;
}
return a > b ? 1 : -1;
}
fiddle here: http://jsfiddle.net/gxFGN/6/
I left out the order parameter, but you could always reverse the array at the end if needed.
Use this:
function typeOrder(x) {
if (x == null)
return 2;
if (isNaN(+x))
return 1;
return 0;
}
function sortNumber(a, b) {
a = parseInt(a, 10); b = parseInt(b, 10);
if (isNaN(a) || isNaN(b))
return 0;
return a - b;
}
function sortString(a, b) {
if (typeof a != "string" || typeof b != "string")
return 0;
return +(a > b) || -(b > a);
}
order = order == "dsc" ? -1 : 1;
numericArr.sort(function(a, b) {
return order * ( typeOrder(a)-typeOrder(b)
|| sortNumber(a, b)
|| sortString(a, b)
);
});
(updated fiddle)
I'm pretty sure that your problem is a red herring... the abstract function that you past into sort doesn't get a third parameter (in your case _order). So in your situation that's always going to be undefined.
Please reconsider your code with that in mind and see what you get.
The array you specify is entirely Numeric so your sort should work correctly, though as other commenters have suggested, if your array ever winds up with string values (i.e. "10", "-7" etc) you'll want to parseInt and test for isNaN before doing your comparison.

Categories

Resources