Listar todas las fechas principales palindrómicas entre 0000-01-01 y 99999-12-31

11

Ya sabes lo que son un palíndromo , una prima y una cita .

Su tarea es enumerar todas las fechas en 100 miles de años que cumplan con las tres características.

No importa nada más que los números, utilizan los siguientes formatos: AAAAMMDD y YYYYYMMDD .

Las fechas entre 0000-01-01 y 9999-12-31 deben imprimirse como fechas de palíndromos de 8 dígitos (si hay alguna) y las fechas entre 10000-01-01 y 99999-12-31 deben imprimirse como palíndromos de 9 dígitos .

No es obligatorio enumerar las fechas en orden cronológico.

Parte de ejemplo de salida válida.

Primeras tres fechas palindrómicas primas de 9 dígitos:

...
100111001
100131001
100161001
...

Reglas

Se aplican lagunas estándar .

Plarsen
fuente
Regla: 02-29solo existe para años que son divisibles por 400 o (divisibles por 4 y no divisibles por 100).
user202729
@ user202729 Sí, creo que sí, por ejemplo, no creo que 2017-02-29, 2018-02-29 y 1900-02-29 puedan considerarse "fechas".
Erik the Outgolfer
44
No hay fechas palindrómicas de 8 dígitos que también sean números primos. Aquí hay un pastebin la lista que se supone que debemos devolver / imprimir (197 en total) . ¿Es esto correcto @Plarsen?
Kevin Cruijssen
1
¿Deberíamos permitir el 30 de febrero? > timeanddate.com/date/february-30.html
jrtapsell
3
El año 0000 nunca sucedió
Jonathan Allan

Respuestas:

5

Ruby , 144 141 bytes (134 + 7 para la -rprimebandera)

¡Guardado 3 bytes gracias a benj2240 !

('01'..'12').map{|m|('01'..'31').map{|d|(?0..?9).map{|k|q=m+d
y=q.reverse+k
r=y+q
Time.new(y,m,d).day==d.to_i&&r.to_i.prime?&&(p r)}}}

Pruébalo en línea!

El algoritmo:

  • generar todas las combinaciones MMDD posibles, desde "0101" hasta "1231"
  • generar todos los años para esa fecha que resultaría en un palíndromo, invirtiendo la cadena MMDD y agregando en el medio, a su vez, todos los caracteres en el rango (0..9)
  • comprobar si es una fecha válida mediante la creación de una Timeinstancia con el dado y, m, dvalores. Si el objeto de tiempo resultante tiene un #dayvalor igual a d, entonces esa era una fecha válida. De lo contrario, cambiaría la fecha (por ejemplo, Time.new 2018,2,30devoluciones 2018-03-02).
  • compruebe si la fecha válida de palíndromo también es primo y muéstrela si es así.

El bucle interno era inicialmente una función que se llamaba para cada elemento en el (?0..?9)rango, así como para la cadena vacía.

Como la cadena vacía no produjo resultados (no hay palíndromos primos de 8 dígitos válidos), decidí eliminarla y refactorizar esta versión.

Cristian Lupascu
fuente
Creo que puede guardar algunos bytes eliminando la tvariable: TIO
benj2240
@ benj2240 ¡Eso es correcto! ¡Gracias!
Cristian Lupascu
4

Python 2 , 116 107 128 122 119 bytes

def g(n=9**8):
 while n<1e9:
  n+=2;m=n/100%100
  if 0<m<13and n%100<31+(m+m/8)%2and`n`[::-1]==`n`and 2**n%n==2:print n

La segunda mitad de la cuarta línea está inspirada en la respuesta de mxdsp aquí a otra pregunta de golf .

Explicación

La función g()toma un argumento solo para inicializar la nvariable usando su valor predeterminado. El valor inicial es un número impar que es lo más corto posible y lo más grande posible sin dejar de ser la primera respuesta válida 100111001.

Bucle hasta nllegar al final del rango de fechas 10 9 . Incrementar nen 2. mes el mes de la fecha n.

Si nes una fecha válida, palíndromo y primo, imprímala:

  • Fecha:
    • 0 < m < 13comprueba que mes un mes válido.
    • n % 100 < 31 + (m+m/8)%2comprueba que ese ndía del mes es válido. (m+m/8)%2agrega 1para todos los meses con 31 días. El crédito por eso va a la respuesta de ArmanX . No hay primos para el 29 y 30 de febrero.
  • Palíndromo: `n`[::-1] == `n`. Los backticks stringify n. [::-1]invierte la cadena.
  • Prime: 2**n % n == 2es una prueba de primalidad de Fermat . Esa prueba es solo probabilística. También hay no primos que coinciden. Pero no en el rango de números que estamos viendo.
