Listar todas as datas primárias palindrômicas entre 0000-01-01 e 99999-12-31

11

Você sabe o que é um palíndromo , um primo e um encontro .

Sua tarefa é listar todas as datas em 100 milhares de anos que atendem às três características.

Não se esqueça de nada, exceto os números, use os seguintes formatos: AAAAMMDD e AAAAAMMDD .

As datas entre 0000-01-01 e 9999-12-31 devem ser impressas como palíndromos de 8 dígitos (se houver alguma) e as datas entre 10000-01-01 e 99999-12-31 devem ser impressas como palíndromos de 9 dígitos .

Não é obrigatório listar as datas em ordem cronológica.

Exemplo de parte da saída válida.

Primeiras três datas palindrômicas primárias de 9 dígitos:

...
100111001
100131001
100161001
...

Regras

Aplicam-se brechas padrão .

Plarsen
fonte
Regra: 02-29existe apenas para os anos divisíveis por 400 ou (divisível por 4 e não divisível por 100).
usar o seguinte comando
@ user202729 Sim, acho que sim, por exemplo, acho que 2017-02-29, 2018-02-29 e 1900-02-29 podem ser considerados "datas".
Erik the Outgolfer
4
Não há datas palindrômicas de 8 dígitos que também sejam primos. Aqui está uma pasta na lista que devemos devolver / imprimir (197 no total) . @Plarsen correto?
Kevin Cruijssen
1
Devemos permitir 30 de fevereiro? > timeanddate.com/date/fevereiro-30.html
jrtapsell
3
O ano 0000 nunca aconteceu
Jonathan Allan

Respostas:

5

Ruby , 144 141 bytes (134 + 7 para o -rprimesinalizador)

Economizou 3 bytes graças 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)}}}

Experimente online!

O algoritmo:

  • gerar todas as combinações possíveis de MMDD, de "0101" a "1231"
  • gerar todos os anos para essa data que resultariam em um palíndromo, revertendo a sequência MMDD e adicionando no meio, por sua vez, todos os caracteres no intervalo (0..9)
  • verificar se que é uma data válida, criando uma Timeinstância com os dados y, m, dvalores. Se o objeto de hora resultante tiver um #dayvalor igual a d, essa era uma data válida. Caso contrário, ele mudaria a data (por exemplo, Time.new 2018,2,30retornos 2018-03-02).
  • verifique se a data válida do palíndromo também é primo e exiba-a se for.

O loop interno foi inicialmente uma função que foi chamada para cada elemento no (?0..?9)intervalo, bem como para a sequência vazia.

Como a sequência vazia não produziu resultados (não há palíndromos primos válidos de 8 dígitos), decidi removê-la e refatorar para esta versão.

Cristian Lupascu
fonte
Eu acho que você pode salvar alguns bytes removendo a tvariável: TIO
benj2240
@ benj2240 Isso mesmo! Obrigado!
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

A segunda metade da quarta linha é inspirada por mxdsp 's resposta aqui a outra pergunta de golfe .

Explicação

A função g()usa um argumento apenas para inicializar a nvariável usando seu valor padrão. O valor inicial é um número ímpar, o mais curto possível e o maior possível, mas ainda sendo menor que a primeira resposta válida 100111001.

Faça um loop até natingir o final do período 10 9 . O incremento nde 2. mé o mês da data n.

Se nfor uma data válida, palíndromo e prime, imprima-a:

  • Encontro:
    • 0 < m < 13verifica se mé um mês válido.
    • n % 100 < 31 + (m+m/8)%2verifica se no dia do mês é válido. (m+m/8)%2adiciona 1para todos os meses com 31 dias. O crédito por isso vai para a resposta da ArmanX . Não há números primos de 29 a 30 de fevereiro.
  • Palíndromo: `n`[::-1] == `n`. Os backticks estremecem n. [::-1]inverte a string.
  • Prime: 2**n % n == 2é um teste de primalidade de Fermat . Esse teste é apenas probabilístico. Também existem não primos correspondentes. Mas não no intervalo de números que estamos vendo.
mercator
fonte
Bom usando o teste de primalidade 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

Experimente online!

Esta é uma Tradfn ( trad itional f unctio n ) que leva um argumento arg = yyyymmddou arg = yyyyymmdd. O uso é f arg.

Isso não produzirá nada quando o argumento iniciar, 10000101pois não encontra uma data principal do palíndromo em 60 segundos.

