Javascript Basic algorithm - javascript

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. No case-sensitivity and order doesn't matter only the letters matter. For ex - ["Hello","hello"] returns true and so does ["Alien","lien"] and also ["Mary", "Aarmy"]. I think you get it. If not return false.
I could solve it with Array.indexOf() === -1 (in the first for loop) but can it work with this code, it's the opposite. I just can't make it return false. Ultimately, I wanna know, can you make it return false without changing the method.
function mutation(arr) {
var split = arr[1].toLowerCase().split("");
var splitSecond = arr[0].toLowerCase().split("");
for(k=0;k<=arr[0].length;k++){
for(i=0;i<=arr[1].length;i++){
if(split[i]===splitSecond[k]) {
return true
}
}
} return false
}
mutation(["hello", "hney"], "");
If using any other method, explain :)

The problem with your code is that you return true; as soon as one letter matches.
What you need to do is check if all letters match, which is easier achieved by checking if any letter doesn't match.
mainloop:
for(k=0;k<=arr[0].length;k++){
for(i=0;i<=arr[1].length;i++){
if(split[i]===splitSecond[k]) {
continue mainloop; // found the letter, move on to next search
}
}
return false; // failed to find letter, fail here
}
return true; // haven't failed yet and end of input reached. Success!
Another alternative would be:
for(k=0;k<arr[0].length;k++) {
if( arr[1].indexOf(split[k]) < 0) {
// letter not found
return false;
}
}
// not failed yet? Excellent!
return true;

function mutation(arr) {
var test = arr[0].toLowerCase(),
chars = arr[1].toLowerCase(),
len=chars.length;
for(var i=0;i<len;i++)
if(test.indexOf(chars[i])==-1) //this char not exist in test string
return false;
return true;//all chars already checked
}
mutation(["hello", "he"]);
https://jsfiddle.net/hb2rsm2x/115/

Here is an interesting way using regular expressions. escapeRegExp was taken from here.
function mutation(arr){
var matcher = new RegExp('[^'+escapeRegExp(arr[1])+']', "i");
return arr[0].match(matcher) === null;
}
function escapeRegExp(s) {
return s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')
}

Related

Count each character in string using recursion

i have tried to make a function count each character in a string using recursion, for 2 days now. I tried to write some pseudo-code, but i can't really implement it.
Pseudocode:
write a function that takes text as a parameter
set a counter, for each element
set a result, using key,value for each character in element
base case: if we only have 1 string, then return the character and string
else return function-1 until the last element is hit.
var tekst = "We have to count strings";
function countStrings(tekst) {
var count = 0
var result = {}
if (count > tekst.lentgh) {
count++
return result
} else {
return countStrings(tekst-1)
}
}
console.log(countStrings(tekst))
Consider using this logic:
var tekst = "We have to count strings";
function countStrings(tekst) {
if (tekst.length == 0) {
return 0;
}
return 1 + countStrings(tekst.substring(1));
}
console.log(countStrings(tekst))
The approach here is, at each step of the recursion, to return 1 plus whatever the length of the substring from the next character onwards is. That is, we recurse down the input string, one character at a time, building out the length. The base case here occurs when the input to countStrings() happens to be empty string. In this case, we just return 0, and stop the recursive calls.
I decided to attempt this problem and this is what I came up with. Definitely a challenging problem so don't feel bad if you didn't get it:
var countStrings = function(tekst) {
if (tekst.length === 0) return {};
var obj = countStrings(tekst.slice(1));
if (obj[tekst[0]]) {
obj[tekst[0]] += 1;
} else {
obj[tekst[0]] = 1;
}
return obj;
};

Javascript - extract letters from an alphanumerical string via loop

