Суеверне програмування


19

Ваше завдання надзвичайно просте. З огляду на рік, введіть усі місяці цього року, які містять п’ятницю 13-го згідно з григоріанським календарем. Зауважимо, що незважаючи на те, що григоріанський календар не був введений до 1582 року, для простоти ми зробимо вигляд, що він використовується з 0001 року нашої ери.

Правила

  • Повні програми або функції дозволені.

  • Ви можете приймати дані як аргументи функції, з STDIN або як аргументи командного рядка.

  • Вам заборонено використовувати будь-які вбудовані дати та час.

  • Можна сміливо припускати, що вхід буде дійсним роком. Якщо вхід менший за 1, не є дійсним цілим числом або більшим, ніж тип нативного числу ваших мов, вам не доведеться це обробляти, і ви отримуєте не визначену поведінку.

  • Вихідні дані можуть бути цифрами англійською або будь-яким іншим читабельним для людини форматом, якщо ви вказали стандарт.

  • Переконайтеся, що ви обліковуєте високосні роки. І пам’ятайте, високосні роки не трапляються кожні 4 роки!

Поради

Оскільки існує стільки різних способів зробити це, я не хочу розповідати, як це зробити. Однак це може заплутати, з чого почати, тому ось кілька різних надійних способів визначення дня тижня від дати.

Зразок IO

2016 --> May
0001 --> 4, 7
1997 --> Jun
1337 --> 09, 12
123456789 --> January, October

Як завжди, це код-гольф, тому застосовуються стандартні лазівки, і найкоротша відповідь виграє.


5
Коли буде запущено в п’ятницю 13-го, це повинно перевернути і вивести місяці, у яких немає п'ятниці 13-го. (Вигадливі посилання на п’ятницю про перемогу)
Аддісон Крумп


Чи правильно цей приклад 0001 --> 5:? Відповідно до цієї сторінки (і мого коду) це має бути квітень та липень.
faubi

@faubiguy моя погана, ти маєш рацію. Це було в Юліанському календарі. Дозвольте це виправити.
DJMcMayhem

Якщо "вам заборонено використовувати будь-яку вбудовану дату чи час", чи це я також не можу перетворити на час Unix?
busukxuan

Відповіді:


1

Піт, 73 байт

L?>b2QtQfq%+++13+/-*2.6?qT2 12%-T2 12 .2 1*5%yT4*4%yT100*6%yT400 7 5r1 13

Спробуйте в Інтернеті!

Використовуючи алгоритм Гаусса, як у моїй відповіді Python. ~ 55 байт коду призначений для обчислення буднього дня, тому вибір кращого алгоритму міг би знизити це на багато, я думаю ... але ей, принаймні, його працює зараз! :)


2

Пітон 2, 157 144 136 байт

У моєму рішенні використовується алгоритм Гаусса. Вхід - це рік як цілий. Вихід - це список місяців з п'ятницею 13 числа як числа (1-12). Напевно, можливе ще кілька гольфів, але його запізнюється ... Завтра відредагуйте цю, а ще трохи опустіть. Пропозиції тим часом завжди вітаються!

def f(i):y=lambda m:(i-1,i)[m>2];print[m for m in range(1,13)if(13+int(2.6*((m-2)%12,12)[m==2]-.2)+y(m)%4*5+y(m)%100*4+y(m)%400*6)%7==5]

редагувати: зменшив його до 144, замінивши цикл for-циклу розумінням списку та внісши деякі інші невеликі коригування.

edit2: Програв його до 136 із пропозиціями Морган Трапп і виправив виявлену помилку. Дуже дякую! :)


1

Perl - 141 107 103 байт

$y=<>-1;map{$y++if++$i==3;print"$i "if($y+int($y/4)-int($y/100)+int($y/400))%7==$_}'634163152042'=~/./g

При цьому використовується модифікована версія формули для Джуліанського дня для обчислення дня тижня 13 березня, потім використовується кількість днів тижня, щомісяця зміщується з січня, щоб знайти день тижня для решти місяців, починаючи з останніх 2 місяців попереднього року, починаючи з березня, а потім перших 10 місяців поточного року (щоб уникнути обчислення високосних років удвічі).


