checking if digit exists on particular place in string - javascript

I have a string that starts with "TT" and ends with six digits(ex. "TT012345", "TT012000, TT329001). The string is always formatted like this and I need to check if the last digit in this string is of a certain value.
Say I have the string "TT032970". In this case I'd like to get a match on this string since the last digit is zero and the digit before that is a seven(I'm looking for 7).
The string "TT037000" should also be a match but "TT0329701" shouldn't(since it isn't all zeroes to the right of the seven(the "last" 7 in the string)).
I was thinking of using a set of nested if's using substr() to check all places of the string for zeroes and if it isn't a zero in position n, then I check if the digit I'm looking for exists in position n.
My code is repetitive and I'm all for being efficient.
This is what I got so far(that works but only checks the last place of the string and the second last place):
var lastDigit = [3, 7, 8], tda = document.querySelectorAll('td a'), i, j;
function checkArray(num) {
"use strict";
for (j = 0; j < lastDigit.length; j++) {
if (num === lastDigit[j]) {
return true;
}
}
}
for (i = 0; i < tda.length; i++) {
if ((parseInt(tda[i].textContent.substr(8, 1), 10) === 0 && checkArray(parseInt(tda[i].textContent.substr(7, 1), 10))) || checkArray(parseInt(tda[i].textContent.substr(8, 1), 10))) {
tda[i].style.background = "rgb(255, 144, 255)";
amountOfTickets.push(tda[i]);
}
}
I'm positive there's a great way of checking the string for trailing zeroes and check the first non-zero digit before the zeroes. However, I'm really bad with loops and I just can't figure out how.
I'm very keen on figuring it out myself but I need a head start. I'd rather take a detailed explanation on how to do it than just the "answer".
If anything else seem off I'd gladly listen to improvements.
Thanks in advance!

To get the first digit before the zeros at the end of a string, you may use a regular expression :
+string.match(/(\d)0*$/)[1]
Example 1 :
var string = "TT032970";
var digit = +string.match(/(\d)0*$/)[1];
console.log(digit); // logs 7
Example 2 :
console.log(["TT012345","TT012000","TT329001","TT032970"].map(function(string){
return +string.match(/(\d)0*$/)[1]
})); // logs [5, 2, 1, 7]
Demonstration

Obviously, from the other answers, a regular expression will be much simpler than your loops. Moreover, any nested loop solution will be difficult to work, as you don't know how many levels deep you have to look. (Is there one zero? Two? Five?)
This regex is quite simple:
/(\d)0+$/
If you do a match on that with your string, you should get either null if it doesn't match (e.g. "TT0329701") or a two-element array if it does (e.g. "TT037000" will return ["7000", "7"].)
That should be enough for your to build your own solution upon.
Best of luck.

The first thing I though about is something like this (depends on whether I understood your problem correctly):
function lookFor(str, digit) {
//validate input...
if (str.length != 8) return false;
if (str[0] != "T" && str[1] != "T") return false;
//start at the end and move to the left as long as there are zeros
//the first non-zero element must be our digit, else return false
for (var i = str.length-1; i>0; --i) {
if (str[i] !== "0") {
return str[i] === digit;
}
}
}
lookFor("TT012000", "2") --> true
lookFor("TT012000", "3") --> false
But I guess the regex solution is probably more compact than this one.

Related

Check length between two characters in a string

