Forecast Palindromic Dates

18

1

Palindromic dates are dates that appear as palindromes: the string of digits can be read the same way backwards as forwards. For the North American date format (MM/DD/YYYY), the next few palindromic dates are:

02/02/2020

12/02/2021

03/02/2030

The Challenge

Create a function that returns all palindromic dates in a consistent, common date format (of your choosing) that fall within a range of dates (edit: including the range itself).

Rules

  • To qualify as a palindrome, only the numeric characters of the date should be checked.
  • The date can be in any common format (MM/DD/YYYY, DD-MM-YYYY), as long as it uses two digits for both the month and day and four for the year, and it uses a character to separate parts of the date. The output must preserve seperating characters (/, -, etc.). Your function only needs to handle one distinct date format. Please include the format in your answer.
  • If there are more than one dates returned, they should be comma or new-line separated.
  • Shortest answer wins!

Example

date_palindrome('05/02/2050', '12/12/2060')
>>>['05/02/2050', '06/02/2060']

atlasologist

Posted 2016-06-23T16:12:02.270

Reputation: 2 945

If i want to post a Oracle SQL answer can I use the input type DATE avoiding a to_date() or I have to use the less golfable VARCHAR2? – Giacomo Garabello – 2016-06-24T12:18:06.847

I don't know enough about Oracle SQL to answer this. – atlasologist – 2016-06-24T17:22:13.450

Answers

8

MATL, 24 23 bytes

YOZ}&:"@23XOtt47>)tP=?8M

Accepts input in the form of an array of string {lower, upper} where the date format is 'MM/DD/YYYY'. Output is in the format MM/DD/YYYY as well.

Try it Online

Explanation

        % Implicitly grab the two inputs
YO      % Convert to serial date format
Z}      % Push them onto the stack separately
&:      % Create an array from [lower...upper] incrementing 1 day
"       % For each day
  @23XO % Get the string version of the date (mm/dd/yyyy)
  tt    % Duplicate twice
  47>)  % Get the numeric parts
  tP=   % Compare numeric part with the flipped version of the numeric part
  ?8M   % If they are the same push it to the stack
        % Implicitly display stack contents

Suever

Posted 2016-06-23T16:12:02.270

Reputation: 10 257

6

Python 2, 197 bytes

One byte saved thanks to @cat!

from datetime import*
def g(a,b):
 for s in"ab":exec"%s=date(*[int(x)for x in %s.split('-')])"%(s,s)
 for d in range((b-a).days+1):
    x=str(a+timedelta(d));y=x.replace("-","")
    if y==y[::-1]:print x

Try it here!

Input and output format is YYYY-MM-DD. First intendation level is spaces, second one is tabs.
Nothing too special going on here. Uses some exec abuse to convert the input to date objects by splitting the date string on - and splatting the list into the date constructor. Then we just iterate over all dates in their inclusive range and print the ones which are palindromic.

Denker

Posted 2016-06-23T16:12:02.270

Reputation: 6 639

1Put the from datetime import* on the first line to save a byte – cat – 2016-06-24T11:40:29.440

Not sure, but does \a+timedelta(d)`` the same as str(a+timedelta(d))? – Mathias711 – 2016-06-24T12:53:29.247

1@Mathias711 Unfortunately not, repr is usually only equivalent to str for primitive datatypes. For date objects I get datetime.date(2012, 12, 12) for instance. – Denker – 2016-06-24T17:28:58.940

6

Bash + GNU utilities, 116 84

Requires 64-bit version of date for the given testcase.

set date -uf- +%
jot -w@ - `$@s` 86400|$@F|sed -r 'h
:
s/-|^(.)(.*)\1$/\2/
t
/./d
g'

I/O is in YYYY-MM-DD format. Input is taken from two lines of stdin, e.g.

printf "%s\n" 2050-05-02 2060-12-12 | ./palindate.sh