1

С - 164 153 112 байт

Я знайшов гарне маленьке рішення, використовуючи сильно модифіковану версію методу Швердтфегера. Він кодує необхідну таблицю в цілому цілому, використовуючи базу 7, модифіковану для розміщення підписаного 32-бітного слова. Він виводить місяць у вигляді символу ASCII, січень кодується як 1, лютий як 2і так далі, жовтень кодується як :, листопад кодується як, ;а грудень кодується як <.

t=1496603958,m;main(y){for(scanf("%d",&y),y--;(y%100+y%100/4+y/100%4*5+t+5)%7||putchar(m+49),t;t/=7)2-++m||y++;}

Ось це трохи невольф:

t=1496603958,m;
main(y){
  for(
    scanf("%d",&y),y--;
    (y%100+y%100/4+y/100%4*5+t+5)%7||putchar(m+49),t;
    t/=7
  )
    2-++m||y++;
}

Я впевнений, що існує кілька способів зробити його ще меншим, але я думаю, що алгоритм, або його незначна зміна, майже ідеальний для пошуку місяців, де відбувається п'ятниця 13-го (щодо розміру коду). Примітки:

  1. Якби 64-бітове слово могло бути використане, можна було б позбутися від дратівливого додавання ( +5).
  2. Ця зміна mнасправді не потрібна, оскільки місяць, який ми дивимось, можна вивести t.

Я залишаю свою стару відповідь нижче, бачачи, як вона використовує зовсім інший метод, який не можна побачити в інших відповідях тут.


Це засновано на вирішенні пов'язаної проблеми ( /codegolf//a/22531/7682 ).

Y,M,D,d;main(y){for(scanf("%d",&y);Y<=y;++D>28+(M^2?M+(M>7)&1^2:!(Y&3)&&(Y%25||!(Y&15)))&&(D=1,M=M%12+1)<2&&Y++)(d=++d%7)^1||D^13||y^Y||printf("%d,",M);}

Він в основному імітує григоріанський календар, просуваючись один за одним, друкуючи місяць, коли це п’ятниця та 13-й. Ось він у трохи більш читабельному вигляді:

Y,M,D,d;
main(y){
  for(
    scanf("%d",&y);
    Y<=y;
    ++D>28+(
      M^2
        ?M+(M>7)&1^2
        :!(Y&3)&&(Y%25||!(Y&15))
    )&&(
      D=1,
      M=M%12+1
    )<2&&Y++
  )
    (d=++d%7)^1||D^13||y^Y||
      printf("%d,",M);
}

вражаючий екк, але не знайдеться у 123456789 -> січень, жовтень, жовтень
RosLuP

Хм, це для мене. Може, мені якась залежна від платформи причина? Він працює для мене на досить сучасному Macbook Pro при компіляції з Clang. Зауважте, що він виводить 1:для 123456789, де :позначається жовтень. Я уточнив кодування вище.
Форс

Так 1: і тут; Я не зрозумів ':' було за жовтень ...
RosLuP

0

Excel, 137 байт

Приймає рік введення в А1. Вихід є не відокремленим списком Hexedcimal. (Січень = 0, грудень = B)

Використовує алгоритм Гаусса за січень та серпень.

=CHOOSE(MOD(6+5*MOD(A1-1,4)+4*MOD(A1-1,400),7)+1,"","",1,"","",0,"")&CHOOSE(MOD(5*MOD(A1-1,4)+4*MOD(A1-1,400),7)+1,9,35,"8B",5,"2A",7,4)

Ця відповідь наразі використовує вбудовані дати та час, що чітко зазначено проти правил у виклику.
Форс

@Fors, Дякую, що вказали на це. Оновлено.
Верніш

0

C, 276 219 байт

