string comparison "=" != "+" , incorrect results - javascript

Task is to check whether string results true or false for following given condition:
If a letter a to z occurs it must have '+' before and after the particular letter
This works fine expect the case when '=' comes before or after the letter.
Why this condition is wrong for '=' ?
This code returns true for these strings
Thanks
function SimpleSymbols(str) {
var temp=str.split("")
if(temp.length==1 || temp.length==2 )
return false;
for(i=0;i<temp.length;i++){
if(temp[i]>='a' && temp[i]<='z'){
if(i===0 || i===(temp.length-1)||
(temp[i-1]!=='+' && temp[i+1]!=='+')){
return false;
}
}
}
return true;
}

The condition (temp[i-1]!=='+' && temp[i+1]!=='+') is only true if both the character before and after the letter are not pluses. If one of them is a plus sign the condition is false.
You need to change the logical and to an or operator: (temp[i-1]!=='+' || temp[i+1]!=='+')
Background: De Morgan's Laws
The original condition is that a letter is surrounded by plus signs:
temp[i-1] === '+' && temp[i+1] === '+'
In your if clause you test that this condition is not matched. So, the original condition becomes:
!(temp[i-1] === '+' && temp[i+1] === '+')
To transform this into a condition using not-equals, you need to apply De Morgan's Laws which basically say that a logical and becomes an or and vice-versa if you factor in a negation. This makes the resulting condition:
temp[i-1] !== '+' || temp[i+1] !== '+'

<!-- I think you should change the condition operator -->
function SimpleSymbols(str) {
var temp=str.split("")
if(temp.length==1 || temp.length==2 )
return false;
for(i=0;i<temp.length;i++){
if(temp[i]>='a' && temp[i]<='z'){
if(i===0 || i===(temp.length-1)||
(temp[i-1]!=='+' || temp[i+1]!=='+')){
return false;
}
}
}
return true;
}

Hint: check out these strings too, they all return true even though they should return false.
"+a4"
"1a+"
"%a+"
Let's simplify your condition:
str[i-1] !== '+' && str[i+1] !== '+'
is the same as
!(str[i-1] === '+' || str[i+1] === '+')
This makes it easier to see what you were really checking.
We can see now that the condition str[i-1] !== '+' && str[i+1] !== '+' returns true only if neither of those two characters are a +.
You want it to return true if at least one is not a +. So you should use this instead:
str[i-1] !== '+' || str[i+1] !== '+'
I re-wrote your code with this correct condition here:
function SimpleSymbols(str) {
if (str.length == 1 || str.length == 2) return false;
for (var i = 0; i < str.length; i++) {
if (str[i] >= 'a' && str[i] <= 'z') {
if (i === 0 || i === (str.length-1) || (str[i-1] !== '+' || str[i+1] !== '+')) {
return false;
}
}
}
return true;
}
Note: regular expressions can help out a lot with pattern-matching in strings like this.
E.g. your whole function would have simply become the regex:
function SimpleSymbols(str) {
return !str.match(/[^+][a-z][^+]/) && str.length > 2;
}

Related

Following function must return true if given sequence is valid. Why this function doesn't return true for "||" sequence?