mercator
fuente
¡Agradable usando la prueba de primalidad de Fermat!
agtoever
3

APL (Dyalog Unicode) , 155 bytes

CY'dfns'
n←⍕x
m←(⍎2↑¯4n)
d←(⍎¯2n)
:If n≡⌽n
:AndIf 1 pco x
:AndIf m<13
:AndIf d<32
:If m d2 29
:AndIf (400|⍎((≢n)-4)↑n)=0
⎕←x
f x+72
:End
⎕←x
:End
f x+1

Pruébalo en línea!

Este es un Tradfn ( trad itional f unctio n ) que toma un argumento arg = yyyymmddo arg = yyyyymmdd. El uso es f arg.

Esto no generará nada cuando el argumento comience en 10000101porque no encuentra una fecha de palíndromo principal en 60 segundos.

Aquí hay un enfoque menos complejo que generará la salida de ejemplo de OP de

100111001
100131001
100161001

Pruébelo en línea! )

Observe que ambos códigos son exactamente iguales hasta justo antes de llamar a la función de forma recursiva para la próxima fecha. Si bien la versión de golf simplemente lo llama así f arg+1, el código menos golfizado salta de día 31en día 01y de mes 12a mes 01, lo que lo acelera un poco.

Cómo funciona:

CY'dfns'                    Copy (⎕CY) all dfns to enable the use of pco.
n←⍕x                         Assign (←) the input to the variable n.
m←(⍎2↑¯4n)                  Take (↑) the last 4 4) elements of n, then take the first 2 elements of that and assign to m. 
d←(⍎¯2n)                    Take the last 2 2) elements of n, and assign to d.
:If n≡⌽n                     If n matches (≡) its reverse (⌽) (is a palindrome)
:AndIf 1 pco x               And a prime (1 pco)
:AndIf m<13                  And month < 13
:AndIf d<32                  And day < 32
:If m d2 29                 If it is 2/29
:AndIf (400|⍎((≢n)-4)↑n)=0   And the year mod 400 = 0
⎕←x                          Print x
f x+72                       call f with arg year0301
:End
⎕←x                          Print x
:End
f x+1                        call f for the next date.
J. Sallé
fuente
2

Python 3, 163 bytes

r=range
for m in r(1,13):
 for d in r(1,31+(m%2==(m<8))-2*(m==2)):
  t="%02d"*2%(m,d)
  for i in r(10):x=int(t[::-1]+str(i)+t);all(x%i for i in r(2,x))and print(x)

La solución es bastante larga (y probablemente se puede mejorar), pero no utiliza ninguna función integrada para la comprobación de prim / date / palindrome. Una versión un tanto descuidada para mayor claridad:

for month in range(1,13):
    for day in range(1,31 + (month%2==(month<8)) - 2*(month==2)):
        t = "%02d%02d" % (month, day)
        for i in range(10):
            x = int(t[::-1] + str(i) + t)
            if all(x%i for i in range(2,x)):print(x)

Las fechas válidas se generan al elegir un mes y un día. Como se comentó anteriormente, solo se debe considerar el tamaño 9. También tenga en cuenta que los años bisiestos no se consideran. Esto no es necesario debido a la afortunada coincidencia de que los primos de palíndromo de longitud 9 que terminan en 0229 simplemente no existen (otras anomalías de fecha como el 30 de febrero de 1712 pueden descartarse por la misma razón).

A continuación, el dígito del medio se elige libremente y se realiza una prueba principal. Debido a que la prueba principal tenía que ser lo más corta posible, es muy ingenua y, por lo tanto, muy lenta. El uso de una biblioteca externa podría resolver esto (y guardar algunos bytes), pero como se mencionó anteriormente, no quería usar ninguno.

Def
fuente
Debe hacer que su código se vea exactamente como lo hace cuando cuenta los bytes (en este caso al contraer el espaciado de sangría). Además, es genial que hayas incluido una versión sin golf, pero por lo general la versión de golf aparece en primer lugar
wnnmaw
@wnnmaw La única diferencia entre la versión con la que conté en la respuesta es que usé pestañas en lugar de los espacios que se usan aquí. Como sé, las pestañas se convierten automáticamente, por lo que no veo ninguna forma de solucionarlo.
Def
@Def IIRC Python le permite usar espacios como sangrías también, de esa manera también podría verse igual en su respuesta. Sin embargo, corrígeme si me equivoco en la primera parte.
elementbound
@elementbound De hecho, gracias por la sugerencia.
Def
2

