Logic concerning negative num inputs being converted to positive num inputs - javascript

Maybe I'm asking google all the wrong questions but I scoured the internet and could not find posts similar to my unique problem.
This is a simple coding challenge from FreeCodeCamp:
I need to work on the function abTest(a,b) where when a OR b is less than 0, the function will exit with the value of undefined. This is because we run the value a and b through a square root function. And you cannot take the square root of a negative number. Below is the code.
// Setup
function abTest(a, b) {
if (a < 0) {
a = -a;
return undefined;
} else if (b < 0) {
b = -b;
return undefined;
}
return Math.round(Math.pow(Math.sqrt(a) + Math.sqrt(b), 2));
}
// Change values below to test your code
abTest(2,2);
This code I used above works fine. However I have to specify that when a or b is < 0, a is assigned -a and b is assigned -b. Why is this necessary? In addition I want to convert this into a Switch statement, but I run into this problem of negative num values. Below are two switch statements I wrote but when using negative num input the abTest(-2,2) or abTest(2,-2) does not return the value undefined.
My First Switch Statement
switch (a,b) {
case a<0 || b<0:
return undefined;
}
My Second Switch Statement
switch (a,b) {
case a < 0:
a = -a;
console.log(undefined);
break;
case b < 0:
b = -b;
console.log(undefined);
break;
}
Where is this hole in my logic concerning switch statements and negative num values?
Thank you guys,

There should be no need to convert a = -a unless there is something wrong with freecodecamp. Just returning the value of undefined would/should produce the exact same result as changing a variable and then still returning undefined. To simplify your code you could also combine the if and else if statements like so
function abTest(a, b) {
if (a < 0 || b < 0){
return undefined;
} else {
return Math.round(Math.pow(Math.sqrt(a) + Math.sqrt(b), 2));
}
}
hope this helps

Related

freeCodeCamp Golf code but with Ternary operators instead of else if [duplicate]