So I've been working on this coding challenge for about a day now and I still feel like I haven't scratched the surface even though it's suppose to be Easy. The problem asks us to take a string parameter and if there are exactly 3 characters (not including spaces) in between the letters 'a' and 'b', it should be true.
Example: Input: "maple bread"; Output: false // Because there are > 3 places
Input: "age bad"; Output: true // Exactly three places in between 'a' and 'b'
Here is what I've written, although it is unfinished and most likely in the wrong direction:
function challengeOne(str) {
let places = 0;
for (let i=0; i < str.length; i++) {
if (str[i] != 'a') {
places++
} else if (str[i] === 'b'){
}
}
console.log(places)
}
So my idea was to start counting places after the letter 'a' until it gets to 'b', then it would return the amount of places. I would then start another flow where if 'places' > 3, return false or if 'places' === 3, then return true.
However, attempting the first flow only returns the total count for places that aren't 'a'. I'm using console.log instead of return to test if it works or not.
I'm only looking for a push in the right direction and if there is a method I might be missing or if there are other examples similar to this. I feel like the solution is pretty simple yet I can't seem to grasp it.
Edit:
I took a break from this challenge just so I could look at it from fresh eyes and I was able to solve it quickly! I looked through everyone's suggestions and applied it until I found the solution. Here is the new code that worked:
function challengeOne(str) {
// code goes here
str = str.replace(/ /g, '')
let count = Math.abs(str.lastIndexOf('a')-str.lastIndexOf('b'));
if (count === 3) {
return true
} else return false
}
Thank you for all your input!
Here's a more efficient approach - simply find the indexes of the letter a and b and check whether the absolute value of subtracting the two is 4 (since indexes are 0 indexed):
function challengeOne(str) {
return Math.abs(str.indexOf("a") - str.indexOf("b")) == 4;
}
console.log(challengeOne("age bad"));
console.log(challengeOne("maple bread"));
if there are exactly 3 characters (not including spaces)
Simply remove all spaces via String#replace, then perform the check:
function challengeOne(str) {
return str = str.replace(/ /g, ''), Math.abs(str.indexOf("a") - str.indexOf("b")) == 4;
}
console.log(challengeOne("age bad"));
console.log(challengeOne("maple bread"));
References:
Math#abs
String#indexOf
Here is another approach: This one excludes spaces as in the OP, so the output reflects that. If it is to include spaces, that line could be removed.
function challengeOne(str) {
//strip spaces
str = str.replace(/\s/g, '');
//take just the in between chars
let extract = str.match(/a(.*)b/).pop();
return extract.length == 3
}
console.log(challengeOne('maple bread'));
console.log(challengeOne('age bad'));
You can go recursive:
Check if the string starts with 'a' and ends with 'b' and check the length
Continue by cutting the string either left or right (or both) until there are 3 characters in between or the string is empty.
Examples:
maple bread
aple brea
aple bre
aple br
aple b
ple
le
FALSE
age bad
age ba
age b
TRUE
const check = (x, y, z) => str => {
const exec = s => {
const xb = s.startsWith(x);
const yb = s.endsWith(y);
return ( !s ? false
: xb && yb && s.length === z + 2 ? true
: xb && yb ? exec(s.slice(1, -1))
: xb ? exec(s.slice(0, -1))
: exec(s.slice(1)));
};
return exec(str);
}
const challenge = check('a', 'b', 3);
console.log(`
challenge("maple bread"): ${challenge("maple bread")}
challenge("age bad"): ${challenge("age bad")}
challenge("aabab"): ${challenge("aabab")}
`)
I assume spaces are counted and your examples seem to indicate this, although your question says otherwise. If so, here's a push that should be helpful. You're right, there are JavaScript methods for strings, including one that should help you find the index (location) of the a and b within the given string.
Try here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#instance_methods

JS Validate Crossword Clue Enumeration

I need to validate a crossword clue's enumeration (the number(s) in the brackets). For example, "Big star (3,5)" - the enumeration is 3,5.
I'm struggling with the required regular expression. Rules should be as follows:
only allow characters 0-9, hyphens and commas
each number shouldn't start with a zero e.g. "09" should be just "9"
it should start with a number
it should end with a number
it shouldn't allow repeated hyphens/commas e.g "3,,5" or "3--5" or "3,-5" or 3-,5"
Some VALID examples...
1
1,2
1,2-3
1,2-3,4
Some INVALID examples...
text
-1
1,
1,,2
0-1
3-04
Hopefully you get the idea. Any help would be greatly appreciated.
Regular expressions are very powerful but can be a pain to write out sometimes, especially if you don't use them often. This is why I often use this site to help.
After speaking in the comments, a logic error became apparent: the regexp would not match anything with 0, even if it did not start with it. It would also not match numbers without - like just 10.
Now, I came up with ([1-9]([0-9]+)?(((\-|\,)[1-9]([0-9]+)?)+)?) but there was another problem:
10-5-40 would be matched as expected
but the 3-2 in 03-2 and the 3 and 2 in 03-02 would also be matched.
So I included some JS logic in addition to the RegExp. Hopefully now it works as intended.
let Regexp1 = /([1-9]([0-9]+)?(((\-|\,)[1-9]([0-9]+)?)+)?)/;
let Regexp2 = /([1-9]([0-9]+)?(((\-|\,)[1-9]([0-9]+)?)+))/;
function test(t) {
match1 = (t.match(Regexp1) != null);
match2 = (t.match(Regexp2) != null);
let matches = false;
if(match1 && match2) {
matches = true;
} else if(match1 && !match2) {
if(t.match(Regexp1)[0].length == t.length) {
matches = true;
} else {
matches = false;
}
}
if(t.match(Regexp1)[0].length != t.length) {
matches = false;
}
console.log(matches);
return matches;
}
test("10-5"); // true
test("03-4"); // false
test("0-5"); // false
test("1,05"); // false
test("1--5"); // false
test("10"); // true
test("10-05"); // false

Comparing Letters in a Palindrome (JavaScript) [duplicate]

This question already has answers here:
Palindrome check in Javascript
(45 answers)
Closed 7 years ago.
My objective is to test if a word (under 10 letters) that a user enters is a palindrome. I want to do this my comparing the first letter to the last, 2nd letter to the 2nd to last, 3rd letter to the 3rd to last...
I am using a for loop and an array to do this. I cannot use the reverse() method. My main issue is formatting the comparison equation that I have:
(lettersArray[i] + 1) == (lettersArray[i].length - 1)
This is supposed to compare the first to last, 2nd and 2nd to last, and so on. Is this the right format? Am I right in my method of accessing the last index in the array and counting it down? Please let me kow what I am doing wrong since it's not running. Here is my code:
var usersWord = prompt("Enter a Palindrome");
var lettersArray =usersWord.split(""); // this is the array
for(var i=0; lettersArray.length < 11; i++) {
if((letters[i] + 1) == (lettersArray.length[i]-1)) {
alert("is palindrome");
} //end if statement
else{
alert("is not palindrome");
} // end else statement
} // end for statement
The issue with your code is that you are reporting results after checking each character; however, we can't tell whether a word is a palindrome or not without checking every character. A function such as the following might better suit your requirements.
function checkPalindrome(word) {
var len = word.length;
for (var i = 0; i < (len / 2); i++) {
if (word.charAt(i) !== word.charAt(len - 1 - i))
return false;
}
return true;
}
Another important point to note is that you should be checking until word.length / 2, not an arbitrary number 11 that may change depending on the word used as an input. Note also that word.length / 2 is an optimized case. The loop could also have been run till the word length but there is no need to check again that last char == first char when already first char == last char