WolframLanguage (Mathematica) 187 bytes

Puede haber alguna reducción en el tamaño que se encuentra. Explicación a seguir ...

t=ToString;p=PadLeft;d=DateObject;Cases[""<>{t/@p[#,If[Length@#<5,4, 5]],t/@ p[#2,2],t/@p[#3,2]}&@@@(IntegerDigits/@#[[1]]&/@DayRange[d@#,d@#2]),x_/;PalindromeQ@x&&PrimeQ@ToExpression@x]&

Casos de prueba

t = ToString; p = PadLeft; d = DateObject;
Cases["" <> {t /@ p[#, If[Length@# < 5, 4, 5]], t /@ p[#2, 2], 
   t /@ p[#3, 2]} & @@@ (IntegerDigits /@ #[[1]] & /@ DayRange[d@#, d@#2]), 
   x_ /; PalindromeQ@x && PrimeQ@ToExpression@x] &[{10011, 10, 1}, {10017, 1, 1}]

(* {"100111001", "100131001", "100161001"} *)

Explicación de código

DayRange[d@#,d@#2]devuelve todas las fechas entre {10011, 10, 1}y {10017, 1, 1}. En este caso, devuelve aproximadamente 5 años, 4 meses de fechas (precisamente 1920 fechas). Los años bisiestos se tienen en cuenta.

Las fechas se devuelven en el formato estándar Wolfram. Por ejemplo, la primera fecha aparecerá como DateObject[List[1,1,1],"Day","Gregorian",-5.] `

#[[1]] & /@eliminará la parte de la fecha, en cada fecha, que nos concierne. En el ejemplo, DateObject[List[1,3,7],"Day","Gregorian",-5.]devuelve la fecha abreviada, {1,3,7}.

t/@p[#3,2]}o ToString/@Padleft[#3,2]rellena el tercer elemento, a saber, el 7 que se encuentra "para el 7º día del mes" como "07". Se proporciona un relleno similar para el símbolo de un solo dígito para el mes de marzo, es decir, 3se devuelve como "03".

p[#, If[Length@# < 5, 4, 5]]rellena el año con ceros para alcanzar la longitud de una cadena de 4 o 5 dígitos. En este caso, enero, a saber 1, se devuelve como "00001" '.

"" <>...une las cuerdas. En este caso, vuelve "000010307".

Cases[...x_ /; PalindromeQ@x && PrimeQ@ToExpression@x] devuelve esos casos, entre las fechas de 1920, que son palíndromos y números primos.

DavidC
fuente
2

Javascript , 187 177

Suposiciones: no coinciden años de 4 dígitos; no hay días coincidentes en febrero entre 29-30

p=n=>(n<10?'0':'')+n;f=n=>n[3]+n[2]+n[1]+n[0];for(m=13;--m;)for(d=31+(m+(0|m/8))%2;--d;){for(y=10;y--;){z=p(m)+p(d);Y=+(f(z)+y+z);for(i=2;Y%i&&i*i<Y;i++);if(Y%i)console.log(Y)}}

Funciona así:

p=n=>(n<10?'0':'')+n;       //Prepend a 0 for 1-digit numbers and convert to a string
f=n=>n[3]+n[2]+n[1]+n[0];   //Flip four digits
for(m=13;--m;)              //Month loop, from 12 to 1
 for(d=
       31+(m+(0|m/8))%2     //Calculate the days in the month, allowing  Feb. 29 & 30
                       ;--d;){ //Day loop
  for(y=10;y--;){           //Middle digit loop
   z=p(m)+p(d);             //Prepend zeros to the month and day
   Y=+(f(z)+y+z);           //Flip the digits; append the middle digit,
                            //month, and day; convert back to an integer
   for(i=2;Y%i&&i*i<Y;i++); //Check if it's a prime
    if(Y%i)console.log(Y)}} //If it doesn't divide evenly, it's not prime. Print it!

Historia:

  • 187 a 177: no hay fechas principales de palíndromo que caigan el 29 o 30 de febrero, por lo que podemos pretender que febrero tiene 30 días y guardar 10 caracteres.

Notas:

A través de las pruebas, descubrí que no hay coincidencias válidas que tengan años de 4 dígitos o caigan el 29 o 30 de febrero. Desafortunadamente, por el bien del código, hay exactamente cinco resultados (no válidos) que caen el 31 de varios meses. que solo tienen 31 días.

ArmanX
fuente
2

Java 10, 329 327 320 318 312 308 307 264 bytes

v->{for(int y=9999,m,d;++y<1e5;)for(m=0;++m<13;)for(d=0;++d<32;)try{java.time.LocalDate.of(y,m,d);var t=y+"".format("%02d%02d",m,d);long n=new Long(t),x=1;for(;n%++x%n>0;);if(t.contains(new StringBuffer(t).reverse())&n==x)System.out.println(t);}finally{continue;}}

-1 byte gracias a @assylias .

Explicación:

Pruébelo en línea (nota: la parte de verificación de cebado ha sido reemplazada por un método separado más eficiente, aunque incluso con eso todavía se agota después de 60 segundos, produciendo solo las primeras ~ 115 fechas de primo palindrómico).
Pastebin de todos los 197 resultados de una ejecución local.

v->{                           // Method without empty unused parameter and no return-type
  for(int y=9999,m,d;++y<1e5;) //  Loop over the years in the range [1000,9999]:
    for(m=0;++m<13;)           //   Inner loop over the months in the range [1,12]:
      for(d=0;++d<32;){        //    Inner loop over the days in the range [1,31]:
        try{java.time.LocalDate.of(y,m,d);
                               //     If it's a valid date:
          var t=y+"".format("%02d%02d",m,d);
                               //      Convert the numbers to a String in format "yyyyyMMdd"
          long n=new Long(t),  //      Convert this String to a long
          x=1;for(;n%++x%n>0;);//      Prime-checking loop
          if(t.contains(new StringBuffer(t).reverse())
                               //      If the string is palindromic
             &n==x)            //      and the long is a prime:
            System.out.println(t);
                               //       Print the string with trailing newline
        }finally{              //     If it isn't a valid date:
          continue;}}}         //      Continue to the next iteration of the inner-most loop
Kevin Cruijssen
fuente
1
if(t.equals(new StringBuffer(t).reverse()+"")-> if(t.contains(new StringBuffer(t).reverse())para guardar 1 carácter (funciona porque sabemos que ambas cadenas tienen la misma longitud). Eso no es mucho :-(
assylias
@assylias Smart, me gusta. ¡Gracias! Y aunque 1 byte no es mucho, sigue siendo 1 byte. Codegolf siempre trata de hacerlo lo más corto posible, por lo que cada byte cuenta. :)
Kevin Cruijssen
1

VBA, 347

Sub PalindromeDate()
Dim DateString As String
For i = 0 To 9999
    For j = 1 To 12
        For k = 1 To 31
        DateString = Format(i, "0000") & Format(j, "00") & Format(k, "00")
        If DateString = StrReverse(DateString) Then
        Debug.Print DateString
        Else
        End If
        Next k
        Next j
        Next i

End Sub
Selkie
fuente
Bienvenido a PPCG! No conozco VBA, pero parece que podrías jugar un poco de espacio en blanco.
FantaC
Tampoco sé realmente VBA, pero creo que DateStringes un nombre de variable arbitrario, por lo que debería poder reducirlo a un solo carácter, ¿verdad?
Martin Ender
3
Y creo que te perdiste la parte principal de las "fechas principales palindrómicas".
mercator
Habría algún código para calcular los años bisiestos (el que tiene 29 días de febrero)
RosLuP
También faltan años de 5 dígitos, y Else no es necesario.
Weijun Zhou
0

Limpio , 262 ... 213 bytes

import StdEnv
@ =(rem)
f=[d\\d<-[a*10^4+b*100+c\\a<-[10^4..99999],b<-[1..12],c<-[1..28+[0,3,if(@a 400<1|| @a 4<1&& @a 100>0)1 0,3,2,3,2,3,3,2,3,2,3]!!b]]|(\k=k==reverse k)[p\\p<-:toString d]&&all((<)0o@d)[2..d-1]]

Pruébalo en línea!

Οurous
fuente
0

Javascript , 234 229 bytes

Un poco voluminoso, pero lo publica para que la bola de JS ruede. Cualquier sugerencia bienvenida!

f=n=>100+10*n+n/10|0
p=n=>{for(i=2;i<n;n=n%i++<1?0:n);return n>1}
q=n=>(''+(100+n)).slice(-2)
r=_=>{for(m=13;--m;)for(d=32;--d;)for(x=10;--x+1;){s=q(f(d))+q(f(m))+x+q(m)+q(d);if(p(s|0)&&d<(m==2?29:31+(m+m/8|0)%2))console.log(s)}}

Sin golf:

// Flip a one- or two-digit number
f=n=>100+10*n+n/10|0

// Primality test
// For initial testing, you can replace this line with:
//      p=require('primality')
// This uses the primality npm module and is way faster
p=n=>{for(i=2;i<n;n=n%i++<1?0:n);return n>1}

// Convert number to string, pad with zeroes if necessary
q=n=>(''+(100+n)).slice(-2)

r=_=>{
    // Loop months
    for(m=13;--m;)
        // Loop days
        for(d=32;--d;)
            // Loop middle digit
            for(x=10;--x+1;) {
                // Construct 'date'
                s = 
                    // Start with day and month, each flipped
                    q(f(d))+q(f(m)) + 
                    // Add middle digit ( will be casted to string since the previous expression is also a string)
                    x + 
                    // Add month and date as they are
                    q(m)+q(d);

                if(
                    // Check for primality
                    p(s|0) && 
                    // Check if it's a valid date by validating day ( month and year will always be valid)
                    d<(
                        // For February, we always assume 28 days ( check for 29 because we use less than)
                        m==2?29 : 
                        // For other months, it alternates between 31 and 30
                        // EXCEPT July and August both have 31 days, then continues alternating
                        31+(m+m/8|0)%2))
                    console.log(s)
            }
}

Cómo funciona:

La magia de volteo de dígitos se basa principalmente en la experimentación.
Comencé por averiguar de qué número restar para obtener la versión invertida. Solo me importaban los dos últimos dígitos.
Entonces, si tomamos n, buscamos keso n+k=flip(n). Para 10<n<20 kcomenzado en 101 y el aumento en incrementos de 9. Sin embargo, para n<10, esto era 100. asumí kaumentó para cada salto de 10, y después de un poco de tocar el violín que pensé que era correcto.
Entonces, k=100+9*n+n//10donde // significa división entera.

Por lo tanto, obtenemos n+k = n+(100+9*n+n//10) = 100+10*n+n//10 = flipped(n).

No puedo probar, ni afirmar que esto funciona para cualquier número, pero produjo resultados correctos para los números utilizados aquí.

Para la prueba de primalidad, acredite la respuesta de Kevin Cruijssen . Tenía una versión un poco más corta, pero no pude hacerlo bien:

p=n=>{for(i=n;--i-1;)if(!(n%i))return 1;}

Me salteé la prueba de palíndromo, haciendo bucles durante meses, días y un dígito medio para poder construir cadenas como dDmMxMmDd, donde Des el primer dígito del día, des el segundo, etc.

Historia

Se ahorraron 5 bytes al deshacerse de la parte condicional de q

q=n=>n<10?'0'+n:(''+n).slice(-2) // from
q=n=>(''+(100+n)).slice(-2)      // to
elemento
fuente
Perdón por perder el tiempo con los bytes. Se deslizó en algunas pestañas suaves accidentalmente. Debería ser correcto ahora.
elementbound
Solo está usando fel resultado de 'como parámetro para' q, así que recorte el intermediario y escriba f=n=>''+n%10+(n/10|0), y el resultado de q siempre se usa como una cadena, para que pueda escribir q=n=>n<10?'0'+n:n.
Neil
0

NARS APL 626 bytes, 313 caracteres

f;y;m;d;i;k;v;x;t
t←{60⊥3↑3↓⎕TS}⋄t0←50+t
x←2 12⍴v,v←31 28 31 30 31 30 31 31 30 31 30 31
x[2;2]←29⋄m←d←1⋄y←10000
X:  i←{(0=4∣⍵)∧0≠100∣⍵:1⋄0=400∣⍵:1⋄0}y
A:  →0×⍳y≥1e5
    →0×⍳t≥t0
    k←d+100×m+y×100
    →B×⍳∼k=⍎⌽⍕k⋄→B×⍳∼0πk⋄⎕←k
B:  d+←1
    →A×⍳d≤x[1+i;m]
    d←1⋄→C×⍳∼m=12⋄m←1⋄y+←1⋄→X
C:  m+←1⋄→A

Esto imprime lo que encuentra en 50 segundos, que se detiene (porque de lo contrario no puedo detener el programa para copiar y pegar la prueba, porque no sé cómo detener el programa sin cerrar las ventanas del intérprete):

  f
100111001
100131001
100161001
101030101
101060101
101141101
101171101
102040201
102070201
103000301
103060301
104000401
104030401
104040401
RosLuP
fuente
0

Julia 0.6 , 109 bytes

El enlace va a una versión más larga con dos diferencias:

  1. Comprueba primos con función escrita a mano, ya que el paquete Primes no está disponible en TIO.
  2. Itera en un intervalo de fechas diferente para no agotar el tiempo de espera.
[s for s in Dates.format(Date(0,1,1):Date(100000,1,1),"YYYYmmdd") if Primes.isprime(parse(s))&&s==reverse(s)]

Pruébalo en línea!

gggg
fuente