8
\$\begingroup\$

Write a function or program that accepts a date (as a string in YYYY-MM-DD format) as input and returns a truthy value if that date is "alphabetical," and a falsey value if it isn't.

An alphabetical date is a date whose month, day and year are in alphabetical order when expressed as a string (and when considered specifically in M - D - Y order). For example, Sept. 26 2018 is an alphabetical date:

September 26th 2018 -> September twenty-sixth two thousand eighteen

September
Twenty-sixth
Two thousand eighteen

Another way to think of this challenge: "are the elements of a given date lexically sorted?"

Notes:

  • 2018 is represented as "two thousand eighteen," not "twenty eighteen" or "two zero one eight." For another example, the year 1456 would be represented as "one thousand four hundred fifty-six," not "fourteen fifty-six."
  • 26th is represented as "twenty-sixth," not "twenty-six."
  • Each element of the date is considered as a whole. This is why 2018 doesn't automatically fail even though the "e" in eighteen comes before the "t" in two.

The following dates are not alphabetical:

  • September 2nd 2018 ("second" should sort ahead of "September")
  • April 30th 4000 ("four thousand" should sort ahead of "thirtieth")

Additional Rules:

  • You will receive the date as a string, formatted like YYYY-MM-DD. The year will always have four digits, and the month and day will always have two digits each. Zero-padding is not represented in the string conversion (e.g., '2000-01-01' is 'January first two thousand' as you'd expect).
  • You may assume that dates will always be valid (no February 30th, no Smarch 1st) and that the value of the year will be positive (no dates B.C.), but the date may be far in the future ("in the year two nine thousand...").
  • You should return a truthy or falsey value, not necessarily a boolean True or False. If you do this in Javascript and want to return '0' and 0 that's fine. Of course, if you want to return a boolean, feel free.
  • Standard loopholes are forbidden.
  • This is code-golf

More Examples of Alphabetical Dates

  • 2066-01-02 (January second, two thousand sixty-six)
  • 1000-04-08 (April eighth, one thousand)
  • 6000-08-01 (August first, six thousand)

More Examples of Non-Alphabetical Dates

  • 1066-01-02 (January second, one thousand sixty-six)
  • 1000-04-07 (April seventh, one thousand)
  • 8000-08-01 (August first, eight thousand)
\$\endgroup\$
  • 2
    \$\begingroup\$ Lousy Smarch weather. \$\endgroup\$ – AdmBorkBork Sep 26 '18 at 19:05
  • \$\begingroup\$ @Arnauld Um, no? Looks like 2018-09-02 is falsy, while 2018-09-26 is truthy (when given as in the question). \$\endgroup\$ – Erik the Outgolfer Sep 26 '18 at 19:12
  • \$\begingroup\$ @EriktheOutgolfer Right. I totally misread the challenge. (Maybe it should be rephrased as Is the date lexically sorted? or something like that.) \$\endgroup\$ – Arnauld Sep 26 '18 at 19:15
  • \$\begingroup\$ @Arnauld I tweaked the first paragraph and included a line with your suggested wording a bit further in, hopefully to the delight of future readers. Thank you! \$\endgroup\$ – souldeux Sep 26 '18 at 19:22
  • 1
    \$\begingroup\$ The year is always the spelled-out number. 1444 is one thousand four hundred forty-four. 1991 is one thousand nine hundred ninety-one. \$\endgroup\$ – souldeux Sep 27 '18 at 12:06
1
\$\begingroup\$

05AB1E, 66 62 58 bytes

0ì'-¡ÀDΣ2£<•88ΛηΣλšëÇñ0é≠>sîä&ζp°Lć®-αÅ®`•21вŽqT32в£Nèsè}Q

Try it online or verify all examples mentioned in the challenge.

Explanation:

0ì         # Prepend a "0" before the (implicit) input
           #  i.e. "2018-09-26" → "02018-09-26"
  '-¡     '# Then split on "-"
           #  i.e. "02018-09-26" → ["02018","09","26"]
     À     # Rotate it once to the left (so [0yyyy,MM,dd] becomes [MM,dd,0yyyy])
           #  i.e. ["02018","09","26"] → ["09","26","02018"]
D          # Duplicate this list
 Σ         # Sort this list by:
  2£       #  Leave only the first 2 digits of the current item
           #  (which is why the prepended 0 was there at the start for the year)
           #   i.e. "09" → "09"
           #   i.e. "02018" → "02"
    <      #  Decrease it by 1 to make it 0-indexed
           #   i.e. "09" → 8
  •88ΛηΣλšëÇñ0é≠>sîä&ζp°Lć®-αÅ®`•21в
           #  Push the list [7,3,7,0,7,7,7,0,13,10,10,0,4,12,17,6,4,17,15,2,9,17,2,19,17,6,4,17,15,2,9,19,19,19,19,19,19,19,19,19,19,17,17,11,20,18,5,5,16,14,1,8]
   ŽqT32в  #  Push the list [12,31,9]
         £ #  Split the first list into parts of that size: [[7,3,7,0,7,7,7,0,13,10,10,0],
           #    [4,12,17,6,4,17,15,2,9,17,2,19,17,6,4,17,15,2,9,19,19,19,19,19,19,19,19,19,19,17,17],
           #    [11,20,18,5,5,16,14,1,8]]
   Nè      #  Then only leave the relevant list of the three based on the sort-index
     s     #  Swap to get the earlier integer at the top of the stack again
      è    #  And use it to index into the list
           #   i.e. [7,3,7,0,7,7,7,0,13,10,10,0] and 8 → 13
 }         # Close the sort
  Q        # And check if the sorted list is equal to the duplicated list,
           # so whether the order is still [MM,dd,0yyyy] after sorting
           # (and output the result implicitly)               

See this 05AB1E tip of mine (section How to compress integer lists?) to understand why •88ΛηΣλšëÇñ0é≠>sîä&ζp°Lć®-αÅ®`•21в is [7,3,7,0,7,7,7,0,13,10,10,0,4,12,17,6,4,17,15,2,9,17,2,19,17,6,4,17,15,2,9,19,19,19,19,19,19,19,19,19,19,17,17,11,20,18,5,5,16,14,1,8] and ŽqT32в is [12,31,9].

Additional general explanation:

The sort function will sort all three types (day, month, year) at the same time, where we will return a truthy value only if M < D < Y (where these D, M, and Y are the values we've retrieved from the compressed lists).

Why these three lists mentioned above? If we put all words in order, categorized by type, we have the following order:

Sorting nr      Type        Which?

0               Month       April, August, December
1               Year        eight thousand
2               Day         eighteenth, eighth, eleventh
3               Month       February
4               Day         fifteenth, fifth, first
5               Year        five thousand, four thousand
6               Day         fourteenth, fourth
7               Month       January, July, June, March, May
8               Year        nine thousand
9               Day         ninteenth, ninth
10              Month       November, October
11              Year        one thousand
12              Day         second
13              Month       September
14              Year        seven thousand
15              Day         seventeenth, seventh
16              Year        six thousand
17              Day         sixteenth, sixth, tenth, third, thirteenth, thirtieth, thirty-first
18              Year        three thousand
19              Day         twelfth, twentieth, twenty-first through twenty-ninth
20              Year        two thousand

If we then look at each type individually and their original order (one thousand, two thousand, etc. for years; January, February, etc. for months; and first, second, etc. for days), the sorting numbers mentioned above are in these orders:

Years:  [11,20,18,5,5,16,14,1,8]
Months: [7,3,7,0,7,7,7,0,13,10,10,0]
Days:   [4,12,17,6,4,17,15,2,9,17,2,19,17,6,4,17,15,2,9,19,19,19,19,19,19,19,19,19,19,17,17]
\$\endgroup\$
9
\$\begingroup\$

JavaScript (ES6), 101 bytes

Saved 4 bytes thanks to @Shaggy

Returns \$0\$ or \$1\$.

s=>'_414044406550'[[,m,d]=s.split`-`,+m]<(d=`_268328715819832871${6e12-12}`[+d])&d<'_6A9338704'[s[0]]

Try it online! or Test all dates! (includes some invalid inputs)

How?

Each month, each day and each year is mapped to an ID in \$[0..10]\$ (\$M\$, \$D\$ and \$Y\$ respectively) according to the following table. We then test if we have \$M<D\$ and \$D<Y\$.

The last part of the lookup string for day IDs is slightly compressed by using ${6e12-12}, which expands to 5999999999988 (19th to 31st).

  M | Month                D | Day                  Y | Year (millennium)
----+----------------    ----+----------------    ----+-------------------
  0 | April                1 | eighth               0 | eight thousand
  0 | August               1 | eleventh           ----+-------------------
  0 | December             1 | eighteenth           3 | four thousand
----+----------------    ----+----------------      3 | five thousand
  1 | February             2 | first              ----+-------------------
----+----------------      2 | fifth                4 | nine thousand
  4 | January              2 | fifteenth          ----+-------------------
  4 | March              ----+----------------      6 | one thousand
  4 | May                  3 | fourth             ----+-------------------
  4 | June                 3 | fourteenth           7 | seven thousand
  4 | July               ----+----------------    ----+-------------------
----+----------------      5 | ninth                8 | six thousand
  5 | October              5 | nineteenth         ----+-------------------
  5 | November           ----+----------------      9 | three thousand
----+----------------      6 | second             ----+-------------------
  6 | September          ----+----------------     10 | two thousand
                           7 | seventh
                           7 | seventeenth
                         ----+----------------
                           8 | third
                           8 | sixth
                           8 | tenth
                           8 | thirteenth
                           8 | sixteenth
                           8 | thirtieth
                           8 | thirty-first
                         ----+----------------
                           9 | twelfth
                           9 | twentieth
                           9 | twenty-*
\$\endgroup\$
  • \$\begingroup\$ 104 bytes \$\endgroup\$ – Shaggy Sep 26 '18 at 20:25
  • \$\begingroup\$ @Shaggy Oops... This m= was, of course, completely useless. Thanks. :) \$\endgroup\$ – Arnauld Sep 26 '18 at 20:29
  • 1
    \$\begingroup\$ That was quick! Nicely done. The "test all dates" and illustrative table are especially appreciated. \$\endgroup\$ – souldeux Sep 27 '18 at 0:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.