Explanation

  • set saves the date command template so it may be accessed using the $@ parameter
  • date -uf- +%s converts endpoint dates to number of seconds since the Unix epoch
  • jot interpolates this to give a list of seconds-from-the-epoch, one per day, each prefixed with @
  • date -uf- +%F formats each list entry as YYYY-MM-DD
  • sed checks for palindromes:
    • h save the input line to the hold buffer
    • : define "unnamed" label
    • s/-|^(.)(.*)\1$/\2/ if a dash is found, remove it or if the first and last characters match, remove them
    • t if there was a match above, jump back to the unnamed label
    • /./d if there are any characters left over, the line is not a palindrome - delete it and continue to the next line
    • g if we got here, then no line deletion happened, thus the line must have been a palindrome. Get the line back from the hold buffer and implicitly display it.

Digital Trauma

Posted 2016-06-23T16:12:02.270

Reputation: 64 644

5

PowerShell v2+, 127 bytes

for($a,$b=[datetime[]]$args;$a-le$b){if(($c="{0:yyyyMMdd}"-f$a)-eq-join$c[$c.length..0]){"{0:MM/dd/yyyy}"-f$a}$a=$a.AddDays(1)}

Takes input as command-line arguments $args in MM/DD/YYYY (or similar) format and recasts as a [datetime] array, stores them in $a and $b. That's the setup step of the for loop. The conditional is so long as $a is less-than-or-equal-to $b.

Each iteration, we set $c equal to a -formatted string of yyyyMMdd style, based on $a. We then compare if that's -equal to $c reversed (using an array-join trick). If so, we output $a in the proper format. Either way, we increment $a with .AddDays(1) to move to the next day.

Example

PS C:\Tools\Scripts\golfing> .\forecast-palindromic-dates.ps1 '06/23/2016' '12/12/2020'
02/02/2020

AdmBorkBork

Posted 2016-06-23T16:12:02.270

Reputation: 41 581

4

Julia, 132 bytes

f(a,b,t=s->DateTime(s,"mm/dd/y"),g=d->Dates.format(d,"mm/dd/yyyy"))=map(g,filter(d->(r=replace(g(d),"/",""))==reverse(r),t(a):t(b)))

This is a function that accepts two strings and returns an array of strings.

Ungolfed:

function f(a, b)
    # Define a function to create a DateTime object from a string
    t = s -> DateTime(s, "mm/dd/y")

    # Define a function to create a string from a DateTime object
    g = d -> Dates.format(d, "mm/dd/yyyy")

    # Filter the range a:b to palindromic dates
    p = filter(d -> (r = replace(g(d), "/", "")) == reverse(r), t(a):t(b))

    # Format all dates in the array
    m = map(g, p)

    return m
end

Try it online!

Alex A.

Posted 2016-06-23T16:12:02.270

Reputation: 23 761

3

JavaScript (ES6), 159 154 bytes

(s,e)=>{for(r=[],s=Date.parse(s),e=Date.parse(e);s<=e;s+=864e5){d=new Date(s).toJSON().slice(0,10);`${a=d.match(/\d/g)}`==a.reverse()&&r.push(d)}return r}

I/O in ISO format. Ungolfed:

function date_palindrome(start, end) {
    start = Date.parse(start);
    end = Date.parse(end);
    var result = [];
    while (start <= end) {
        var date = new Date(start).toISOString().slice(0, 10);
        var digits = date.match(/d/g);
        if (digits.join() == digits.reverse.join()) {
            result.push(date);
        }
        start += 24 * 60 * 60 * 1000; // ms
    }
    return result;
}

Neil

Posted 2016-06-23T16:12:02.270

Reputation: 95 035

2

Java 7, 436 435 416 bytes *sigh..*

import java.text.*;import java.util.*;void c(String...a)throws Exception{DateFormat f=new SimpleDateFormat("dd-MM-yyyy");Calendar s=Calendar.getInstance(),e=Calendar.getInstance();s.setTime(f.parse(a[0]));e.setTime(f.parse(a[1]));for(Date d=s.getTime();s.before(e);s.add(5,1),d=s.getTime()){String o=f.format(d),x=o.replaceAll("\\W|_",""),w="";for(char c:x.toCharArray())w=c+w;if(x.equals(w))System.out.println(o);}}