Hello there StackOverflow people,
What I expected:
Removing the numbers of the string "23Ka5X". The loop counts the length and the if statement extracts the letters into an array letterMemory. When no letters are in the string, the message '"oh no numbers!" should be the output.
What I ran into:
I have been working on this for some time now but I can't find my mistake. I don't know if I missed a simple detail or made a big mess.
My feeling and console output:
var letterMemory = [];
function orderMsg(mixedMsg) {
for (var loopString = 0; loopString < mixedMsg.length; loopString++); {
if (isNaN(parseInt(mixedMsg.charAt[loopString]))); {
letterMemory.push(mixedMsg.charAt[loopString]);
return letterMemory;
} if (!isNaN(parseInt(mixedMsg.charAt[loopString]))) {
return "oh no numbers!";
}
}
}
console.log(orderMsg("23Ka5X"));
I feel like the issue is trying to push any letter into the array letterMemory via letterMemory.push(mixedMsg.charAt[loopString])
does not work how I imagine it.
I would be really grateful for your help!
I found a simple solution via .replace() but I really want to make it work with a loop and if statements since loops combined with if statements were my latest freecodecamp lessons and I want to get better at it.
The fixed code
function orderMsg(mixedMsg){
var letterMemory = []
for (var loopString = 0; loopString < mixedMsg.length; loopString++){
if (isNaN(mixedMsg[loopString])){
letterMemory.push(mixedMsg[loopString])
}
}
if (letterMemory.length){
return letterMemory
} else {
return 'oh no numbers!'
}
}
The issue was
The for loop was not executing since you terminated it with ; at the end.
charAt is a function, so you either do string.charAt(index), or you can also simply say string[index].
You are using the return statement within the for loop, so what will happen is even if the for loop ran (without the semi-colon at the end), it would run just once.
One other issue is that the variable letterMemory is declared outside the function so that means if you were to call this function twice, it would use the same letterMemory array.
-end of answer-
Additional read: you can use split, filter and ternary operator to condense the function as follows ..
function orderMsg(mixedMsg){
const letterMemory = mixedMsg.split('').filter(isNaN)
return letterMemory.length ? letterMemory : 'oh no numbers!'
}
This could be helpful,
function orderMsg(mixedMsg) {
for (var loopString = 0; loopString < mixedMsg.length; loopString++) {
if (isNaN(parseInt(mixedMsg.charAt(loopString)))) {
letterMemory.push(mixedMsg.charAt(loopString));
}
}
return letterMemory;
}
var arr = orderMsg("23s5");
if (arr.length == 0) {
console.log("oh no numbers!")
} else {
console.log(arr);
}
Use replace with regex globally, replacing all digits by an empty string:
string.replace(/[0-9]/g, "")
You have terminated for loop in the same line with ;.
charAt() is a method.
Return value after for loop ends.
var letterMemory = [];
function orderMsg(mixedMsg) {
for (var loopString = 0; loopString < mixedMsg.length; loopString++) {
var letter=parseInt(mixedMsg.charAt(loopString));
if(isNaN(letter)){
letterMemory.push(mixedMsg.charAt(loopString));
}
}
if(letterMemory.length>0){
return letterMemory;
}
else{
return "Oh no numbers!";
}
}
console.log(orderMsg("23Ka5X"));
Maybe try using .test to match the letters.
function orderMsg(str){
var result = [];
for(var letter of str){
if(/[a-zA-Z]+/g.test(letter)){
result.push(letter)
}
}
if(result.length === 0){
return 'Oh no numbers'
}
return result
}
For a more thorough explanation:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test

What is wrong with my function that accepts an array of 2 element and check if the first element has every letter in the second element?

