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;
}
}
}
Related
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;
}
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'));
I have written a code that removes all consonants before a vowel from a string and replaces it with an 'r' and in the case, the string starts with a vowel it should return the word without doing anything to it. Now, I want to add two things I came up with to it but unfortunately, I have not been able to:
1. When the string input is all consonants then it should do nothing and just return the string.
2. If user types in space like so ' ' then it should be trimmed.
How do I place this logic in the code below without affecting what is already working?
const scoobyDoo = str => {
if(typeof str !== 'string'){
return 'This function accepts strings only';
}
let newStr = str.toLowerCase().split('');
let arrWord = newStr.length;
let regex = /[aeiou]/gi;
if (newStr[0].match(regex)){
let nothing = newStr.join('');
return nothing;
}
else {
for (let i = 0; i < arrWord; i++){
let vowelIndex = newStr.indexOf(str.match(regex)[i].toLowerCase());
newStr.splice(0, vowelIndex, 'r');
return newStr.join('');
}
}
}
console.log(scoobyDoo('scooby'));//works as expected returns 'rooby'
console.log(scoobyDoo('ethane'));//works as expected returns 'ethane'
console.log(scoobyDoo('why'));// should return 'why'
console.log(scoobyDoo(' '));// should return trimmed space and a
text telling the user only spaces were entered.
I realise this doesn't really answer your question, but your existing logic is very complicated and you could achieve the same result with String.trim, .toLowerCase and .replace:
console.log('scooby'.trim().toLowerCase().replace(/^(?=.*?[aeiou])[^aeiou]+/, 'r'))
rooby
console.log('ethane'.trim().toLowerCase().replace(/^(?=.*?[aeiou])[^aeiou]+/, 'r'))
ethane
console.log('why'.trim().toLowerCase().replace(/^(?=.*?[aeiou])[^aeiou]+/, 'r'))
why
console.log('*' + ' '.trim().toLowerCase().replace(/^(?=.*?[aeiou])[^aeiou]+/, 'r') + '*')
**
The regexp uses a positive lookahead to ensure that there is a vowel in the string, and if so replaces all leading consonants with an r.
To do something more in line with your existing function, you could try this. It still makes extensive use of regex functions though.
const scoobyDoo = str => {
if(typeof str !== 'string'){
return 'This function accepts strings only';
}
// is it a blank string?
if (str.match(/^\s+$/)) {
return '';
}
// does it start with a vowel? if so, nothing to do
if (str.match(/^[aeiou]/i)) {
return str;
}
// does it only contain consonants?
if (!str.match(/[aeiou]/i)) {
return str;
}
// must not start with a vowel but still include one
return str.replace(/^[^aeiou]+/i, 'r');
}
I want to remove all consonants in a string before the occurrence of a vowel and then replace it with an 'r'.
This means that 'scooby' will become 'rooby', 'xylographer' will become 'rographer' and so on. This is the algorithm I came up with:
1. Check if input type is not a string.
2. Use a variable(newStr) to hold lowercase conversion and splitted word.
3. Declare a variable(arrWord) to hold the length of the array.
4. Another variable called regex to check if a string starts with a consonant
5. Variable newArr holds the final result.
6. Search through the array, if the string does not start with a consonant
join it and return it.
7. Else keep looking for where the first vowel occurs in the word.
8. When found, remove all characters(consonants) before the vowel occurence
and replace them with an r.
9. Join the array together.
I have been able to come up with this:
const scoobyDoo = str => {
if(typeof str !== 'string'){
return 'This function accepts strings only';
}
let newStr = str.toLowerCase().split('');
let arrWord = newStr.length;
let regex = /[aeiou]/gi;
for (let i = 0; i < arrWord; i++){
if (newStr[0].match(regex)) {
let nothing = newStr.join('');
return nothing;
}
else {
let vowelIndex = newStr.indexOf(str.match(regex)[0]);
newStr.splice(0, vowelIndex, 'r');
return newStr.join('');
}
}
}
console.log(scoobyDoo('scOoby'));
I tested out the program again by capitalizing the first vowel index and instead of 'rooby' I get 'rscooby'. Why is that so?
Can you once try with following code in your else and see the changes
else {
var vowelIndex = newStr.indexOf(str.match(regex)[0]);
newStr.splice(0, vowelIndex, 'r');
return newStr.join("");
}
Is it not much easier like this? Or am I missing something??
'xylographer'.replace(/^\s*[^aieou]+(?=\w)/i,function(m,o,s){return "r"})
//"rographer"
'scooby'.replace(/^\s*[^aieou]+(?=\w)/i,function(m,o,s){return "r"})
//"rooby"
you could just use one reg expression for the whole algorithm and no need to split your string no more.
regexp to use.
/^[^aouie, AOUIE]+(?=[aouie, AOUIE])/g
of course you can readjust regexp to suit you more but this will get your main requirement.
On the line immediately after the else statement, I just called .toLowerCase() on it and it was fixed:
let vowelIndex = newStr.indexOf(str.match(regex)[0].toLowerCase());
I like keeping my code simple and readable
function pattern(str){
var vowelIndex = str.indexOf(str.match(/[aeiou]/)); //returns index of first vowel in str
return "r" + str.slice(vowelIndex);
}
console.log(pattern('xylographer'));
I am brand new to Javascript and trying to figure out how to camel-case any string by using a for loop. This is what I have so far.
function camelCase(str) {
var splitStr = "";
var result = "";
splitStr = str.split(" ");
for(var i = 0; i < splitStr.length; i++){
result += splitStr[i][0].toUpperCase() +
splitStr[i].slice(1);
}
return result;
}
console.log(camelCase("hello there people"));
it returns "HelloTherePeople" - How do you I make the very first index of splitStr (splitStr[0][0]) be excluded from toUpperCase, but still included in the beginning of the string?
What is your delimiter? This method assumes an underscore _. Change it to a space if you want a space. Or make it a variable you can pass to camelize.
if( !String.prototype.camelize )
String.prototype.camelize = function(){
return this.replace(/_+(.)?/g, function(match, chr) {
return chr ? chr.toUpperCase() : '';
});
}
"a_new_string".camelize()
//"aNewString"
The regex /_+(.)?/g/ says find 1 or more _ characters followed by any character ., the (.) creates a capturing group, so you are able to get that one character. It's passed to the function as the second paramater chr. The ? means not greedy so it will stop at the next _. The g means globally, pretty much means find all matches.
String.prototype.replace reference
change return like this:
return result[0].toLowerCase()+result.substr(1);
You can do a check inside the loop to see if you are on the first index.
function camelCase(str) {
//splitStr will be an array
var splitStr = [];
var result = "";
splitStr = str.split(" ");
//Capitalize first letter of words starting from the second one
for(var i = 0; i < splitStr.length; i++){
//first word
if (i===0) {
//Good practice to lowercase the first letter regardless of input
result += splitStr[i][0].toLowerCase() + splitStr[i].slice(1);
}
else {
//rest can proceed as before
result += splitStr[i][0].toUpperCase() +
splitStr[i].slice(1);
}
}
return result;
}
console.log(camelCase("hello there people"));
Alternatively, the loop can even start on the second index. However, you will have to check if the length of splitStr before running a loop from the second index