Input & Output format: dd-MM-yyyy

Ungolfed & test code:

Try it here.

import java.text.*;
import java.util.*;

class Main{
  static void c(String... a) throws Exception{
    DateFormat f = new SimpleDateFormat("dd-MM-yyyy");
    Calendar s = Calendar.getInstance(),
             e = Calendar.getInstance();
    s.setTime(f.parse(a[0]));
    e.setTime(f.parse(a[1]));
    for(Date d = s.getTime(); s.before(e); s.add(Calendar.DATE, 1), d = s.getTime()){
      String o = f.format(d),
             x = o.replaceAll("\\W|_", ""),
             w = "";
      for(char c : x.toCharArray()){
        w = c + w;
      }
      if(x.equals(w)){
        System.out.println(o);
      }
    }
  }

  public static void main(String[] a){
    try{
      c("05-02-2050", "12-12-2060");
    } catch (Exception e){}
  }
}

Output:

05-02-2050
15-02-2051
25-02-2052
06-02-2060

Kevin Cruijssen

Posted 2016-06-23T16:12:02.270

Reputation: 67 575

2+1. Cause, y'know, Java. – cat – 2016-06-24T11:39:42.717

@cat Thanks for the comment I guess, but you forgot to actually +1 the answer. ;P – Kevin Cruijssen – 2016-06-24T11:45:35.600

Well, actually, my lazy browser didn't feel like agreeing that I +1'd and so when I refresh, bam, my vote is gone D: – cat – 2016-06-24T11:47:07.630

2

TSQL, 88 bytes

Using ISO8601 format for date(yyyy-mm-dd)

DECLARE @ date='2050-05-02',@t date='2060-12-12'

a:IF stuff(reverse(@),3,1,'')=stuff(@,8,1,'')PRINT @
SET @=dateadd(d,1,@)IF @<=@t GOTO a

Fiddle

t-clausen.dk

Posted 2016-06-23T16:12:02.270

Reputation: 2 874

1

Oracle 11: SQL: 246 bytes (hey, at least I beat Java :P lol )

with d as(select to_date('&1','yyyy-mm-dd')s,to_date('&2','yyyy-mm-dd')e from dual),r as(select level-1 l from d connect by level<=e-s+1),x as(select s+l y,to_char(s+l,'yyyymmdd')w from d,r)select to_char(y,'yyyy-mm-dd')from x where w=reverse(w);

Output:

  SQL> with d as(select to_date('&1','yyyy-mm-dd')s,to_date('&2','yyyy-mm-dd')e from dual),r as(select level-1 l from d connect by level<=e-s+1),x as(select s+l y,to_char(s+l,'yyyymmdd')w from d,r)select to_char(y,'yyyy-mm-dd')from x where w=reverse(w);
  Enter value for 1: 2000-01-01
  Enter value for 2: 2021-01-01

  TO_CHAR(Y,
  ----------
  2001-10-02
  2010-01-02
  2011-11-02
  2020-02-02

  SQL>

In readable format:

  with d as (select to_date('&1','yyyy-mm-dd') s,
                    to_date('&2','yyyy-mm-dd') e
              from dual),
        r as (select level-1 l 
                from d connect by level <= e-s+1),
        x as (select s+l y, to_char(s+l,'yyyymmdd') w 
                from d,r)
  select to_char(y,'yyyy-mm-dd')
    from x 
   where w=reverse(w);

Explained:

d: get input for start/end
r: generate rows needed, 1 per day.
x: calculate the actual dates, and convert them to a minimal string.
final: use REVERSE function to verify the palindroms, return in proper format.

Learned about the REVERSE function today :)

Ditto

Posted 2016-06-23T16:12:02.270

Reputation: 495

1

C#, 97 94 bytes

