Перечислите все палиндромные простые даты между 0000-01-01 и 99999-12-31

11

Вы знаете, что такое палиндром , прайм и свидание .

Ваша задача - перечислить все даты за 100 тысяч лет, которые соответствуют всем трем характеристикам.

Nevermind ничего , кроме номера, используйте следующие форматы: ГГГГММДД и YYYYYMMDD .

Даты между 0000-01-01 и 9999-12-31 должны быть напечатаны как 8-значные палиндромы (если есть?), А даты между 10000-01-01 и 99999-12-31 должны быть напечатаны как 9-значные палиндромы.

Не обязательно перечислять даты в хронологическом порядке.

Пример части правильного вывода.

Первые три 9-значные простые палиндромные даты:

...
100111001
100131001
100161001
...

правила

Применяются стандартные лазейки .

Plarsen
источник
Правило: 02-29существует только для лет, которые делятся на 400 или (делятся на 4 и не делятся на 100).
user202729
@ user202729 Да, я так думаю, например, я не думаю, что 2017-02-29, 2018-02-29 и 1900-02-29 можно считать "датами".
Эрик Outgolfer
4
Нет никаких 8-значных палиндромных дат, которые также являются простыми числами. Вот список, который мы должны вернуть / напечатать (всего 197) . Это правильно @Plarsen?
Кевин Круйссен
1
Должны ли мы позволить 30 февраля? > Timeanddate.com/date/february-30.html
jrtapsell
3
Год 0000 никогда не случался
Джонатан Аллан

Ответы:

5

Ruby , 144 141 байт (134 + 7 для -rprimeфлага)

Сохранено 3 байта благодаря 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)}}}

Попробуйте онлайн!

Алгоритм:

  • генерировать все возможные комбинации MMDD от «0101» до «1231»
  • сгенерируйте все годы для этой даты, которые приведут к палиндрому, путем обращения строки MMDD и добавления в середине, в свою очередь, всех символов в диапазоне (0..9)
  • проверить, что является действительной датой путем создания Timeэкземпляра с учетом y, m, dзначения. Если полученный объект времени имеет #dayзначение, равное d, то это была действительная дата. В противном случае это сместит дату (например, Time.new 2018,2,30возврат 2018-03-02).
  • проверьте, является ли действительная дата палиндрома также простым числом, и отобразите ее, если она есть.

Внутренний цикл изначально был функцией, которая вызывалась для каждого элемента в (?0..?9)диапазоне, а также для пустой строки.

Так как пустая строка не дала никаких результатов (нет действительных 8-значных простых палиндромов), я решил удалить ее и выполнить рефакторинг для этой версии.

Кристиан Лупаску
источник
Я думаю , что вы можете сэкономить несколько байт, удалив tпеременную: TIO
benj2240
@ benj2240 Это верно! Благодаря!
Кристиан Лупаску
4

Python 2 , 116 107 128 122 119 байт

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

Вторая половина 4 - й строки вдохновлена mxdsp «s ответа здесь на другой вопрос гольфа .

объяснение

Функция g()принимает аргумент только для инициализации nпеременной, используя ее значение по умолчанию. Начальное значение - это нечетное число, которое как можно короче и максимально возможно, но все же меньше первого действительного ответа 100111001.

Цикл, пока не nдостигнет конца диапазона дат 10 9 . Инкремент nна 2. mявляется месяцем даты n.

Если nдействительная дата, палиндром и штрих, выведите ее:

  • Дата:
    • 0 < m < 13проверяет, что mявляется действительным месяцем.
    • n % 100 < 31 + (m+m/8)%2проверяет, что nдень месяца действителен. (m+m/8)%2добавляет 1за все месяцы с 31 дня. Кредит на это идет к ответу ArmanX . На 29-30 февраля нет простых чисел.
  • Палиндром: `n`[::-1] == `n`. Обратные черты преобразуются n. [::-1]переворачивает строку
  • Prime: 2**n % n == 2это тест на примитивность Ферма . Этот тест только вероятностный. Есть также не простые числа, которые соответствуют. Но не в диапазоне чисел, на которые мы смотрим.
Меркатора
источник
Хороший, использующий тест первичности Ферма!
августа
3

APL (Dyalog Unicode) , 155 байт

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

Попробуйте онлайн!

Это Tradfn ( трады itional х unctio п ) , который принимает один аргумент arg = yyyymmddили arg = yyyyymmdd. Использование есть f arg.

