JS Validate Crossword Clue Enumeration - javascript

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

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

checking if digit exists on particular place in string

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.

textbox must contain number or letter validation on javascript without regex

Hi guys i got a problem here, how i can validate a password box that must contain at least one numeric character. i'm not allowed using regular expression / regex. i have tried searching over the web, but the solution is always end with regex.
here's my code that i try
function validateIn()
{
var pass=document.getElementById('password').value;
for(var i=0;i<pass.length;i++)
{
if(isNaN(pass.charAt(i))==false)
{
return true;
break;
}
else
{
return false;
}
}
}
i have tried that way but i fail, can u help me guys? thanks before
One possible approach:
function validateIn() {
var pass = document.getElementById('password').value,
p = pass.length,
ch = '';
while (p--) {
ch = pass.charAt(p);
if (ch >= '0' && ch <= '9') {
return true; // we have found a digit here
}
}
return false; // the loop is done, yet we didn't find any digit
}
The point is, you don't have to return immediately after you have found a normal character (as you're basically looking for a single digit) - you just have to move on with your checking.
Note that I have gone without isNaN, as it's a bit inefficient: the only thing required is a range check.

regex only number, dash is optional

I'm trying to make a javascript function with a regex, that will validate a phone number.
the rules are :
1. numbers only.
2. more then 10 numbers.
3. a dash ( - ) is allowed (optional).
first, I tried this one :
function validatePhone(phone) {
var phoneReg = /[0-9]{10,}/;
return (phoneReg.test(phone));
}
it worked well only on the first 2 rules, but not with the dash.
Then I tried var phoneReg = /[-0-9]{10,}/; and even var phoneReg = [\d]+\-?[\d]+ but then the javascript was broken...
any thoughts ?
This is how I would approach phone number validation:
var validatePhone = function(phone) {
// Stip everything but the digits.
// People like to format phone numbers in all
// sorts of ways so we shouldn't complain
// about any of the formatting, just ensure the
// right number of digits exist.
phone = phone.replace(/\D/g, '');
// They should have entered 10-14 digits.
// 10 digits would be sans-country code,
// 14 would be the longest possible country code of 4 digits.
// Return `false` if the digit range isn't met.
if (!phone.match(/\d{10,14}/)) return false;
// If they entered 10, they have left out the country code.
// For this example we'll assume the US code of '1'.
if (phone.length === 10) phone = '1' + phone;
// This is a valid number, return the stripped number
// for reformatting and/or database storage.
return phone;
}
This should work. The - character needs to be escaped.
var phoneReg = /[0-9-\-]{11,}/;
The potential problem with this, is that strings that have multiple dashes will test positive even when 10 numbers aren't in the string. I would suggest replacing dashes before testing.
var phoneReg = /[0-9]{11,}/;
return (phoneReg.test(phone.replace(/\-/g, ''));

Always getting result of 0 when counting patterns in string

I keep getting a result of 0 whenever I type in a search term. I'm trying to find the number of times that a pattern occurs in string. So for example searching for at would return 3. Any advice on where I'm going wrng?
string =
[
"cat math path"
]
var pattern = prompt('Please enter a search term:');
function check(string,pattern)
{
if(pattern)
{
if(pattern.indexOf(string) == -1)
{
return 0;
}
return count(pattern.substring(pattern.indexOf(string)+string.length), string)+1;
}
else
{
return("Nothing entered!");
}
}
alert(check(string,pattern));
if(pattern.indexOf(string) == -1)
should be
if(string.indexOf(pattern) == -1)
I think you inverted the use of pattern and string. See the documentation of indexOf. Also you can easily count occurrences with split which breaks your string into an array:
count=string.split(pattern).length - 1;
Where string="cat math path"; (instead of an array)

Categories