I'm attempting to solve the following problem from coderbyte.com:
Using the JavaScript language, have the function SimpleSymbols(str) take the str parameter being passed and determine if it is an acceptable sequence by either returning the string true or false. The str parameter will be composed of + and = symbols with several letters between them (ie. ++d+===+c++==a) and for the string to be true each letter must be surrounded by a + symbol. So the string to the left would be false. The string will not be empty and will have at least one letter.
The following is my attempt:
function SimpleSymbols(str) {
// code goes here
var abc = 'abcdefghijklmnopqrstuvwxyz';
for (var i = 0; i < str.length; i++) {
if (abc.indexOf(str[i]) !== -1) {
if (str[i-1] + str[i+1] === "++") {
return true;
}
else {
return false;
}
}
}
}
This works for the following cases:
SimpleSymbols("+a+d+"); // true
SimpleSymbols("+ab+d+"); // false
SimpleSymbols("b+d+"); // false
The only case I have found where this doesn't provide the right answer is when there is a trailing letter, for example:
SimpleSymbols("+a+b"); // true
This returns true, when in fact it should return false.
NB: I'm assuming string will be lowercase... I haven't dealt with case sensitivity, but I'd like to get the lowercase version working and then I will make it case independent.
Any ideas on what is wrong with my code?
I interpret this as: There is no letter which is not preceded/followed by a character other than plus (including none):
function SimpleSymbols(str) {
return !/^[a-z]|[^+][a-z]|[a-z][^+]|[a-z]$/i.test(str)
}
You may use a regex:
function SimpleSymbols(str) {
if (/^[a-zA-Z]/.test(str) || /[a-zA-Z]$/.test(str)) {
return false;
}
else if (/[^+][a-zA-Z]/.test(str) || /[a-zA-Z][^+]/.test(str)) {
return false;
}
else {
return true;
}
}
or
function SimpleSymbols(str) {
var arr = str.toLowerCase().split("");
for (var i = 0; i < arr.length; i++) {
if (arr[i] >= "a" && arr[i] <= "z") {
if (i === 0 || i === arr.length) {
return false;
}
if (arr[i-1] !== "+" || arr[i+1] !== "+") {
return false;
}
}
}
return true;
}
This returns 'true' on the first successful letter surrounded by + symbols, it doesn't continue checking thru to the end.
I also wonder whether string indices would be out-of-bounds [i-1], [i+1] on the first/last character? It appears not, but I can't find a language ref.
Better:
function SimpleSymbols(str) {
var abc = 'abcdefghijklmnopqrstuvwxyz';
for (var i = 0; i < str.length; i++) {
if (abc.indexOf(str[i]) !== -1) {
if (str[i-1] + str[i+1] != "++") {
return false;
}
}
}
return true;
}
There are also probably performance improvements that could be made (checking bounding characters by AND rather than by string addition), and you could also do it by a regex.
By regex:
if (str.search( /[^+][a-z]/) >= 0) // will match letters with no + beforehand.
return false;
if (str.search( /[a-z][^+]/) >= 0) // will match letters with no + afterward.
return false;
return true;
I believe this is a perfect regex case
Check the regex ^[^a-z]*(\++[a-z]\++[a-z]?)*[^a-z]*$ explained in here
Use it in javascript like this:
function SimpleSymbols(str) {
return !/^[^a-z]*(\++[a-z]\++[a-z]?)*[^a-z]*$/i.test(str);
}
export const simpleSymbols = (str) => {
const arr = str.split('')
let k = []
arr.forEach(element => {
if((/[a-zA-Z]/).test(element)){
if(arr[arr.indexOf(element)-1]==="+" && arr[arr.indexOf(element)+1]==="+"){
k.push(1)
}else{
k.push(0)
}
}
});
if(k.includes(0)){
return false
}else{
return true
}
}
Related
This question already has answers here:
Javascript Pangram Regex
(9 answers)
Closed 5 months ago.
Summary of problem:
Essentially I want to perform the following function:
function isPangram(string){
if (all characters a - z are present in the string) {
return true;
} else {
return false;
}
}
Here's what I've tried thus far:
function isPangram(string){
if (string.contains(/[a-z]/)) {
return true;
} else {
return false;
}
}
function isPangram(string){
if (string.matchAll(/[a-z]/) {
return true;
} else {
return false;
}
}
function isPangram(string){
for (let i = 0; i < string.length; i++) {
if (string[i] = /[a-z]/) {
return true;
} else {
return false;
}
}
I've laid out the problem and I have the solution but I'm unaware of the proper syntax that allows me to get the solution I'm looking for. So! I'm asking for syntax recommendations that can help lead me in the right direction. I can struggle from there~
Try using this expression:
new Set("<your_string>".toLowerCase().replace(/[^a-z]/g, "") ).size === 26
A way to accomplish that could be iterating all characters in test string, and match each character against an "alphabet" array. If character is found, then it gets removed from the alphabet.
When all characters are scanned, if alphabet doesn't contain any elements, it means test string contained all characters in the alphabet.
const alphabet = []
//const testString = '123badcfehgjilknmporqtsvuxwzy000'
const testString = '123badcfehgtsvuxwzy000'
// POPULATE alphabet WITH ASCII CHARACTERS CODES FROM a TO z
for (let i = 97; i < 123; i++) {
alphabet.push(i)
}
// SCAN ALL CHARACTERS IN testString
for (let i = 0; i < testString.length; i++) {
let pos = alphabet.indexOf(testString[i].charCodeAt(0))
if (pos != -1) {
// IF CURRENT CHARACTER IS PRESENT IN OUR alphabet ARRAY, REMOVE IT
alphabet.splice(pos, 1)
}
}
if (alphabet.length == 0) {
console.log('All alphabet letters found in test string')
} else {
console.log('These alphabet letters were not found: ', alphabet.map(c => String.fromCharCode(c)) )
}
I am trying to solve this problem
Given an string and a dictionary of words, find out if the input string can be broken into a space-separated sequence of one or more dictionary words.
dictionary = ["I" , "have", "Jain", "Sumit", "am", "this", "dog"]
String = "IamSumit"
Output: "I am Sumit"
String ="thisisadog"
Output : String can't be broken
My function is giving me boolean output instead of string result I tried like this return result;. still returning boolean
const find = (S,dic ,result) =>{
if (S.length === 0) {
console.log(result,'kkkk')
return result;
}else {
let index = 0,
word = "";
while (index < S.length){
word += S.charAt(index);
if (dic.indexOf(word) !==-1) {
if (find(S.substring(index + 1), dic, result + word + " ")) {
return true;
} else {
//System.out.println(word + " backtrack");
index++;
}
}else{
index++;
}
}
}
return false
}
console.log(find("thisisadog",["I" , "have", "Jain", "Sumit", "am", "this", "dog"],''))
I understood what you need to do, but I didn't well understand how your code works, so I implemented my version of it.
const splitStringFromDict = (str, dict) => {
let index = 0, word = "", result = [];
while (index < str.length) {
word += str.charAt(index);
if (dict.indexOf(word) !== -1) {
result.push(word);
word = ""
}
index++;
}
if (word !== "") result.push(word);
for (word of result) {
if (dict.indexOf(word) === -1){
return "String can not be broken";
}
}
return result.join(' ');
}
It's not an recursive function, and I think it's slightly easier to follow.
Now, I should probably emphasise that naming a function by the same name of an existing function in Array.prototype, is not a good practice at all.
More about clean code tips here.
There are some errors like you use (return true/false) instead of string value return. Except in
if (S.length === 0) {
console.log(result,'kkkk')
return result;
}
Due to which it returns the boolean value and i have fixed the code according to your desire output.
const find = (S,dic ,result,broken) =>{
if (S.length === 0) {
console.log(result)
return result;
}
else {
let index = 0,
word = "";
while (index < S.length){
word += S.charAt(index);
if (dic.indexOf(word) !==-1) {
if (find(S.substring(index + 1), dic, result + word + " ")) {
return result;
} else {
//System.out.println(word + " backtrack");
index++;
}
}else{
index++;
}
}
}
return broken;
}
console.log(find("IamSumit",["I" , "have", "Jain", "Sumit", "am", "this", "dog"],'',`String can't be broken`))
Output:
String = "IamSumit"
Output: "I am Sumit"
String ="thisisadog"
Output : 'String can`t be broken'
What I am trying to do is make a function that takes user input, splits that input into an array of numbers, then replaces each number with a string depending on what the number is. It seems all this does now is return undefined, because it doesn't want to reassign the index to what It tell it to. I want to do this using a for loop or the forEach method if possible.
Here is my code so far:
function stringify(num){
var array = num;
for (i in array) {
if (array[i] == 2) {
array[i] = "x";
} else if (array[i] == 5) {
array[i] = "y";
} else {
array[i] = "meow"
}
return array;
}
}
Here is an example of what I want to eventually happen:
stringify(52527);
y x y x meow
You could map the new array by using an object for the wanted replacings.
function stringify(num) {
return Array.from(num, v => ({ 2: 'x', 5: 'y' }[v] || v));
}
console.log(stringify('5252'));
With default value
function stringify(num) {
var values = { 2: 'x', 5: 'y', default: 'meow' };
return Array.from(num, v => values[v] || values.default);
}
console.log(stringify('52527'));
Convert the input data to a string, and split the string to characters:
function stringify(num) {
var array = String(num).split('');
for (i in array) {
if (array[i] === '2') {
array[i] = "x";
} else if (array[i] === '5') {
array[i] = "y";
} else {
array[i] = "meow"
}
}
return array; // the return should be after the loop ends
}
console.log(stringify(52527));
Another solution would be to use a Array.map() to iterate after the split, and an object with the characters that should be replaced:
function stringify(num) {
var rep = { 2: 'x', 5: 'y' };
return String(num)
.split('')
.map(function(c) {
return rep[c] || 'meow';
});
}
console.log(stringify(52527));
I think you might have a couple of problems:
Using a for ... in loop for an array or an iterator isn't ideal; rather use the construction for (var i = 0; i < array.length; i += 1).
As other commenters have said, make sure you're converting the passed argument, which is a Number, into a String. My preference for doing this something like var numString = '' + num;. If you're using es6, you could also use the template literal notation:
var numString = `${num}`;
Be careful of using the double equal sign == versus the triple equals === to check equality. The double equal will do some arcane type-casting of its operands. Safer to stick with the triple equal unless you're sure.
Strings are immutable, which means that while you can access the values of their indices, you can't change those values. I would suggest creating a new array that you then join upon return:
function stringify(num) {
var numString = '' + num;
var ret = [];
for (var i = 0; i < numString.length; i += 1) {
if (numString[i] === '2') { // The index values will be strings, not numbers now
ret.push('x');
} else if (numString[i] === '5') {
ret.push('y');
} else {
ret.push('meow');
}
}
return ret.join(' ');
}
this results in:
stringify(52527);
y x y x meow
I have two questions actually.
What I want to do is 1st to check if the user entered value is a correct mathematical equation. For example, if the use enters x + y ( z this should detect as an invalid formula and x + y ( z ) as a correct one,
The 2nd thing I want to do is to split the formula from the + - * / () signs, so the above formula will be return as x, y, z.
What I have done is bellow
var arr = [];
var s = 'x + y ( z )';
arr = s.split("(?<=[-+*/])|(?=[-+*/])");
console.log(arr);
This returns a single array with just one data like, [x + y ( z )]
Another thing, the variables are not single letters. they could be
words like, annual price, closing price, etc
Can someone help me in this problem. Thanks in advance
UPDATE : I have tried "/[^+/*()-]+/g" also
For the second part:
var s = 'x + y ( z )';
var arr = s.match(/(\w)/g);
console.log(arr);
document.write(JSON.stringify(arr));
Of course, you have to check the validity of the input first.
Edit: using Tomer W's answer suggesting eval():
function checkExpression(str) {
// check for allowed characters only
if (/[^\w\d\(\)\+\*\/\-\s]/.exec(s) != null)
return false;
// extract variable names, assuming they're all one letter only
var arr = s.match(/(\w+)/g);
// instantiate the variables
arr.forEach(function (variable) {
eval(variable + '= 1');
});
// ( is alone, replace it by * (
str = str.replace(/\(/g, '* (');
try {
eval(str);
return true;
}
catch (ex) {
console.log(ex);
return false;
}
}
It's dirty but it works most of the time (Tomer W pointed some edge cases like ++62+5 or 54++++6 that can be avoided with an another regex check), do you have more complicated example to test?
Word of warning
VERY VERY VERY DANGEROUS METHOD AHEAD !!!
I am posting this as it is a valid answer, but you should do it only with extreme caution as a user can totally mess up your site.
DO not let the one user input be used in eval for another user !!! EVER !!!
Actual answer
You can use the built-in java-script compiler of your browser, and use eval()
function checkEq(equ)
{
for(ch in equ){
// check that all characters in input are "equasion usable"
if(" +-*/1234567890e^&%!=".indexOf(ch) === -1)
{ // if there are invalid chars
return false;
}
}
try{
// try running the equ, will throw an exception on a syntax error.
eval(equ);
return true; // no exception
}
catch(ex){
return false; // syntax error
}
}
Plunker example
and as i noted before! extreme caution!
Using both #ShanShan and #Tomer W answers, I wrote a formula validator. the code is bellow. In this validator, I checks for opening and closing brackets, extra / * - + signs, unwanted symbols, etc.
If the user wants to create and validate a formula with x,y,z
variables, user have to add the variables to an array and pass it to
this validator with the formula written so the validator accepts the
variables which are not numbers.
I also used a custom set mentioned in this post. https://stackoverflow.com/a/4344227/918277
Important : This java script function can't validate very complex formulas with sin, cos, tan, log, etc. Script will identify them as just letters and will return false.
function StringSet() {
var setObj = {}, val = {};
this.add = function(str) {
setObj[str] = val;
};
this.contains = function(str) {
return setObj[str] === val;
};
this.remove = function(str) {
delete setObj[str];
};
this.values = function() {
var values = [];
for ( var i in setObj) {
if (setObj[i] === val) {
values.push(i);
}
}
return values;
};
}
/**
*
* #param _formulaInputs
* Array of use entered inputs to be use in formula
* #param _formula
* User entered formula
* #returns {Boolean}
*/
function validateFormula(_formulaInputs, _formula) {
var formula = _formula;
var bracketStack = new Array();
var formulaDescArray = [];
var formulaDescInForm = new StringSet();
for (var i = 0; i < _formulaInputs.length; i++) {
formulaDescInForm.add(_formulaInputs[i]);
}
/* Regex to check for unwanted symbols(! # # $ etc.) */
if (/[^\w\d\(\)\+\*\/\-\s]/.exec(formula) != null) {
return false;
}
for (var i = 0; i < _formula.length; i++) {
if ((_formula.charAt(i) == '/' || _formula.charAt(i) == '*'
|| _formula.charAt(i) == '-' || _formula.charAt(i) == '+')
&& (_formula.charAt(i + 1) == '/'
|| _formula.charAt(i + 1) == '*'
|| _formula.charAt(i + 1) == '-' || _formula
.charAt(i + 1) == '+')) {
return false;
}
}
var lastChar = formula.charAt(formula.length - 1);
if (lastChar == '/' || lastChar == '*' || lastChar == '-'
|| lastChar == '+') {
return false;
}
formulaDescArray = formula.split(/[\/\*\-\+\()]/g);
/* Remove unwanted "" */
for (var i = 0; i < formulaDescArray.length; i++) {
if (formulaDescArray[i].trim().length == 0) {
formulaDescArray.splice(i, 1);
i--;
}
}
/* Remove unwanted numbers */
for (var i = 0; i < formulaDescArray.length; i++) {
if (!isNaN(formulaDescArray[i])) {
formulaDescArray.splice(i, 1);
i--;
}
}
for (var i = 0; i < formulaDescArray.length; i++) {
if (!formulaDescInForm.contains(formulaDescArray[i].trim())) {
return false;
}
}
for (var i = 0; i < formula.length; i++) {
if (formula.charAt(i) == '(') {
bracketStack.push(formula.charAt(i));
} else if (formula.charAt(i) == ')') {
bracketStack.pop();
}
}
if (bracketStack.length != 0) {
return false;
}
return true;
}
I am trying to compare two strings to see if ALL of one of the string's input is also within another string, regardless of order.
So far I have the following code...
What am I doing wrong?
var str1= "rkqodlw"
var str2= "world"
StringScrambler(str1, str2);
function StringScrambler(str1, str2) {
var string1= str1.split("").sort();
console.log(string1);
var string2 = str2.split("").sort();
console.log(string2);
matches = [];
for (i=0; i< string1.length; i++) {
for (j=0; j<string2.length; i++) {
while (j === i) {
matches.push(j);
console.log(matches);
var matchSort = matches.sort();
console.log(matchSort);
if (matchSort === string2) {
return true;
}else {
return false;
}
}
}
}
}
All the answers this far work fine but they will not work for words with double letters in the second string but not in the first (for eg. 'worlld' - notice the double L). The trick is to affect the first word such that it removes the found character(s) so that the same letter is not checked again. Something like this would do the trick:
// Check if the second string's characters are
// found in the first string
function StringScrambler(str1, str2) {
var arr1 = str1.split(''),
arr2 = str2.split(''),
isATrueSubset = true,
indexOfChar;
arr2.forEach(function(char) {
indexOfChar = arr1.indexOf(char);
if (indexOfChar > -1) {
// Remove the character that was found
// to avoid matching against it again
arr1.splice(indexOfChar, 1);
} else {
isATrueSubset = false;
// No need to continue
return;
}
});
console.log(isATrueSubset);
return isATrueSubset;
}
StringScrambler('rkqodlw ', 'world '); // outputs true
StringScrambler('rkqodlw ', 'worlld '); // outputs false
var one = "dlrow";
var two = "world";
var allCharsFound = true;
one.split("").map(function(char) {
if (two.indexOf(char) < 0) {
allCharsFound = false;
}
});
console.log(allCharsFound);
var str1= "rkqodlw";
var str2= "world";
function test($str1, $str2) {
var string2 = str2.split("");
for(var i=0; i<string2.length; i++) {
if (str1.indexOf(string2[i]) == -1) {
return false;
}
}
return true;
}
You can use the following code to do this task:
alert (AllFirstInSecond("world", "rkqodlw"));
alert (AllFirstInSecond("worldz", "rkqodlw"));
function AllFirstInSecond(str1, str2) {
var pos = str1.length - 1;
while (pos >= 0) {
if (str2.indexOf(str1.substr(pos--,1)) == -1) {
return false;
}
}
return true;
}
It simply checks every single character in the first string to see if it's in the second. If not, it returns false.
Only once all have been found does it return true.
There are possibilities for optimisation (every character is checked even if it's a duplicate that's already been checked) but, unless your strings are particularly large, there's probably not much absolute gain to be had.
If str2 is always a subset of str1, then this answer can be used
Compute intersection of two arrays in JavaScript
var arr1 = "rkqodlw".split("");
var arr2 = "world".split("");
var commonValues = arr2.filter(function(value) {
return arr1.indexOf(value) > -1;
});
alert(commonValues.join(""))
This will compare each words of the second string in the first one and if its present it will be added in the mathes array.
var str1= "rkqodlw";
var str2= "world2";
StringScrambler(str1, str2);
function StringScrambler(str1, str2) {
var string2 = str2.split("").sort();
console.log(string2);
matches = [];
for (j=0; j<string2.length; j++) {
if(str1.indexOf(string2[j]) > -1){
matches.push(string2[j]);
console.log(string2[j]);
}
}
console.log(matches);
}
try this:
var str1= "rkqodlw"
var str2= "world"
StringScrambler(str1, str2);
function StringScrambler(str1, str2) {
var string1 = str1.split("").sort();
var string2 = str2.split("").sort();
matches = [];
for (i = 0; i < string1.length; i++) {
if (string2.indexOf(string1[i]) > -1) matches.push(string1[i]);
}
return matches
}