I have a function to check sums in an array :
function checkSum(array, sum) {
// array = [1,4,6,11] sum = 10
var answers = [];
var map = new Map();
for (var x = 0; x < array.length; x++) {
if (map.has(array[x])) {
answers.push([sum - array[x], array[x]])
} else {
map.set(sum - array[x])
}
}
answers.length != 0 ? console.log(answers) : console.log("nada")
}
I originally had the last line just return answers; but let's say I don't want to return an empty array -- instead, I'd rather just log a statement.
why doesn't a return in a ternary conditional work such as this:
answers.length != 0 ? return answers : console.log("nada")
You need to use return answers.length != 0 ? answers : console.log("nada"). The reason it fails is because ternary conditions do not support return in their conditions. Infact, the ternary operator evaluates to an expression and expressions do not contain a return statement.
function checkSum(array, sum) {
// array = [1,4,6,11] sum = 10
var answers = [];
var map = new Map();
for (var x = 0; x < array.length; x++) {
if (map.has(array[x])) {
answers.push([sum - array[x], array[x]])
} else {
map.set(sum - array[x])
}
}
return answers.length != 0 ? answers : console.log("nada")
}
console.log(checkSum([1, 4, 6, 11], 10));
The ternary (conditional) operator expects the "expr1" part (where return answers is) to be an expression - that is, something that can be evaluated to a value, which can be used in other expressions. But a return statement is a statement, one which cannot possibly be interpreted as value, or as an expression; hence, a syntax error is thrown.
Instead of
answers.length != 0 ? console.log(answers) : console.log("nada")
either use a standard if statement:
if (answers.length !== 0) return answers;
console.log('nada');
or, if you just want to log, put the conditional operator inside the console.log instead:
console.log(
answers.length === 0
? 'nada'
: answers
)
I used ternary operators like this a lot in the past. It's fun, and keeps it to one line.
It can certainly be done, as Ankit shows, by putting the return statement out front
return answers.length != 0 ? answers : console.log('nada')
But I would recommend you use a classic if statement for this. Particularly since you're testing whether to return a value or just log one.
if (answers.length != 0) {
return answers;
};
console.log('nada')
I would go even further and recommend that you return the same value type no matter what. This will go a long way for using your function, well - functionally. In this case, that would involve still returning the array (even if it's empty) and logging the nada as well if empty.
if (answers.length == 0) {
console.log('nada');
};
return answers;

How to fix a recursive hcf function?

I tried to make an HCF function in javascript using recursive functions as given in the code below. But somehow this only works for exact multiples of numbers (like 2,4 ; 52,104 etc). Co-prime numbers also gives 'undefined'. Please help me fix the bug.
I have tried substituting a local scope variable c = a % b. But this doesn't work out either.
The code:
function hcf(a, b) {
if (b == 1){
return 1;
} else if (a % b == 0){
return b;
} else {
hcf(a,a % b);
}
}
Test cases:
hcf(4,2);
hcf(108,52);
hcf(9,4);
Expected Outcomes:
2
4
1
Actual Outcomes:
2 [Correct]
undefined [Incorrect]
undefined [Incorrect]
The recursive case needs a return statement.

Longest common subsequence (Why does this recursive solution not work?)

Trying to write a similar recursive solution to the one described on: http://www.geeksforgeeks.org/longest-common-subsequence/ but it does not work. It outputs one. Anyone have an idea of why?
LCS_seq_req = (str1, str2) => {
m=str1.length;
n=str2.length;
str1_cut = str1.slice(0, m-1)
str2_cut = str2.slice(0, n-1)
if (m===0 || n===0) {
return 0
}
else if (str1.slice(m-1, m) === str2.slice(n-1, n) ) {
return LCS_seq_req(str1_cut, str2_cut) + 1
} else {
res_1 = LCS_seq_req(str1_cut, str2)
res_2 = LCS_seq_req(str1,str2_cut)
return Math.max(res_1, res_2)
}
}
LCS_seq_req("AGGTAB", "GXTXAYB")
In JavaScript, unlike (say) Python, assigning to a variable inside a function does not implicitly declare it as a local variable. Instead, you need to explicitly declare it using the var keyword; otherwise you get a global variable.
More specifically, your problem is that this line:
res_1 = LCS_seq_req(str1_cut, str2)
has the side-effect of mutating the global variable str2_cut, causing this line:
res_2 = LCS_seq_req(str1,str2_cut)
to compute the wrong value. If you add var in the right places, you'll get the right answer.
Incidentally, Eric Lippert has written a blog post, https://ericlippert.com/2014/03/05/how-to-debug-small-programs/, which gives very good advice for how to debug this sort of problem on your own.
I looked at the Naive recursive Python implementation of LCS problem you give and converted Python code into JS code. Hope it will help.
LCS_seq_req = (str1, str2, m, n) => {
if(m == 0 || n == 0)
return 0;
else if(str1.charAt(m-1) === str2.charAt(n-1))
return 1 + LCS_seq_req(str1, str2, m-1, n-1);
else
return Math.max(LCS_seq_req(str1, str2, m, n-1), LCS_seq_req(str1, str2, m-1, n));
}
var X = "AGGTAB";
var Y = "GXTXAYB";
console.log(LCS_seq_req(X , Y, X.length, Y.length)); //6

checking array length in switch statement

I am looking at using a switch statement to check if an array's length is greater than 0. I could do this using an if/else statement but I want to get more comfortable using switch statements and am slightly baffled why the following doesn't work.
Given an array of numbers, my function determines whether the sum of all of the numbers is odd or even.
Here is what it looks like:
function oddOrEven(array) {
switch(array) {
case array.length === 0:
throw 'Error';
break;
case array.length > 0:
answer = array.reduce((a, b)=>{
return a + b;
}) % 2 === 0 ? 'even' : 'odd';
break;
}
}
examples
oddOrEven([0]) returns "even"
oddOrEven([2, 5, 34, 6]) returns "odd"
oddOrEven([0, -1, -5]) returns "even"
I know I can do if(array.length > 0)... but as I said I want to get used to using switch statements and thought that this should also work.
With switch, you compare an expression to values, doing an action for each one. In your case, you could switch the array.length like that:
function oddOrEven(array) {
switch(array.length) {
case 0:
throw 'Error';
break;
default: // in that case, array.length != 0, not > 0 necessarily
answer = array.reduce((a, b)=>{
return a + b;
}) % 2 === 0 ? 'even' : 'odd';
break;
}
}
However, in my opinion, if/else is the right one to be used here. It is worth to take a look at MDN documentation for switch to understand the best scenarios in which it can be used.
The idiomatic usage of the switch statement would be as follows:
switch(array.length) {
case 0: // ...
default: // ...
}
However, you are right in assuming that expressions can be used instead of values in the case labels. The following will work:
function oddOrEven(array) {
switch (true) {
case array.length === 0:
throw 'Error';
case array.length > 0:
return array.reduce((a, b) => a + b) % 2 === 0 ? 'even' : 'odd';
}
}
console.log(oddOrEven([0]));
console.log(oddOrEven([2, 5, 34, 6]));
Obviously, using an if statement is the more readable approach in this case.
I don't think it's a good practice to do switch statements to check an array length. You should rather do it like this:
function oddOrEven(arr) {
if(arr.length === 0) {
throw 'Error';
}
return array.reduce((a, b)=>{
return a + b;
}) % 2 === 0 ? 'even' : 'odd';
}

How to avoid short-circuited evaluation in JavaScript?

I need to execute both sides of an && statement, but this won't happen if the first part returns false. Example:
function doSomething(x) {
console.log(x);
}
function checkSomething(x) {
var not1 = x !== 1;
if (not1) doSomething(x);
return not1;
}
function checkAll() {
return checkSomething(1)
&& checkSomething(3)
&& checkSomething(6)
}
var allValid = checkAll(); // Logs nothing, returns false
The problem here is that doSomething(x) should log 3 and 6, but because checkSomething(1) returns false, the other checks won't be called. What is the easiest way to run all the checks and return the result?
I know I could save all the values in variables and check those subsequently, but that does not look very clean when I have a lot of checks. I am looking for alternatives.
Use a single &. That is a bitwise operator. It will execute all conditions and then return a bitwise sum of the results.
function checkAll() {
return checkSomething(1)
& checkSomething(2)
& checkSomething(3)
}
You can multiply the comparison result and cast it to boolean.
function checkSomething(x) {
var not1 = x !== 1;
if (not1) alert(x);
return not1;
}
function checkAll() {
return !!(checkSomething(1) * checkSomething(2) * checkSomething(3));
}
document.write(checkAll());
Or take some array method:
function checkAll() {
return [checkSomething(2), checkSomething(2), checkSomething(3)].every(Boolean);
}
Coming back to my own question 2,5 years later I can agree with the people in the comments on how bad this code is by being based on side effects and therefore violating the single responsibility principle.
I just want to provide a proper solution for people visiting this page with the same question.
function doSomething(x) {
console.log(x);
}
function checkSomething(x) {
return x !== 1;
}
var values = [1, 3, 6];
var validValues = values.filter(checkSomething); // -> [3, 6]
validValues.forEach(doSomething); // -> Logs 3 and 6
var allValid = validValues.length === values.length; // false
As you can see, the checkSomething function now only does one thing: check something. The doSomething logic runs separately after all the checks are done.
A function should always either do something or return something, not both. Of course there are exceptions to this, but it is a good rule of thumb. This makes the code more predictable, testable and understandable.
Now, if at some point I want to check if all values are valid without "doing something", I can actually do this...
var allValid = checkSomething(1) && checkSomething(3) && checkSomething(6);
...without having to worry about side effects.
Conclusion: You don't want to avoid short circuited evaluation

Categories

Resources