Это не будет ничего выводить, когда аргумент начинается с, 10000101потому что он не находит простую дату палиндрома за 60 секунд.

Вот менее удачный подход, который будет выводить пример вывода OP

100111001
100131001
100161001

( Попробуйте онлайн! )

Обратите внимание, что оба кода одинаковы до тех пор, пока не будут рекурсивно вызваны функции для следующей даты. В то время как версия для игры в гольф просто называет это так f arg+1, код с меньшим количеством игроков скачет изо дня 31в день 01и из месяца 12в месяц 01, что значительно ускоряет его.

Как это работает:

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.
Ж. Салле
источник
2

Python 3, 163 байта

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)

Решение довольно длинное (и, вероятно, может быть улучшено), но не использует никаких встроенных функций для проверки простого числа / даты / палиндрома. Несколько неутешительная версия для ясности:

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)

Действительные даты генерируются путем выбора месяца и дня. Как отмечалось ранее, необходимо учитывать только размер 9. Также обратите внимание, что високосные годы не учитываются. Это не требуется из-за счастливого совпадения, что простые числа палиндрома длины 9, заканчивающиеся на 0229, просто не существуют (другие аномалии даты, такие как 30 февраля 1712 года, могут быть отклонены по той же причине).

Затем выбирается средняя цифра, и выполняется первичный тест. Из-за того, что основной тест должен был быть как можно короче, он очень наивен и, следовательно, крайне медленен. Использование внешней библиотеки может решить эту проблему (и сэкономить несколько байтов), но, как уже упоминалось, я не хотел использовать какую-либо.

Защита
источник
Вы должны заставить свой код выглядеть точно так же, как и при подсчете байтов (в данном случае путем сокращения отступа). Кроме того, замечательно, что вы включили версию без гольфа, но обычно версия с гольфом указана первой
wnnmaw
@wnnmaw Единственная разница между версией, которую я рассчитывал на версию, представленную в ответе, состоит в том, что я использовал табуляции вместо пробелов, которые здесь используются. Как я знаю, вкладки автоматически преобразуются, поэтому я не вижу способа это исправить.
Def
@Def IIRC Python также позволяет использовать пробелы в качестве отступов, чтобы и в вашем ответе он выглядел одинаково. Поправьте меня, если я ошибаюсь в первой части.
элемент
@elementbound Действительно, спасибо за предложение.
Def
2

WolframLanguage (Mathematica) 187 байт

Там может быть некоторое уменьшение в размерах, которые будут найдены. Объяснение, чтобы следовать ...

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]&

Контрольные примеры

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

Объяснение кода