(a,b)=>{for(;a<b;a=a.AddDays(1))if($"{a:yyy}".SequenceEqual($"{a:MMdd}".Reverse()))a.Dump();};

C# lambda (Action) where inputs are DateTime and the output is printed by using the .Dump() method (@EvilFonti's trick).


C#, 115 112 bytes

(a,b)=>{var r="";for(;a<b;a=a.AddDays(1))if($"{a:yyy}".SequenceEqual($"{a:MMdd}".Reverse()))r+=a+",";return r;};

C# lambda (Func) where inputs are DateTime and output is a string.

Code:

(a,b)=> {
    var r="";
    for(;a<b;a=a.AddDays(1)) {
        if($"{a:yyy}".SequenceEqual($"{a:MMdd}".Reverse()))
            r+=a+",";
    }
    return r;
};

Try them online!

aloisdg moving to codidact.com

Posted 2016-06-23T16:12:02.270

Reputation: 1 767

0

VBA, 240 193 bytes

Function f(a, b)
Dim j, g()
For i = CDate(a) To CDate(b)
    If Format(i, "yyyy") = StrReverse(Format(i, "mmdd")) Then
        ReDim Preserve g(j)
        g(j) = Format(i, "yyyy-mm-dd")
        j = j + 1
    End If
Next
f = g()
End Function

That's it in a comprehensible format. Test case:

Sub e()
MsgBox Join(f("5/2/2050", "6/2/2060"), ", ")
End Sub

Without that much redundancy:

Function f(a,b)
Dim j, g()
For i=CDate(a) To CDate(b)
If Format(i,"yyyy")=StrReverse(Format(i,"mmdd")) Then
ReDim Preserve g(j)
g(j)=Format(i,"yyyy-mm-dd")
j=j+1
End If
Next
f=g()
End Function

user3819867

Posted 2016-06-23T16:12:02.270

Reputation: 439

0

Javascript (using external library) (158 bytes)

(a,b)=>_.RangeTo(a%1e20,b%1e20,864e5).Select(y=>new Date(y)).Where(x=>z=(_.From(x.toJSON()).Where(y=>!isNaN(y)).Take(8)).SequenceEqual(z.Reverse())).ToArray()

Link to lib: https://github.com/mvegh1/Enumerable

Code explanation: Ok, I finally used some actual code golfing here for once. So the inputs a,b are Date objects. Create a range of integers from a to b, where a and b are coerced into integers, and the distance between values in the range is 86400000, i.e the amount of ticks in one day. Map each value in the range to a date object. Filter that range by the predicate that represents palindromic dates. The logic to determine that is simple...cast the JSON string representation of the current date object to a char array using the library and filter out the non-numeric entries, and only take the first 8 values (because the that would be yyyyMMdd) and store that into variable z, then check if z is equivalent to z Reversed. Finally, cast back to native JS array

Edit: Shaved 2 bytes by removing unnecessary parens..

enter image description here

applejacks01

Posted 2016-06-23T16:12:02.270

Reputation: 989

0

Java, 269 bytes

import java.time.LocalDate;void q(String...a)throws Exception{LocalDate s=LocalDate.parse(a[0]);while(!s.isAfter(LocalDate.parse(a[1]))){String d=s.toString().replace("-","");if(d.equals(new StringBuffer(d).reverse().toString()))System.out.println(d);s=s.plusDays(1);}}


Ungolfed:

import java.io.IOException;
import java.time.LocalDate;

public class UnGolfedPalindromicDates {
    public static void main(String...a) throws IOException {
        LocalDate start = LocalDate.parse(a[0]), end = LocalDate.parse(a[1]);
        while (!start.isAfter(end)) {
            String d = start.toString().replace("-","");
            if (palindrome(d)) System.out.println(d);
            start = start.plusDays(1);
        }
    }

    public static boolean palindrome(String s) {
        return s.equals(new StringBuffer(s).reverse().toString());
    }
}

416E64726577

Posted 2016-06-23T16:12:02.270

Reputation: 123