Finding characters of a word in a string, optimized - javascript

I am doing doing a few code challenges in the hope to learn some new stuff. Currently I have written a piece of code that find charachter of a given word in a string of random letters.
I thought regexp might be the best performance-wise (it's one of the objectives). This code passes the checks but takes too long with absurd long strings. Is there any way I can improve this? It's really ugly as is honestly. I've tried several approaches but I am probably just really a newbie at reg exp etc.
before all the if statements I only used regexp but if str2 which is the word I am looking for had double characters it would come back 'true' because it would count already counted characters. That is why I am using replace to exclude them. That's all I could get.
the goal is to return true if a portion of str1 can be rearranged to form str2, otherwise return false. Only lower case letters will be used (a-z). No punctuation or digits will be included. for example scramble('aabbcamaomsccdd','commas') should return true
function scramble (str1, str2)
{
var o = 0; // tracks amount of matched letters.
for(i = 0; i < str2.length; i++)
{
var regex1 = new RegExp (str2[i]) ; // select letter from word that needs to be found
if( regex1.test(str1) == true)// if selected character is found us replace to remove it from the random characters string for next iteration.
{
str1 = str1.replace(regex1 ,"");
o++; // increment o if character is removed from random string.
}
}
//check if amount of removed characters equals total characters of word that we want.
if ( o == str2.length)
{
return true
}
if (o !== str2.length)
{
return false
}
}
Update: I flagged the hash table as answer because afaik this was not doable with regexp it seems also I was able to achieve a proper result with .split and loops myself plus the hash table also achieved this.

if-less methodology!
i didnt stress it on tests but looks fine
function scramble(str1, str2) {
str1 = [...str1];
return [...str2].filter((str => (str == str1.splice(str1.indexOf(str), 1)))).join('') == str2;
}

You could take a hash table, count the wanted characters and return if no count is not more necessary.
function scramble (str1, str2) {
var counter = {},
keys = 0;
for (let i = 0; i < str2.length; i++) {
if (!counter[str2[i]]) {
counter[str2[i]] = 0;
keys++;
}
counter[str2[i]]++;
}
for (let i = 0; i < str1.length; i++) {
if (!counter[str1[i]]) continue;
if (!--counter[str1[i]] && !--keys) return true;
}
return false;
}
console.log(scramble('abc', 'cba'));
console.log(scramble('abc', 'aba'));
console.log(scramble('abcdea', 'aba'));
console.log(scramble('aabbcamaomsccdd', 'commas'));

Related

Finding longest word in a string javascript code that is not working on the last wordd

I've already solved this by using a split function but I'm still confused as to why my previous for-loop only code is not working when I'm trying to find the longest word in a string in javascript. The function I'm writing is supposed to return the number of letters of the longest word. After using the console, whenever i use only one word, it returns the value i initialized the counter of the letters with (which is 0). If the longest word is the last word, it returns the second longest word on the preceding words. If the longest word is on anywhere except the last word, the result is accurate. It seems like it has trouble counting the letters of the last word. Here is my code.
let lettCount = 0;
let largest = 0;
let spaceCheck = /\s/;
for(let i = 0; i < str.length; i++) {
if(spaceCheck.test(str[i]) == true) {
if(lettCount > largest) {
largest = lettCount;
}
lettCount = 0;
} else {
lettCount++;
}
}
return largest;
You should be able to simplify the logic here significantly, using String.split() and Math.max().
We split the string into an array, then use Array.map() to get the length of each word, then use Math.max() along with the Spread syntax to get the longest word.
let str = 'the longest word is dinosaur';
function getLongest(str) {
return Math.max(...str.split(/\s/).map(s => s.length));
}
console.log('Longest word:', getLongest(str));
You can also do this with String.split() and Array.reduce(), this is even a little simpler:
let str = 'the longest word is dinosaur';
function getLongest(str) {
return str.split(/\s/).reduce((acc,s) => s.length > acc ? s.length: acc, 0);
}
console.log('Longest word:', getLongest(str));

How can I create a pallindrome code in JavaScript?

So I am trying to create a code for palindrome this is how I tried. Is there another or better way of doing it?
But now it only shows that if the first value is equal or not and shows true or false?
var inpo= prompt("Please enter to check if palindrome")
var inp = parseFloat(inpo)
var a = inpo.split('')
var inpo2 = a.reverse()
var len= inpo.length
for (var i =0;i< len ;i++) {
if (inpo[i] == inpo2[i] )
alert("True")
else
alert("False")
}
A way to check if a word or an entire phrase is a palindrome or not:
function isPalindrome(str) {
// Escape the string: Eliminate punctuation and spaces, enforce lower case
let escaped = str.replace(/[^A-Za-z0-9_]/g,"").toLowerCase();
// Reverse the escaped string
let reversed = escaped.split('').reverse().join('');
//compare
return escaped == reversed;
}
console.log(isPalindrome('Level'));
console.log(isPalindrome('Red rum, sir, is murder'));
I hope the comments serve well as an explanation.
Also, you have a prompt example in THIS jsfiddle.
If you are creating a palindrome checker code, here is a simple way to do it. Split, reverse then join.
str1 = "xxaa";
str2 = str1.split('').reverse().join("");
if (str1 == str2) {
alert("good");
} else {
alert("not");
}
You can check the single character from the string consuming 1 character from right and another from left until you will find either the string is finished or there are 2 inequal character. I implemented with a classical for loop.
Note that bracket notation for strings [] is only recently supported, you can use charAt if memory serves me right
let inp = "otdto";
console.log(isPalindrome(inp));
function isPalindrome(inp) {
const len = inp.length;
for (let i = 0; i < Math.floor(len / 2); i++)
if (inp[i] != inp[len - i - 1])
return false;
return true;
}

How to remove string between two characters every time they occur [duplicate]

This question already has answers here:
Strip HTML from Text JavaScript
(44 answers)
removing html tags from string
(3 answers)
Closed 7 years ago.
I need to get rid of any text inside < and >, including the two delimiters themselves.
So for example, from string
<brev-y>th</brev-y><sw-ex>a</sw-ex><sl>t</sl>​
I would like to get this one
that
This is what i've tried so far:
var str = annotation.split(' ');
str.substring(str.lastIndexOf("<") + 1, str.lastIndexOf(">"))
But it doesn't work for every < and >.
I'd rather not use RegEx if possible, but I'm happy to hear if it's the only option.
You can simply use the replace method with /<[^>]*>/g.It matches < followed by [^>]* any amount of non> until > globally.
var str = '<brev-y>th</brev-y><sw-ex>a</sw-ex><sl>t</sl>';
str = str.replace(/<[^>]*>/g, "");
alert(str);
For string removal you can use RegExp, it is ok.
"<brev-y>th</brev-y><sw-ex>a</sw-ex><sl>t</sl>​".replace(/<\/?[^>]+>/g, "")
Since the text you want is always after a > character, you could split it at that point, and then the first character in each String of the array would be the character you need. For example:
String[] strings = stringName.split("<");
String word = "";
for(int i = 0; i < strings.length; i++) {
word += strings[i].charAt(0);
}
This is probably glitchy right now, but I think this would work. You don't need to actually remove the text between the "<>"- just get the character right after a '>'
Using a regular expression is not the only option, but it's a pretty good option.
You can easily parse the string to remove the tags, for example by using a state machine where the < and > characters turns on and off a state of ignoring characters. There are other methods of course, some shorter, some more efficient, but they will all be a few lines of code, while a regular expression solution is just a single replace.
Example:
function removeHtml1(str) {
return str.replace(/<[^>]*>/g, '');
}
function removeHtml2(str) {
var result = '';
var ignore = false;
for (var i = 0; i < str.length; i++) {
var c = str.charAt(i);
switch (c) {
case '<': ignore = true; break;
case '>': ignore = false; break;
default: if (!ignore) result += c;
}
}
return result;
}
var s = "<brev-y>th</brev-y><sw-ex>a</sw-ex><sl>t</sl>";
console.log(removeHtml1(s));
console.log(removeHtml2(s));
There are several ways to do this. Some are better than others. I haven't done one lately for these two specific characters, so I took a minute and wrote some code that may work. I will describe how it works. Create a function with a loop that copies an incoming string, character by character, to an outgoing string. Make the function a string type so it will return your modified string. Create the loop to scan from incoming from string[0] and while less than string.length(). Within the loop, add an if statement. When the if statement sees a "<" character in the incoming string it stops copying, but continues to look at every character in the incoming string until it sees the ">" character. When the ">" is found, it starts copying again. It's that simple.
The following code may need some refinement, but it should get you started on the method described above. It's not the fastest and not the most elegant but the basic idea is there. This did compile, and it ran correctly, here, with no errors. In my test program it produced the correct output. However, you may need to test it further in the context of your program.
string filter_on_brackets(string str1)
{
string str2 = "";
int copy_flag = 1;
for (size_t i = 0 ; i < str1.length();i++)
{
if(str1[i] == '<')
{
copy_flag = 0;
}
if(str1[i] == '>')
{
copy_flag = 2;
}
if(copy_flag == 1)
{
str2 += str1[i];
}
if(copy_flag == 2)
{
copy_flag = 1;
}
}
return str2;
}

Javascript Array Issues

The task at hand;
Return true if the string in the first element of the array contains
all of the letters of the string in the second element of the array.
For example, ['hello', 'Hello'], should return true because all of the
letters in the second string are present in the first, ignoring case.
The arguments ['hello', 'hey'] should return false because the string
'hello' does not contain a 'y'.
Lastly, ['Alien', 'line'], should return true because all of the
letters in 'line' are present in 'Alien'.
My attempted solution that isn't working;
function mutation(arr) {
if (arr[0].toLowerCase().indexOf(arr[1].toLowerCase()) >= 0){
return true;
}else{
return false;
}
return arr;
}
mutation(['hello', 'hey']);
Can someone please explain to me why it isn't working. I am not looking for an answer just an explanation so that I can understand better.
Many thanks
Try this:
$('#id').click(function() {
var arr = ['hello','hey'];
var isExist = false;
for (i = 0;i < arr[1].length; i++) {
if(arr[0].toLowerCase().indexOf(arr[1][i].toLowerCase()) >= 0)
isExist = true;
else {
isExist = false;
break;
}
}
if (isExist)
alert('true'); // In case of all chars of 2nd present in 1st arr
});
what you are doing is that, you are converting first element to lower case and than trying to find the second element in first array.
your solution will work for the cases where the whole second element exists in first element as a sub string or both elements are exactly same.
for example it'll work for following examples
['hello', 'Hello']
['hello', 'ell']
['hello', 'He']
But it will not work when letters in second string are shuffled first string. for following examples your solution will fail.
['Alien', 'line']
['hello', 'elo']
['hello', 'Hol']
If whole second word does not exists as it is in first word your solution will not work.
Let me know if this is helpful. i'll provide you the solution if you need.
As another answer correctly states, your code does not work because it's looking in the first string for the second string, in its entirety, with the letters in the same order. Instead, you need to look at each letter in the second string individually and check that it's in the first string.
We'll adopt the strategy of "Programming in English and going backward". The English for the overall problem is:
Does every letter to check match?
We can write this in JavaScript as
letters_to_check . every(matches)
We can calculate letters_to_check as input[1].toLowerCase().split('').
Now we have to write the matches function, which can be expressed in English as
Is the letter found in the string to check against?
So we write
function matches(letter) { return string_to_heck_against.search(letter); }
string_to_check_against is of course input[0].
The entire program is thus:
function mutation(input) {
// Check if a letter is in the string to be checked against.
function matches(letter) { return string_to_check_against.search(letter); }
var string_to_check_against = input[0].toLowerCase();
var string_to_check = input[1].toLowerCase();
var letters_to_check = string_to_check.split('');
return letters_to_check . every(matches);
}
If you are programming in ES6, this could be written as
function mutation([source, target]) {
return target .
toLowerCase() .
split('') .
every(letter => source.toLowerCase().search(letter));
}
According to your output you have to check all the characters of array second string with array first string. For this you have to check all characters are available or not in the first string, not using the direct string. If we use strings directly, it will look for total string not for the characters.
Try the following:
var arr = ['Alien', 'line'];
var arr1 = ['hello','hey'];
var arr2 = ['hello','Hello'];
function mutation(arr) {
var str1 = arr[0].toLowerCase();
var str2 = arr[1].toLowerCase();
var o = false;
for (var i=0;i<str2.length;i++) {
o = (str1.indexOf(str2[i]) !== -1);
if (!o) break;
}
return o;
}
console.log('first arr : ', mutation(arr));
console.log('second arr :', mutation(arr1));
console.log('third arr :', mutation(arr2));
This is my working code. You can check. The idea is to transfer both strings in the array to lowercase. Then we compare both strings together.
I take every single letter from the shorter string, then use the indexOf function to check if it's in the longer string. Every time there is a match, the valule no1 or no2 will increase.
If the value of no1 or no2 equal with the length of the shorter string, it means all the letters in the shorter string is inside the longer string.
function mutation(arr) {
// transfer both strings in the array to lower case
var val1 = arr[0].toLowerCase();
var val2 = arr[1].toLowerCase();
// check if val2 is shorter than val1
if(val1.length >= val2.length){
var no1 = 0;
// Check every if any letter in val2 is in val1
for(var i = 0; i < val2.length; i++){
if(val1.indexOf(val2[i]) != -1){
// plus 1 if there is a match
no1++;
}
}
// check if the value of no1 equals to length of val2
if(no1 == val2.length){
return true;
}else{
return false;
}
}else if(val2.length > val1.length){
var no2 = 0;
for(var j = 0; j < val1.length; j++){
if(val2.indexOf(val1[j]) != -1){
no2++;
}
}
if(no2 == val1.length){
return true;
}else{
return false;
}
}
}

How to match a input parenthesis with regular expression in JavaScript?

I have no idea on matching the input parenthesis with JavaScript.
Input string example:
(pen)
((pen) and orange)
it should return false if the input string is like the following:
(pen
pen)
(pen) and orange)
((pen and orange )
((pen) and orange
)(pen and orange )(
(pen and )orange()
Regular expressions would be messy. It's much easier to go through with a simple counter.
function parenthesesBalanced(string) {
var count = 0;
for (var i = 0, l = string.length; i < l; i++) {
var char = string.charAt(i);
if (char == "(") {
// Opening parenthesis is always OK
count++;
} else if (char == ")") {
// If we're at the outer level already it's not valid
if (count == 0) return false;
count--;
}
}
return (count == 0);
}
replace every group of "left paren - some chars - right paren" with nothing, until there is no more groups. If the resulting string contains a parenthesis, the parens were not balanced.
balancedParens = function(str) {
var q;
do {
q = str;
str = str.replace(/\([^()]*\)/g, '');
} while(q != str);
return !str.match(/[()]/);
}
a = "foo ((and) bar and (baz) quux) and (blah)";
b = "(dddddd()";
alert(balancedParens(a))
alert(balancedParens(b))
http://jsfiddle.net/gvGGT/
It's not possible to match a balanced string with a single regexp in javascript, because JS dialect doesn't support recursive expressions.
It is a known hard problem to match parens with regular expressions. While it is possible, it's not particularly efficient.
It's much faster simply to iterate through the string, maintaining a counter, incrementing it every time you hit an open paren, and decrementing it every time you hit a close paren. If the counter ever goes below zero, or the counter is not zero at the end of the string, it fails.
I made a node library call balanced to make this a bit more sane, if you wanted to just get balanced outer matches you can do this
balanced.matches({source: source, open: '(', close: ')'})
my use case was a bit more complicated, and required me to do replacements and support comments.

Categories

Resources