DayRange[d@#,d@#2]возвращает все даты между {10011, 10, 1}и {10017, 1, 1}. В этом случае возвращается приблизительно 5 лет, 4 месяца дат (точно 1920 дат). Високосные годы учитываются.

Даты возвращаются в стандартном формате Wolfram. Например, первая дата будет выглядеть как DateObject[List[1,1,1],"Day","Gregorian",-5.] `

#[[1]] & /@удалит часть даты, в каждой дате, которая касается нас. В этом примере DateObject[List[1,3,7],"Day","Gregorian",-5.]возвращает сокращенную дату {1,3,7}.

t/@p[#3,2]}или ToString/@Padleft[#3,2]дополняет третий элемент, а именно 7, стоящий «на 7-й день месяца» как "07". Аналогичное дополнение предоставляется для однозначного символа месяца марта, а именно, 3возвращается как "03".

p[#, If[Length@# < 5, 4, 5]]дополняет год нулями до длины строки из 4 или 5 цифр. В этом случае январь, а именно 1, возвращается как «00001».

"" <>...присоединяется к струнам. В этом случае он возвращается "000010307".

Cases[...x_ /; PalindromeQ@x && PrimeQ@ToExpression@x] возвращает те случаи, среди дат 1920 года, которые являются палиндромами и простыми числами.

DavidC
источник
2

Javascript , 187 177

Допущения: не совпадают 4-значные годы; нет подходящих дней в феврале между 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)}}

Это работает так:

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!

История:

  • 187–177: нет простых дат палиндрома, которые выпадают на 29 или 30 февраля, поэтому мы можем притвориться, что февраль имеет 30 дней и сохранить 10 символов.

Заметки:

В ходе тестирования я обнаружил, что нет действительных совпадений, которые имеют 4-значные годы или выпадают на 29 или 30 февраля. К сожалению, ради кода, ровно пять (недействительных) результатов выпадают на 31-е число различных месяцев. это только 31 день.

ArmanX
источник
2

Java 10, 329 327 320 318 312 308 307 264 байта

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 байт благодаря @assylias .

Объяснение:

Попробуйте сделать это онлайн (обратите внимание: часть первичной проверки была заменена на более эффективный метод разделения, хотя даже после этого он истекает через 60 секунд, выводя только первые ~ 115 палиндромных простых чисел).
Pastebin из всех 197 выходов из местного запуска.

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
Кевин Круйссен
источник
1
if(t.equals(new StringBuffer(t).reverse()+"")-> if(t.contains(new StringBuffer(t).reverse())сохранить 1 символ (работает, потому что мы знаем, что обе строки имеют одинаковую длину). Это не так много :-(
assylias
@assylias Умный, мне это нравится. Благодаря! И хотя 1 байт не так много, это все равно 1 байт. Codegolf всегда стремится сделать его максимально коротким, поэтому каждый байт считается. :)
Кевин Круйссен
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
источник
Добро пожаловать в PPCG! Я не знаю VBA, но похоже, что вы могли бы поиграть в свободное пространство.
FantaC
Я также на самом деле не знаю VBA, но я думаю, что DateStringэто произвольное имя переменной, так что вы должны быть в состоянии сократить его до одного символа, верно?
Мартин Эндер
3
И я думаю, что вы пропустили главную часть "палиндромных простых дат".
mercator
Будет какой-то код для расчета високосных лет (у него 29 февраля)
RosLuP
Пятизначные годы также отсутствуют, и остальное не нужно.
Вейцзюнь Чжоу
0

Чисто , 262 ... 213 байт

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

Попробуйте онлайн!

Οurous
источник
0

Javascript , 234 229 байт

Немного громоздко, но выкладываю его, чтобы завалить шар JS. Любые предложения приветствуются!

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

Как это работает:

Магия переключения цифр основана в основном на экспериментах.
Я начал с выяснения, из какого числа вычесть, чтобы получить перевернутую версию. Я заботился только о последних двух цифрах.
Так что, если мы возьмем n, найдите kтак n+k=flip(n). Для 10<n<20 kначала с 101 и с увеличением с шагом 9. Однако, для n<10, это было 100. Я предполагал, что kувеличивается для каждого прыжка 10, и после небольшой тряски я понял, что это было правильно.
Итак, k=100+9*n+n//10где // означает целочисленное деление.

Таким образом, мы получаем n+k = n+(100+9*n+n//10) = 100+10*n+n//10 = flipped(n).

Я не могу ни доказать, ни утверждать, что это работает для любого числа, но оно дало правильные результаты для чисел, используемых здесь.

За тест на первичность, ответьте на ответ Кевина Круйссена . У меня была немного более короткая версия, но я не мог понять это правильно:

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

Я пропустил тест на палиндром, выполнив циклы по месяцам, дням и средней цифре, чтобы я мог строить строки dDmMxMmDd, где Dпервая цифра dдня, вторая и т. Д.

история

Сохранено 5 байт за счет избавления от условной части q

q=n=>n<10?'0'+n:(''+n).slice(-2) // from
q=n=>(''+(100+n)).slice(-2)      // to
elementbound
источник
Извините, что возиться с количеством байтов. Заскочил в некоторые софт-вкладки случайно. Должно быть правильно сейчас.
стихийное
Вы когда-либо используете fрезультат только в качестве параметра для q, поэтому вырежьте посредника и напишите f=n=>''+n%10+(n/10|0), а результат q всегда используется как строка, так что вы можете писать q=n=>n<10?'0'+n:n.
Нил
0

APL NARS 626 байт, 313 символов

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

это вывести за 50 секунд, чем остановить самому (потому что иначе я не могу остановить программу для копирования и вставки теста, потому что я не знаю, как остановить программу, не закрывая окна интерпретатора):

  f
100111001
100131001
100161001
101030101
101060101
101141101
101171101
102040201
102070201
103000301
103060301
104000401
104030401
104040401
RosLuP
источник
0

Юлия 0.6 , 109 байт

Ссылка идет на более длинную версию с двумя отличиями:

  1. Проверяет простые числа с помощью рукописной функции, поскольку пакет простых чисел недоступен в TIO.
  2. Итерации по другому диапазону дат, чтобы не превышать время ожидания.
[s for s in Dates.format(Date(0,1,1):Date(100000,1,1),"YYYYmmdd") if Primes.isprime(parse(s))&&s==reverse(s)]

Попробуйте онлайн!

GGGG
источник