Finding first alphabetical letter in a string - Javascript

I've done some research and can't seem to find a way to do this. I even tried using a for loop to loop through the string and tried using the functions isLetter() and charAt().
I have a string which is a street address for example:
var streetAddr = "45 Church St";
I need a way to loop through the string and find the first alphabetical letter in that string. I need to use that character somewhere else after this. For the above example I would need the function to return a value of C. What would be a nice way to do this?
Maybe one of the shortest solutions:
'45 Church St'.match(/[a-zA-Z]/).pop();
Since match will return null if there are no alphanumerical characters in a string, you may transform it to the following fool proof solution:
('45 Church St'.match(/[a-zA-Z]/) || []).pop();
Just check if the character is in the range A-Z or a-z
function firstChar(inputString) {
for (var i = 0; i < inputString.length; i += 1) {
if ((inputString.charAt(i) >= 'A' && inputString.charAt(i) <= 'Z') ||
(inputString.charAt(i) >= 'a' && inputString.charAt(i) <= 'z')) {
return inputString.charAt(i);
}
}
return "";
}
console.assert(firstChar("45 Church St") === "C");
console.assert(firstChar("12345") === "");
This can be done with match
"45 Church St".match(/[a-z]/i)[0]; // "C"
This code example should get the job done.
function numsNletters(alphanum) {
firstChar=alphanum.match(/[a-zA-Z]/).pop();
numsLetters=alphanum.split(firstChar);
numbers=numsLetters[0];
// prepending the letter we split on (found with regex at top)
letters=firstChar+numsLetters[1];
return numbers+'|'+letters;
}
numsNletters("123abc"); // returns "123|abc";

Recursion and Loops - Maximum Call Stack Exceeded

I'm trying to build a function that adds up all the numbers within a string... for example, 'dlsjf3diw62' would end up being 65.
I tried to be clever and put together a recursive function:
function NumberAddition(str) {
var numbers='1234567890';
var check=[];
str=str.split[''];
function recursive(str,check) {
if (str.length==0)
return check;
else if (numbers.indexOf(str[0])>=0)
{
for (i=0;i<str.length;i++){
if (numbers.indexOf(str[i])<0)
check.push(str.slice(0,i));
str=str.slice(i);
return recursive(str,check);
}
}
else
str.shift();
return recursive(str,check);
}
You'll see that I'm trying to get my numbers returned as an array in the array named check. Unfortunately, I have a maximum call stack size exceeded, and I'm not sure why! The recursion does have a base case!! It ends once str no longer has any contents. Why wouldn't this work? Is there something I'm missing?
-Will
You can achieve the same thing with a far easier solution, using regular expressions, as follows:
var str = 'dlsjf3diw62';
var check = str.match(/\d+/g); // this pattern matches all instances of 1 or more digits
Then, to sum the numbers, you can do this:
var checkSum = 0;
for (var i = 0; i < check.length; i++) {
checkSum += parseInt(check[i]);
}
Or, slightly more compact:
var checkSum = check.reduce(function(sum, num){ return sum + parseInt(num) }, 0);
The reason your recursion doesn't work is the case where you do enter the for loop, because you've found a digit, but the digits continue to the end of the string. If that happens, the return inside the for loop never happens, and the loop ends. After that, the .shift() does not happen, because it's in that else branch, so you return re-process the same string.
You shouldn't solve this particular problem that way, but the code makes a good example of the anti-pattern of having return statements inside if bodies followed by else. Your code would be clearer (and would work) if it looked like this:
function recursive(str, check) {
if (str.length == 0)
return check;
if (numbers.indexOf(str[0]) >= 0) {
// Find the end of the string of digits, or
// the end of the whole thing
for (var i = 0; i < str.length && numbers.indexOf(str[i]) >= 0; i++);
check.push(str.slice(0, i));
str = str.slice(i);
return recursive(str, check);
}
// A non-digit character
str.shift();
return recursive(str, check);
}
In that version, there are no else clauses, because the two if clauses always involve a return. The for loop is changed to simply find the right value of "i" for the subsequent slicing.
edit — one thing this doesn't fix is the fact that you're pushing arrays into your "check" list. That is, the substring "62" would be pushed as the array ["6", "2"]. That's not a huge problem; it's solved with the addition of a .join() in the right place.

Categories