The function is given an array of 2 elements, 2 string to be exact. If the first element has every single letter in the second element (just one time, no case, no order), then the function returns true, if not false.
hey and hello works. But for example, mutation(["zyxwvutsrqponmlkjihgfedcba", "qrstu"]) is not returning true, somehow. I suspect there is something wrong with my if statement nested inside my for loop. Am I returning false or true multiple times, or some other problem?
function mutation(arr) {
var one=arr[0];
var two=arr[1];
one.toLowerCase();
two.toLowerCase();
var array=two.split("");
for(var i=0;i<array.length;i++){
if(one.indexOf(array[i]) !== -1){
return false;
}else return true;
}
}
mutation(["hello", "hey"]);
EDIT:
New discovery! if I move else return true to right after the end bracket of the for loop, mutation("hello", "neo") would return false, as wanted. But if I did that, then, mutation("hello", "hey") wouldn't return true, whereas before the change, it would.
This:
for(var i=0;i<array.length;i++){
if(one.indexOf(array[i]) !== -1){
return false;
}else return true;
}
is essentially (close enough) the same as this:
if(one.indexOf(array[0]) !== -1){
return false;
}else return true;
That is, you're not actually looping over anything. Because, no matter what, your loop always returns on the first iteration.
Consider the logic of what your function should do. If I understand correctly, you want to return false if the loop ever encounters a letter that isn't found in one. And to return true if the loop never encounters such a match. In that case, the default condition after the loop would be to return true. Something like this:
for(var i=0;i<array.length;i++){
if(one.indexOf(array[i]) === -1){
return false;
}
}
return true;
Basically, if the loop never found a "non-match", then it never returned false. So return true.
Edit: I also changed the comparison in the if, because I think you had it reversed. But I guess I'm not 100% sure on that, since the intent of the method is a little unclear. (The logic therein is a bit confusing, and the name of the method certainly doesn't help.) But hopefully you at least get the idea and can test/validate accordingly for your needs.
First, you should only return false if you find any character in one that wasn't in two, but you can only return true at the end of the loop, because then you know all characters match. It can't be in the else block.
Second, Shouldn't it be the other way around based on your description? You should iterate the characters of one and see if they are in two instead. Then it would fit.
function mutation(arr) {
var one=arr[0].toLowerCase();
var two=arr[1].toLowerCase();
var oneArr=one.split("");
var twoArr=two.split("");
console.log("Do all of '" + one + "' characters occur in '" + two + "'?");
for(var i=0;i<oneArr.length;i++){
console.log("Looking for " + oneArr[i]);
// If any characters in two didn't occur in one, it fails
var twoIndex = twoArr.indexOf(oneArr[i]);
if(twoIndex === -1) {
console.log("Can't find " + oneArr[i]);
return false;
} else {
console.log("Found at index " + twoIndex + " in '" + two + "'");
}
}
return true;
}
console.log(mutation(["hey", "hello"]));
console.log(mutation(["qrstu", "zyxwvutsrqponmlkjihgfedcba"]));
The main issue is that you're using an else block to return true inside the loop, so your loop is only checking one element then either returning true or false based on whether or not that element is in the first string. Put the return true statement after the for loop.
The second issue is that when you're checking for existence, you're returning false if it does exist. Use one.indexOf(array[i]) === -1 instead.
The final issue is that you're splitting a string to iterate it, but strings don't need to be split to be iterated using a for loop.
The rest of the changes just use less lines of code to do the same thing.
function mutation(arr) {
arr = arr.map(e => e.toLowerCase());
for(let i = arr[1].length - 1; i > -1; --i)
if(arr[0].indexOf(arr[1][i]) === -1) return false;
return true;
}
console.log(mutation(["hello", "hey"]));
console.log(mutation(["hello", "hel"]));
console.log(mutation(["zyxwvutsrqponmlkjihgfedcba", "qrstu"]));

charAt not evaluating

I am trying to write a function that will evaluate equality of characters in a string and return true if 3 in a row match. The charAt() doesn't seem to be working as the if statement always goes to the else block.
function myFunction(num1)
{
var checkNum1;
for (var i = 0; i < num1.length; i++)
{
if (num1.charAt(i) == num1.charAt(i+1) && num1.charAt(i) == num1.charAt(i+2))
{
checkNum1 = true;
break;
}
}
if (checkNum1 == true)
{
return true;
}
else
{
return false;
}
}
What should I be doing to get the last "if" block to return true?
The code that you have provided works fine with strings ie: myFunction("257986555213") returns true.
However, myFunction(257986555213) returns false as expected as charAt is a String method.
As a fail-safe approach, you can try adding the following line to your method at the beginning:
num1 += '';
This should convert your argument to string and you should get your results..
Hope it Helps!!