#define R return
#define L(i) for(;i-->0;) 
u(y,m){R m-1?30+((2773>>m)&1):28+(y%4==0&&y%100||y%400==0);}s(y,m,g){g+=4;L(m)g+=u(y,m),g%=7;L(y)g+=1+u(y,1),g%=7;R g;}z(y,m,r){m=12;L(m)s(y,m,13)-4||(r|=1<<(m+1));R r;}

вхід з виводу stdin у stdout спробуйте на http://ideone.com/XtuhGj [функція налагодження z]

w(y,m,r){m=12;L(m)s(y,m,u(y,m))||(r|=1<<(m+1));R r;}
/*    
// ritorna il numero dei giorni di anno=y mese=m con mese in 0..11
// m==1 significa febbraio   y%4?0:y%100?1:!(y%400) non funziona
u(y,m){R m-1?30+((2773>>m)&1):28+(y%4==0&&y%100||y%400==0);}

// argomenti anno:y[0..0xFFFFFFF]  mese:m[0..11]  giorno:g[1..u(y,m)]
// ritorna il numero del giorno[0..6]
s(y,m,g)
{g+=4; // correzione per il giorno di partenza anno mese giorno = 0,1,1
 L(m)g+=  u(y,m),g%=7; // m:0..m-1  somma mod 7 i giorni del mese dell'anno y
 L(y)g+=1+u(y,1),g%=7; // y:0..y-1  somma mod 7 gli anni da 0..y-1
                       // g+=1+u(y,1) poiche' (365-28)%7=1 e 1 e' febbraio
 R g;
}

// argomenti anno:y[0..0xFFFFFFF], m=0 r=0 
// calcola tutti gli ultimi giorni del mese dell'anno y che cadono di lunedi'
// e mette tali mesi come bit, dal bit 1 al bit 12 [il bit 0 sempre 0] in r
w(y,m,r){m=12;L(m)s(y,m,u(y,m))||(r|=1<<(m+1));R r;}

// argomenti anno:y[0..0xFFFFFFF], m=0 r=0 
//ritorna in r il numero dei mesi che ha giorno 13 di venerdi[==4]
// e mette tali mesi come bit, dal bit 1 al bit 12 [il bit 0 sempre 0] in r
z(y,m,r){m=12;L(m)s(y,m,13)-4||(r|=1<<(m+1));R r;}
*/

#define P printf
#define W while 
#define M main 
#define F for
#define U unsigned
#define N int
#define B break
#define I if
#define J(a,b)  if(a)goto b
#define G goto
#define P printf
#define D double
#define C unsigned char
#define A getchar()
#define O putchar
#define Y malloc
#define Z free
#define S sizeof
#define T struct
#define E else
#define Q static
#define X continue
M()
{N y,m,g,r,arr[]={1,297,1776,2000,2016,3385}, arr1[]={2016,1,1997,1337,123456789};
 C*mese[]={"gen","feb","mar","apr","mag","giu","lug","ago","set","ott","nov","dic"};
 C*giorno[]={"Lun","Mar","Mer","Gio","Ven","Sab","Dom"};
 P("Inserisci Anno mese giorno>");r=scanf("%d %d %d", &y, &m, &g);
 P("Inseriti> %d %d %d r=%d\n", y, m, g, r);
 I(r!=3||m>12||m<=0||g>u(y,m-1))R 0;
 r=s(y,m-1,g);// 12-> 11 -> 0..10
 P("Risultato=%d giorno=%s\n", r, giorno[r]);
 r=w(y,0,0);P(" r=%d ", r);P("\n");
 F(m=0;m<6;++m)
        {P("N anno=%d -->",arr[m]); 
         r=w(arr[m],0,0); // ritorna in r i mesi tramite i suoi bit...
         F(y=1;y<13;++y) I(r&(1<<y))P("%s ",mese[y-1]);
         P("\n");
        }
 F(m=0;m<4;++m)
        {P("N anno=%d -->",arr1[m]); 
         r=z(arr1[m],0,0); // ritorna in r i mesi tramite i suoi bit...
         F(y=1;y<13;++y) I(r&(1<<y))P("%s ",mese[y-1]);
         P("\n");
        }

}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.