Lasse said:
Most likely not. He gave a generic way to test for a finite number of
strings. It wokrs whether there are structure to the strings or not.
Undoubtedly. But his method consumes much more memory and computing
time than mine, no matter if the strings are structured or not. IOW:
Compared to my method, his is highly inefficient in *every* case.
Regexps take more work to make, and are harder to read.
Not generally, no.
And *much* harder to extend with new numbers, if it becomes necessary
No, see below.
return(!/^93(1(0[1-35-9]|1[016-8]|2[01]|[3-69]0|99)|40[1-35-9]|41[02])$/.test(o.value));
}
Are you sure that your regexp matches exactly the correct strings?
Pretty sure.
(It probably does, but comparing RegExps to string is ExpSpace complete
^^^^^^^^^^^^^^^^
Define that.
in general, so very hard to do).
Not at all. It is primarily a matter of structured building of the
RegExp, finding similarities first.
See the numbers again the RegExp should match. I remove the duplicate
93199 and group the numbers so one sees clearly what they have in common.
93101, 93102, 93103, 93105, 93106, 93107, 93108, 93109,
93110, 93111, 93116, 93117, 93118,
93120, 93121,
93130, 93140, 93150, 93160, 93190,
93199,
93401, 93402, 93403, 93405, 93406, 93407, 93408, 93409
93410, 93412
Obviously all numbers begin with 93:
/^93/
There are numbers continuing with 1 and with 4:
/^93(1|4)/
Numbers continuing with 1 continue with either 0 to 6, or 9:
/^93(1(0|1|2|3|4|5|6|9)|4)/
Numbers continuing from there with 0 continue with digits from 1 to 9,
except of 4:
/^93(1(0[1-35-9]|1|2|3|4|5|6|9)|4)/
Numbers continuing from there with 1 continue with 0, 1, and 6 to 8:
/^93(1(0[1-35-9]|1[016-8]|2|3|4|5|6|9)|4)/
Numbers continuing from there with 2 continue with either 0 or 1:
/^93(1(0[1-35-9]|1[016-8]|2[01]|3|4|5|6|9)|4)/
Numbers continuing from there with 3 to 6 and 9 continue with 0:
/^93(1(0[1-35-9]|1[016-8]|2[01]|[3-69]0)|4)/
If the fourth digit was 9, also 9 can follow:
/^93(1(0[1-35-9]|1[016-8]|2[01]|[3-69]0|99)|4)/
(One could have also grouped 93190 and 93199 together:
...|[3-6]0|9[09])...)
Numbers having a 4 as third digit continue with either 0 or 1:
/^93(1(0[1-35-9]|1[016-8]|2[01]|[3-69]0|99)|4[01])/
Because the fourth digit is followed by different sets of digits we write
/^93(1(0[1-35-9]|1[016-8]|2[01]|[3-69]0|99)|4(0|1))/
instead.
If the third digit is 4 and the fourth digit is 0, digits from 1 to 3
and 5 to 9 may follow:
/^93(1(0[1-35-9]|1[016-8]|2[01]|[3-69]0|99)|4(0[1-35-9]|1))/
If the third digit is 4 and the fourth digit is 1, the fifth may be
only 0 and 2:
/^93(1(0[1-35-9]|1[016-8]|2[01]|[3-69]0|99)|4(0[1-35-9]|1[02]))/
For we match whole numbers, we finally add the end-of-text meta character:
/^93(1(0[1-35-9]|1[016-8]|2[01]|[3-69]0|99)|4(0[1-35-9]|1[02]))$/
Now compare that to my RegExp which was built (but only in mind)
using the same procedure:
/^93(1(0[1-35-9]|1[016-8]|2[01]|[3-69]0|99)|40[1-35-9]|41[02])$/
The only difference is that I wrote `40[...]|41[...]' instead of
`4(0[...]|1[...])' which is semantically equal, though.
You will not tell me that the above was hard work, will you?
Because the RegExp was built *this* way, it is easy as well to find out
the strings it will match, going from left to right, creating a branch
in a build tree every time we find an alternative (including sets of
characters):
93
931
9310
93101
93102
93103
93105
93106
93107
93108
93109
9311
93110
93111
93116
93117
93118
9312
93120
93121
9313
93130
9314
93140
9315
93150
9316
93160
9319
93190
93199
934
9340
93401
93402
93403
93405
93406
93407
93408
93409
9341
93410
93412
We take only the leaves of the build tree:
93101
93102
93103
93105
93106
93107
93108
93109
93110
93111
93116
93117
93118
93120
93121
93130
93140
93150
93160
93190
93199
93401
93402
93403
93405
93406
93407
93408
93409
93410
93412
Group them:
93101, 93102, 93103, 93105, 93106, 93107, 93108, 93109
93110, 93111, 93116, 93117, 93118,
93120, 93121
93130, 93140, 93150, 93160, 93190,
93199,
93401, 93402, 93403, 93405, 93406, 93407, 93408, 93409
93410, 93412
And compare with what was provided (already grouped here and removed
dupes):
93101, 93102, 93103, 93105, 93106, 93107, 93108, 93109,
93110, 93111, 93116, 93117, 93118,
93120, 93121,
93130, 93140, 93150, 93160, 93190,
93199,
93401, 93402, 93403, 93405, 93406, 93407, 93408, 93409
93410, 93412
q.e.d.
We have only five-digit numbers with few linear exceptions here, one
should manage it to see that the above RegExp matches without writing
the matches down, especially if one has built the RegExp by themselves
as described above.
If reading the entire RegExp is still too difficult, one can also manage
it to divide the RegExp into many (say each for every third or fourth
digit) and have the tests combined with `&&'.
So new numbers are not be a problem at all. If in doubt, one can simply
add another alternative: If 93429 should be forbidden, too, the RegExp
can be simply changed to
/^(93(1(0[1-35-9]|1[016-8]|2[01]|[3-69]0|99)|4(0[1-35-9]|1[02])|93429)$/
^ ^^^^^^^
which, of course, could (later) be optimized to
/^93(1(0[1-35-9]|1[016-8]|2[01]|[3-69]0|99)|4(0[1-35-9]|1[02]|29))$/
An additional test may be as well combined with `&&' without wasting to
much computing time.
PointedEars