Aqui está uma abordagem menos eficiente que produzirá o exemplo de saída do OP de

100111001
100131001
100161001

( Experimente online! )

Observe que os dois códigos são exatamente os mesmos até a direita antes de chamar a função recursivamente para a próxima data. Enquanto a versão golfista apenas chama assim f arg+1, o código menos golfado salta de dia 31para dia 01e de mês 12para mês 01, o que acelera bastante.

Como 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é
fonte
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)

A solução é bastante longa (e provavelmente pode ser aprimorada), mas não usa nenhuma função interna para verificação de prime / date / palíndromo. Uma versão um pouco não destruída para maior clareza:

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)

Datas válidas são geradas escolhendo um mês e dia. Como comentado anteriormente, apenas o tamanho 9 precisa ser considerado. Observe também que os anos bissextos não são considerados. Isso não é necessário devido à coincidência afortunada de que os primos palíndricos de comprimento 9 que terminam em 0229 simplesmente não existem (outras anomalias de datas como 30 de fevereiro de 1712 podem ser descartadas pelo mesmo motivo).

Em seguida, o dígito do meio é escolhido livremente e um teste principal é executado. Por causa do teste principal, ele tinha que ser o mais curto possível, é muito ingênuo e, portanto, extremamente lento. Usar uma biblioteca externa poderia resolver isso (e salvar alguns bytes), mas, como mencionado anteriormente, eu não queria usar nenhum.

Def
fonte
Você deve fazer com que seu código pareça exatamente como ele é quando contou bytes (nesse caso, recolhendo o espaçamento de recuo). Além disso, é ótimo que você incluiu uma versão ungolfed, mas geralmente a versão do golfe é o primeiro da lista
wnnmaw
@wnnmaw A única diferença entre a versão que contei com a fornecida na resposta é que usei guias em vez dos espaços usados ​​aqui. Como sei que as guias são convertidas automaticamente, não vejo como corrigir isso.
Def
O @Def IIRC Python também permite que você use espaços como recuos, assim também pode parecer o mesmo em sua resposta. Corrija-me se eu estiver errado na primeira parte.
elementbound
@elementbound De fato, obrigado pela sugestão.
Def
2

WolframLanguage (Mathematica) 187 bytes

Pode haver alguma redução no tamanho a ser encontrada. Explicação 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 teste

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"} *)

Explicação do código