JavaScript Throws Undefined Error

What it is supposed to do -
Example
url1(pages,"ALT") returns "www.xyz.ac.uk"
url1(pages,"xyz") returns ""
The error - TypeError: Cannot call method 'toUpperCase' of undefined
This is just for some coursework, Im stuck with these errors. Any help would be much appreciated
function index(string,pattern,caseSensitive) {
if(caseSensitive == false) {
var v = string.toUpperCase();
} else {
var v = string;
}
return indexNumber = v.indexOf(pattern);
}
var pages = [ "|www.lboro.ac.uk|Loughborough University offers degree programmes and world class research.", "!www.xyz.ac.uk!An alternative University" , "%www%Yet another University"];
alert(url1(pages, "ALT"));
function url1(pages,pattern) {
var siteContent = [];
for(i=0;i<pages.length;i++) {
var seperator = pages[i].charAt(0);
if(pages[i].indexOf(seperator)>0){
siteContent = pages[i].split(pages[i].indexOf(seperator));
}
if( index(siteContent[2],pattern,false)>=0){
return siteContent[1];
}else{
return "";
}
}
}
if(pages[i].indexOf(seperator)>0){
siteContent = pages[i].split(pages[i].indexOf(seperator));
}
if( index(siteContent[2],pattern,false)>=0){
return siteContent[1];
}else{
return "";
}
If pages[i].indexOf(seperator)<=0, siteContent is still whatever it was from the last iteration. If that happens on the first iteration, siteContent is still [], and siteContent[2] is undefined.
Another problem: the expression pages[i].indexOf(seperator) returns a number, and pages[i].split expects a delimiting string as an argument. Since the number doesn't appear in your input, you'll always get a single-element array, and siteContent[2] will always be undefined. Get rid of .indexOf(seperator), change it to siteContent = pages[i].split(seperator).
One more: get rid of the else { return ""; }. Add a return ""; after the for loop.
Finally, in the first if statement condition, change .indexOf(seperator) > 0 to .indexOf(seperator, 1) !== -1. Since you're getting seperator from the first character of the string, it will be found at 0. You want the second occurrence, so start the search at 1. In addition, .indexOf returns -1 if it doesn't find the substring. You'll need to account for this in both if conditions.
Side note, as this is not causing your problem: never use == false. JS will coerce stuff like 0 and "" to == false. If that's what you want, just use the ! operator, because the expression has nothing to do with the value false.
My final answer is http://jsfiddle.net/QF237/
Right here:
alert(url1(pages, ALT)); // ALT ISN'T DEFINED
I believe you forgot to quote it:
alert(url1(pages, "ALT"));
You should split the string passing the separator character itself. Your function then will look like:
function url1(pages,pattern) {
var siteContent = [];
for(i=0;i<pages.length;i++) {
var seperator = pages[i].charAt(0);
console.log(seperator);
if(pages[i].indexOf(seperator)>=0){
siteContent = pages[i].split(seperator); //fixed here
}
console.log(siteContent);
if( index(siteContent[2],pattern,false)>=0){
return siteContent[1];
}else{
return "";
}
}
}
Tell us if it worked, please.
EDIT: It seeems your index() also has a little problem. Please try the function below.
function index(string,pattern,caseSensitive) {
var v;
if(caseSensitive == false) {
v = string.toUpperCase();
pattern = pattern.toUpperCase(); //to clarify: pattern should be uppercased also if caseSensitiveness is false
} else {
v = string;
}
return v.indexOf(pattern);
}
EDIT 2:
And url1() is finally like this:
function url1(pages,pattern) {
var siteContent = [];
for(i=0;i<pages.length;i++) {
var seperator = pages[i].charAt(0);
if(pages[i].indexOf(seperator)>=0){
siteContent = pages[i].split(seperator);
}
if( index(siteContent[2],pattern,false)>=0){
return siteContent[1];
}
}
return "";
}
In this case, the first occurrence of pattern in all pages will be returned.

Categories