Function must return true for "()" sequence and false for "[)" sequence, so it does. But why this function doesn't return true for "||" sequence? Could you help, please?
I wrote this code, but nothing works :(
function check(s) {
const brackets = {
")": "(",
"]": "[",
"}": "{",
"|": "|",
};
const st = [];
for (let i = 0; i < s.length; i++) {
if (isClosedBracket(s[i])) {
if (brackets[s[i]].toString() !== st.pop()) {
return false;
}
} else {
st.push(s[i]);
}
}
return st.length === 0;
}
//if bracket is in this array, function returns true, so bracket is closing
function isClosedBracket(ch) {
return [")", "]", "}", "|"].indexOf(ch) > -1;
}
Well, since the pipe sequence "||" uses the same character for opening and closing, then when the first | (the opening one) will be encountered, the block of code for the closing bracket will be executed.
Your code works, but it will not operate correctly if the opening character is the same as the closing character. If you absolutely need this feature, then consider adding more checks in this particular situation.
However, the code will get much more complex since a singular | could also mean a closing bracket in an error sequence, so inputs like "(|)" will be a bit complicated to handle.
Thank you all! I solved this problem by adding another if/else block. Here is solution, if you need it =3
function check(str) {
let stack = [];
for (let i = 0; i < str.length; i++) {
if (
+str[i] === 1 ||
+str[i] === 3 ||
+str[i] === 5 ||
str[i] === "(" ||
str[i] === "[" ||
str[i] === "{"
) {
stack.push(str[i]);
} else if (
(+str[i] === 2 && stack.at(-1) === "1") ||
(+str[i] === 4 && stack.at(-1) === "3") ||
(+str[i] === 6 && stack.at(-1) === "5") ||
(str[i] === ")" && stack.at(-1) === "(") ||
(str[i] === "]" && stack.at(-1) === "[") ||
(str[i] === "}" && stack.at(-1) === "{")
) {
stack.pop();
} else if (str[i] !== stack.at(-1)) {
stack.push(str[i]);
} else {
stack.pop();
}
}
return !stack.length > 0;
}
Any ideas how to improve this code?

Why does my test pass, even though it doesn't meet my logic gate?

I'm working on telephone validator on FCC. For some reason this passes 5555555555. Why does my logic gate pass this number? For context, this isn't my first attempt at this code. I've added multiple statements, nested if statements, and it still doesn't catch it. Why does this evaluate to true? Here's the code:
function telephoneCheck(str) {
if(str[0] === '1' || '(' && str.length >= 10) {
return true;
}
else {
return false;
}
}
telephoneCheck("5555555555");
You need to restate the condition you're comparing (|| '(' will always be true):
if(str[0] === '1' || str[0] === '(' && str.length >= 10) {
This is due to the fact that && has a greater precedence than the || operator. So without the parenthesis, the '(' && str.length >= 10 part of the expression is evaluated first. So the ultimate condition becomes str[0] === '1' || true which would always be true. So your code would return true for any string of length >= 10

letters are not counted using OR in javascript. any reason?

Learning javascript I've written this :
function compterNbVoyelles() {
var nombreDeVoyelles = 0;
var mot = "Anaconda";
for (var i = 0; i < mot.length; i++) {
var lettre = mot[i].toLowerCase();
if (lettre === ('a' || 'e' || 'i' || 'o' || 'u' || 'y')) {
nombreDeVoyelles++;
}
}
return nombreDeVoyelles;
}
console.log(mot + " has " + compterNbVoyelles(mot) + " vowels and " + (mot.length - compterNbVoyelles()) + " consonants");
It prints:
Anaconda has 3 vowels and 5 consonants... (there are 4 vowels in fact).
now this :
function compterNbVoyelles(mot) {
var nombreDeVoyelles = 0;
var mot = "Anaconda";
for (var i = 0; i < mot.length; i++) {
var lettre = mot[i].toLowerCase();
if ((lettre === 'a') || (lettre === 'e') || (lettre === 'i') ||
(lettre === 'o') || (lettre === 'u') || (lettre === 'y')) {
nombreDeVoyelles++;
}
}
return nombreDeVoyelles;
}
It prints :
Anaconda has 4 vowels and 4 consonants
Perfect! I don't get what is my mistake, and I assume the computer doesn't make any ;)
The problem lays in your if condition. First you need to understand how short circuit operations in javascript.
While evaluating a condition, javascript is going to perform the least possible amount of work to evaluate a boolean answer.
In the case of || (which is a logical or) if you do:
if (condition1 || condition2 || condition3) {
// do something
}
If condition1 is true then it's only going to evaluate condition1, it will never run through condition2 and condition3 because no matter if they are true of not, the result is going to be true.
If condition2 is false, then it's going to continue evaluating condition2 and stop at the first true condition.
In the case of && (which is a logical and) if you do:
if (condition1 && condition2 && condition3) {
// do something
}
Here the short circuit works differently, it's going to stop evaluating as soon as it meets a false value. Because no matter what the result is going to be false.
Faulty values in Javascript are
false
0
"" (empty string)
null
undefined
NaN (the result of 1/0 for example)
Back to your example:
'a'|| 'e' || 'i' || 'o' || 'u' || 'y'
'a' ALWAYS evaluates to true therefore this entire condition will return you the first truthy value: 'a'
your condition then simplifies to
if (letters === 'a')
How many 'a' do you have in anaconda ? 3 therefore that's why you obtain 3 vowels.
Your second way to build the condition is the correct one. If you want to search for an element in an array you can use Array.indexOf
When you do lettre === ('a'|| 'e' || 'i' || 'o' || 'u' || 'y') it evaluates what's in the brackets first before comparing it with lettre.
Evaluating what's in the brackets will result in just 'a' as that counts as a truthy value, so in the end that line effectively becomes lettre === 'a'
console.log(('a'|| 'e' || 'i' || 'o' || 'u' || 'y'))
.as-console-wrapper { max-height: 100% !important; top: 0; }
whereas in the second (working example) your saying does lettre === 'a' or lettre === 'e' and so on, rather than just comparing it with one value
lettre === ('a'|| 'e' || 'i' || 'o' || 'u' || 'y') is actually equivalent to lettre === ('a'). Try putting x = ('a'|| 'e' || 'i' || 'o' || 'u' || 'y') and see the output. So your answer was just counting a.
Another option is to do something like (['a','e','i','o','u','y']).includes(lettre);

How can I test two strings for equivalence in JavaScript, considering null and empty string the same?

If I compare "a" and "b", that should be false.
If I compare "a" and "a", that should be true.
If I compare "" and null, that should be true.
I could write my own method, but thought there was perhaps a JavaScript shortcut.
Edit: I was thinking something like this:
areDbSame(s1, s2) {
if (s1 === null) s1 = "";
if (s2 === null) s2 = "";
return s1 === s2;
}
Edit2: Settled on this version:
areDbSame(s1, s2) {
return (s1 === null ? "" : s1) === (s2 === null ? "" : s2);
}
Just before you test the equality of your string, you could do a simple one line enforcement, by converting to '' in the case of null. For example (if you also don't care about undefined, false, etc):
// testString becomes the one you are testing
var testString = myString || '';
If you only want to ensure null is blank
var testString = (myString === null) ? '' : myString;
Then you can simply do your string comparisons using testString, and not worry about the null equalities.
IMO this is the cleanest answer because it doesn't convolute the original equality testing of javascript strings. It is the same as saying, let's split the problem up into two parts.
1) When should my string be considered blank, and
2) Now I can just check for regular string equality.
function areEqualStrings(a, b) {
var otherEqualValues = ['', null];
if(typeof a === 'string' && typeof b === 'string') {
return a === b;
} else if(otherEqualValues.indexOf(a) > -1 && otherEqualValues.indexOf(b) > -1) {
return !a === !b;
} else {
return false;
}
}
When coercing JavaScript values, !null is true and !'' is true, so those would result in being equal.
Here's the test (screenshotted from my console):
This function should do it. It type checks first and short circuits otherwise.
function stringCompare(a, b) {
if (((a === null || typeof a === 'string') ||
(b === null || typeof b === 'string')) &&
((a === '' && b === null) ||
(b === '' && a === null) ||
(a === b))) {
return true;
}
return false;
}
No it hasn`t. The two first cases you can do naturally using operator =.
The third case it is impossible because "" is considered a empty string and null has any type. So they never can be true naturally. To do this, you have to write your own method.
Just to be clear. You can use operators = (equal) to do comparison:
== equal to
`x == 8 false
x == 5 true
x == "5" true
=== equal value and equal type
x === 5 true
x === "5" false
Hope it helps

What is the correct syntax for this 'OR' and 'AND' in this 'IF' statement?

I've got an 'if' statement and just wanted to know if these are both valid (which I believe they are) and if so what is the difference?
var type;
var type2;
if ((type == 'BOS'|| type == 'BPS'|| type == 'BRS') && (type2 == 'BOS'|| type2 == 'BPS'|| type2 == 'BRS))
OR
if ((type == 'BOS') || (type == 'BPS') || (type == 'BRS') && (type2 == 'BOS') || (type2 == 'BPS') || (type2 == 'BRS'))
Which has the correct syntax and do they do anything differently? is there a way to shorten this statement?
Thanks
The two statements are different. Yes, they are both valid statements, syntactically, but logically they differ. Since the && operator has a higher precedence than the || in javscript,
the resulting logic will evaluate as follows in statement 2:
1) (type == 'BRS') && (type2 == 'BOS')
2) (type == 'BOS') || (type == 'BPS') || (result of 1) || (type2 == 'BPS') || (type2 == 'BRS')
While in statement 1:
1) (type == 'BOS'|| type == 'BPS'|| type == 'BRS')
2) (type2 == 'BOS'|| type2 == 'BPS'|| type2 == 'BRS')
3) (result of 1) && (result of 2)
var type1;
var type2;
var correct_value = {
BRS: 1,
BOS: 1,
BPS: 1
};
if( correct_value[type1] && correct_value[type2]) {
alert('ok');
}
else {
alert('not ok');
}
Both conditional statement are valid but the result may be different.
The first statement will evaluate the OR value in the first bracket, and then evaluate the OR value in the second bracket, and finally evaluate the AND operator.
The second statement will evaluate the AND first and then evaluate from left to right without specific precedence (as in the first one).
You have to know which one do you actually use to determine the best refactoring code for it.
See this link: Operator Precedence.

Categories