DayRange[d@#,d@#2]retorna todas as datas entre {10011, 10, 1}e {10017, 1, 1}. Nesse caso, ele retorna aproximadamente 5 anos, 4 meses de datas (precisamente 1920 datas). Os anos bissextos são levados em consideração.

As datas são retornadas na formatação padrão da Wolfram. Por exemplo, a primeira data aparecerá como DateObject[List[1,1,1],"Day","Gregorian",-5.] `

#[[1]] & /@removerá a parte da data, em cada data, que nos interessa. No exemplo, DateObject[List[1,3,7],"Day","Gregorian",-5.]retorna a data abreviada {1,3,7},.

t/@p[#3,2]}ou ToString/@Padleft[#3,2]preenche o terceiro elemento, ou seja, o 7 em pé "para o 7º dia do mês" como "07". Preenchimento semelhante é fornecido para o símbolo de um dígito para o mês de março, ou seja, 3é retornado como "03".

p[#, If[Length@# < 5, 4, 5]]preenche o ano com zeros para atingir o comprimento de uma sequência de 4 ou 5 dígitos. Nesse caso, janeiro, ou seja 1, é retornado como "" 00001 "'.

"" <>...junta as cordas. Nesse caso, ele retorna "000010307".

Cases[...x_ /; PalindromeQ@x && PrimeQ@ToExpression@x] retorna aqueles casos, entre as datas de 1920, que são palíndromos e primos.

DavidC
fonte
2

Javascript , 187 177

Pressupostos: sem anos de 4 dígitos correspondentes; Não há dias correspondentes entre 29 e 30 de fevereiro

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 assim:

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!

História:

  • 187 a 177: não há datas primárias do palíndromo que caem nos dias 29 ou 30 de fevereiro, para que possamos fingir que o período de fevereiro tem 30 dias e economiza 10 caracteres.

Notas:

Através dos testes, descobri que não há correspondências válidas com anos de quatro dígitos ou que caem nos dias 29 ou 30 de fevereiro. Infelizmente, pelo bem do código, exatamente cinco resultados (inválidos) que caem no dia 31 de vários meses que têm apenas 31 dias.

ArmanX
fonte
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 graças a @assylias .

Explicação:

Experimente on-line (observação: a parte da verificação do prime foi substituída por um método separado mais eficiente, embora mesmo assim ele expire após 60 segundos, produzindo apenas as primeiras ~ 115 datas primárias palindrômicas).
Colar pasta de todas as 197 saídas de uma execução 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
fonte
1
if(t.equals(new StringBuffer(t).reverse()+"")-> if(t.contains(new StringBuffer(t).reverse())para salvar 1 caractere (funciona porque sabemos que as duas seqüências têm o mesmo comprimento). Isso não é muito :-(
assylias 17/01
@assylias Smart, eu gosto. Obrigado! E embora 1 byte não seja muito, ainda é 1 byte. O Codegolf sempre tenta torná-lo o mais curto possível, para que cada byte conte. :)
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
fonte
Bem-vindo ao PPCG! Não conheço o VBA, mas parece que você pode jogar um pouco de espaço em branco.
FantaC
Eu também realmente não conheço VBA, mas acho que DateStringé um nome de variável arbitrário, então você deve ser capaz de reduzi-lo a um único caractere, certo?
Martin Ender
3
E acho que você perdeu a parte principal das "datas primárias palindrômicas".
Mercator
Haveria algum código para calcular os anos bissextos (o que tem 29 de fevereiro)
RosLuP
Também faltam anos de cinco dígitos e Else não é necessário.
Weijun Zhou
0

Limpo , 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]]

Experimente online!

Furioso
fonte
0

Javascript , 234 229 bytes

Um pouco volumoso, mas publicá-lo para fazer a bola JS rolar. Todas as sugestões são bem-vindas!

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)}}

Ungolfed:

// 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)
            }
}

Como funciona:

A mágica dos lançamentos de dígitos é baseada principalmente em experiências.
Comecei descobrindo qual número subtrair para obter a versão invertida. Eu só me importava com os dois últimos dígitos.
Então, se pegarmos n, encontre kassim n+k=flip(n). Para 10<n<20 kcomeçar em 101 e aumentar em incrementos de 9. No entanto, para n<10, este foi 100. Supus kaumento a cada salto de 10, e depois de um pouco de brincadeira, achei que estava correto.
Então, k=100+9*n+n//10onde // significa divisão inteira.

Assim, chegamos n+k = n+(100+9*n+n//10) = 100+10*n+n//10 = flipped(n).

Não posso provar, nem afirmar que isso funciona para qualquer número, mas produziu resultados corretos para os números usados ​​aqui.

Para o teste de primalidade, credite a resposta de Kevin Cruijssen . Eu tinha uma versão um pouco mais curta, mas não conseguia acertar:

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

Eu pulei no teste do palíndromo, fazendo um loop por meses, dias e um dígito do meio para que eu pudesse criar strings como dDmMxMmDd, onde Dé o primeiro dígito do dia, do segundo, etc.

História

Economizou 5 bytes ao se livrar da parte condicional de q

q=n=>n<10?'0'+n:(''+n).slice(-2) // from
q=n=>(''+(100+n)).slice(-2)      // to
elementbound
fonte
Desculpe por mexer com a contagem de bytes. Escorregou acidentalmente em algumas abas suaves. Deve estar correto agora.
elementbound
Você sempre usa fo resultado de s como parâmetro para q, então recorte o intermediário e escreva f=n=>''+n%10+(n/10|0), e o resultado de q é sempre usado como uma string, para que você possa escrever q=n=>n<10?'0'+n:n.
Neil
0

APL NARS 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

esta impressão o que encontrar em 50 segundos, do que parar a si mesmo (porque senão não consigo parar o programa para copiar e colar o teste, porque não sei como parar o programa sem fechar as janelas do intérprete) test:

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

Julia 0.6 , 109 bytes

O link vai para uma versão mais longa com duas diferenças:

  1. Verifica primos com função escrita à mão, pois o pacote Primes não está disponível no TIO.
  2. Repete um período diferente para não atingir o tempo limite.
[s for s in Dates.format(Date(0,1,1):Date(100000,1,1),"YYYYmmdd") if Primes.isprime(parse(s))&&s==reverse(s)]

Experimente online!

gggg
fonte