January 24th, 2013, 10:08 AM

LeapYear, no upper limit
Hi guys,
My task is to write a regular expression which accept leapyear only, and the first year have to be 1584 without upper limit. Could someone help me with redo this expr. ?
Code:
(15(8[48]9[26]))((1[69][29]\d)(0[48][13579][26][2468][048]))(([2468][048]163579[26])00)
January 24th, 2013, 01:42 PM

And you can't do it in code? It would be much, much easier to do it in some code than in a regular expression.
January 24th, 2013, 02:23 PM

Originally Posted by requinix
And you can't do it in code? It would be much, much easier to do it in some code than in a regular expression.
That's the point to do this by regular expression, it is my homework.
January 24th, 2013, 02:47 PM

I tend to think of the problem going from generic to specific:
* Anything with five or more digits is valid
* If the first digit is 29 and there are three more digits then it's valid
* If the first is 1, second is 69, and there are two more digits then it's valid
* If the first is 1, second is 5, third is 99 (=9), and there is another digit then it's valid
* If the first is 1, second is 5, third is 8, and fourth is 49 then it's valid
You can just as easily reverse those. Probably more efficient to do so, actually.
[edit] That only meets the "after 1584" and not the "only leap years" requirements. I'm just demonstrating how I would go about solving the problem.
Last edited by requinix; January 25th, 2013 at 01:41 PM.
January 25th, 2013, 04:53 AM

Is it good ?
Code:
[19][09]{4,}[29][09]{3,}1[69][09]{2}159[09]158[49]
January 25th, 2013, 07:57 AM

No time to do the full thing right now, but a quick try, limiting the range from 1600 to 2999, but it could be adapted quite easily to the full range:
Code:
(162028)00\d\d[19]([02468][048][13579][26])0[48]
I've tried it with about 30 miscellaneous values, it seems to be working.
January 25th, 2013, 01:53 PM

But it permits 1900. (Also has a couple typos.)
Here's a similar version for 10002999:
Code:
(1[26]2[048])00[12]\d(0[48][13579][26][2468][048])
Last edited by requinix; January 25th, 2013 at 06:03 PM.
January 25th, 2013, 05:53 PM

My proposal does qualify 1600, 2000 or 1904 as leap years, but does not consider 1700, 1800 or 1900 as leap years. Which is correct. A straight copy and past under Perl works not so bad, as shown in the following debug session:
Code:
DB<1> print "leap" if 1600 =~ /(162028)00\d\d[19]([02468][048][13579][26])0[48]/
leap
DB<2> print "leap" if 1700 =~ /(162028)00\d\d[19]([02468][048][13579][26])0[48]/
DB<3> print "leap" if 1800 =~ /(162028)00\d\d[19]([02468][048][13579][26])0[48]/
DB<4> print "leap" if 1900 =~ /(162028)00\d\d[19]([02468][048][13579][26])0[48]/
DB<5> print "leap" if 1904 =~ /(162028)00\d\d[19]([02468][048][13579][26])0[48]/
leap
DB<6> print "leap" if 2000 =~ /(162028)00\d\d[19]([02468][048][13579][26])0[48]/
leap
DB<7> print "leap" if 2004 =~ /(162028)00\d\d[19]([02468][048][13579][26])0[48]/
leap
Having said that, I just did it for the fun in less than 5 minutes, looking back to it, there are some parenthesis errors or missing characters compared to what I was really thinking about, so probably some errors on some other cases. After a few more minutes, the following is closer to what I had in mind:
Code:
/(16202428)00\d\d([2468][048])(\d\d[13579][26])(\d\d0[48])/
As I said, it is designed to work from 1600 to 2999. Actually, thinking about it, it should probably be good from 1204 to 3196, unless no years before 1584 should never be leap. What needs to be changed if the first part ((16202428)00), to make it more general in the management of centuries. No big deal to find if MC can be divided by 4, just the same logic as what is used if DU is a multiple of 4 later in the regex will do it. But since this is a homework, I'll leave it to the OP to complete this.
Managing dates before 1584 can be a bit trickier, but we don't really know what exact rules should apply for them or whether they should even be considered. Just as a reminder, there were leap years before 1584, the Julian calendar has leap years every 4 years, it is just that, for example, 1000, 1100, 1300, 1400 and 1500 would not have been leap in the rules of the Gregorian calendar, while they were leap in the Julian calendar. If we don't have to worry about years before 1584, then there is nothing to change for years before 1600, the only change left to be made is to make the rule more general for years after 3196, as described above.
Comments on this post
January 25th, 2013, 06:03 PM

And my comment got lost.
Originally Posted by requinix
requinix agrees: ah, I misread it is a couple of typos. you are right