1
\$\begingroup\$

You get a string which contains an integer between 1000 and 99999999 as input. The input string might contain leading zeroes but cannot be longer than 8 characters.

Your goal is to output all dates between 6th of December 1919 and 5th of December 2019 which fit the input in these formats:

  • day - month - year (dmy)
  • month - day -year (mdy)
  • year - month - day (ymd)

Days and months can be either one or two digits. Years can be either two or four digits. Also don't forget the leap years!


Your output dates must be all in the same format (choose one). Its days, months and years must be clearly distinguishable (choose a separator or encode them like YYYYMMDD).

You are free to leave any duplicate dates in your output (you're a good boy if you remove them though). If there are no dates to return, return nothing.

Examples:

Input:  "1234"
Output: 1934-02-01, 2012-03-04, 1934-01-02

Input:  "01234"
Output: 1934-01-02, 1934-02-01

Input:  "01211"
Output: 2001-11-01, 2011-01-01, 2001-01-11

Input:  "30288"
Output: 1988-02-03, 1988-02-30, 1988-03-02

Input:  "999999"
Output:

Shortest code in bytes wins. Have fun!

\$\endgroup\$
6
  • 1
    \$\begingroup\$ In your examples you have inputs with leading zeros. However you say that inputs are integers between 1000 and 99999999. Hence 1234 is equivalent to 01234. This needs clarified \$\endgroup\$ Commented Dec 5, 2019 at 17:28
  • \$\begingroup\$ Are there situations where a 7-digit integer leads to non-empty output? \$\endgroup\$ Commented Dec 5, 2019 at 17:31
  • \$\begingroup\$ @RobinRyder 2018111 should produce 2018-11-01,2018-01-11, if I'm understanding this challenge properly. \$\endgroup\$
    – 79037662
    Commented Dec 5, 2019 at 17:34
  • 3
    \$\begingroup\$ 1988-02-30 doesn't look like a valid date. \$\endgroup\$
    – Arnauld
    Commented Dec 5, 2019 at 17:41
  • 1
    \$\begingroup\$ Did you mean for the input to be "01111" for that example? \$\endgroup\$
    – 79037662
    Commented Dec 5, 2019 at 18:13

1 Answer 1

1
\$\begingroup\$

Ruby, 234 bytes

require'date'
a,b,g=%w(%Y%-m%d %Y%m%d %Y%-m%-d %Y%m%-d %-m%d%Y %m%d%Y %-m%-d%Y %m%-d%Y %d%-m%Y %d%m%Y %-d%-m%Y %-d%m%Y),Date.new(1920)-26,gets
(b..b+36524).map{|d|puts d.to_s if(a+a.map{|x|x.tr(?Y,?y)}).map{|x|d.strftime(x)}.member?g}

Try it online!

I'm willing to bet that this can be shortened this significantly (with regex maybe), but I'm not clever or knowledgable enough to figure that out.

If we are allowed to print the date object itself instead of a string, change puts d.to_s to p d.

\$\endgroup\$
3
  • \$\begingroup\$ The question has been closed now, but for future reference, [g]-array==[] is shorter than array.member?g by 1 byte, and is generally the shortest way to check if an element is in an array. \$\endgroup\$
    – Value Ink
    Commented Dec 6, 2019 at 22:22
  • \$\begingroup\$ On the regex generation angle, I feel like this works pretty well, can probably be optimized further but already shaves a solid 40 bytes on its own (since you don't need the a+a.map part anymore): a=%w(Y y -m m -d d);a=a.product(a,a).map{|e|?%+e*?%}.grep /y.*m.*d|(d.*m|m.*d).*y/i \$\endgroup\$
    – Value Ink
    Commented Dec 6, 2019 at 22:38
  • \$\begingroup\$ @ValueInk Thanks for the tips. \$\endgroup\$
    – 79037662
    Commented Dec 6, 2019 at 22:56

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