Abergläubische Programmierung


19

Ihre Herausforderung ist denkbar einfach. Geben Sie bei Eingabe eines Jahres alle Monate in diesem Jahr aus, die einen Freitag, den 13., gemäß dem gregorianischen Kalender enthalten. Obwohl der Gregorianische Kalender erst 1582 eingeführt wurde, werden wir der Einfachheit halber so tun, als wäre er seit 0001 n. Chr. In Gebrauch.

Regeln

  • Vollständige Programme oder Funktionen sind zulässig.

  • Sie können Eingaben als Funktionsargumente, von STDIN oder als Befehlszeilenargumente übernehmen.

  • Sie dürfen keine eingebauten Datums- und Zeitangaben verwenden.

  • Sie können davon ausgehen, dass die Eingabe ein gültiges Jahr ist. Wenn die Eingabe kleiner als 1, keine gültige Ganzzahl oder größer als der Typ der systemeigenen Zahl Ihrer Sprache ist, müssen Sie dies nicht verarbeiten, und Sie erhalten ein undefiniertes Verhalten.

  • Die Ausgabe kann in Englisch oder in einem anderen für Menschen lesbaren Format erfolgen, sofern Sie den Standard angeben.

  • Stellen Sie sicher, dass Sie Schaltjahre berücksichtigen. Und denken Sie daran, Schaltjahre kommen nicht alle 4 Jahre vor!

Tipps

Da es so viele verschiedene Möglichkeiten gibt, möchte ich Ihnen nicht sagen, wie es geht. Es kann jedoch verwirrend sein, wo Sie anfangen sollen. Hier finden Sie einige zuverlässige Methoden, um den Wochentag anhand eines Datums zu bestimmen.

Beispiel IO

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

Wie üblich ist dies Codegolf, daher gelten Standardlücken, und die kürzeste Antwort gewinnt.


5
Bei Ausführung am Freitag, dem 13., sollten Monate, die keinen Freitag, den 13. haben, umgekehrt und ausgegeben werden. (Freaky Friday Referenzen für den Sieg)
Addison Crump


Ist dieses Beispiel richtig 0001 --> 5:? Laut dieser Seite (und meinem Code) sollte es April und Juli sein.
Faubi

@faubiguy my bad, du hast recht. Das stand im Julianischen Kalender. Lassen Sie mich das beheben.
DJMcMayhem

Wenn "Sie keine eingebauten Datums- oder Zeitangaben verwenden dürfen", kann ich dann auch nicht auf Unix-Zeit umstellen?
Busukxuan

Antworten:


1

Pyth, 73 Bytes

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

Probieren Sie es online!

Mit dem Gauß-Algorithmus, wie in meiner Python-Antwort. ~ 55 Bytes des Codes sind für die Wochentagsberechnung bestimmt, also könnte die Wahl eines besseren Algorithmus dies um ein Vielfaches verringern ... aber hey, zumindest funktioniert es jetzt! :)


2

Python 2, 157 144 136 Bytes

Meine Lösung verwendet den Gauß-Algorithmus. Eingabe ist das Jahr als Ganzzahl. Ausgabe ist die Liste der Monate mit einem Freitag 13. als Zahlen (1-12). Wahrscheinlich ist noch mehr Golf möglich, aber es wird spät ... Ich werde das morgen bearbeiten und es noch ein bisschen runterholen. Vorschläge sind in der Zwischenzeit immer willkommen!

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]

edit: Es wurde auf 144 reduziert, indem die for-Schleife durch ein Listenverständnis ersetzt und einige andere kleine Anpassungen vorgenommen wurden.

edit2: Golfed es auf 136 mit den Vorschlägen von Morgan Thrapp und behebt den Fehler, den er entdeckt hat. Vielen Dank! :)


1

Perl - 141 107 103 Bytes

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

Dies verwendet eine modifizierte Version der Formel für die Julianischen Tag verwendet , um den Wochentag des 13. März zu berechnen. Anschließend wird die Anzahl der Wochentage verwendet, die jeder Monat vom Januar abweicht, um den Wochentag für den Rest des Monats zu ermitteln Monate, beginnend mit den letzten 2 Monaten des Vorjahres, beginnend im März, dann den ersten 10 Monaten des laufenden Jahres (um die Schaltjahre nicht zweimal zu berechnen).


1

C - 164 153 112 Bytes

Ich fand eine nette kleine Lösung mit einer stark modifizierten Version von Schwerdtfegers Methode. Die erforderliche Tabelle wird mit der Basis 7 in einer Ganzzahl codiert, die so geändert wird, dass sie in ein vorzeichenbehaftetes 32-Bit-Wort passt. Es gibt den Monat als ASCII-Zeichen aus, wobei der Januar als 1, der Februar als 2und so weiter, der Oktober als :, der November als ;und der Dezember als codiert sind <.

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++;}

Hier ist es leicht ungolfed:

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++;
}

Ich bin mir sicher, dass es ein paar Möglichkeiten gibt, es noch kleiner zu machen, aber ich denke, der Algorithmus oder eine kleine Variation davon ist fast ideal, um die Monate zu finden, in denen Freitag der 13. auftritt (in Bezug auf die Codegröße). Anmerkungen:

  1. Wenn ein 64-Bit-Wort hätte verwendet werden können, wäre es möglich, einen nervigen Zusatz zu beseitigen (+5 ) .
  2. Die Variable mist eigentlich nicht notwendig, da der Monat, auf den wir schauen, ableitbar ist t.

Ich lasse meine ältere Antwort unten, da sie eine völlig andere Methode verwendet, als in anderen Antworten hier.


Dies basiert auf einer Lösung für ein verwandtes Problem ( /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);}

Es simuliert im Grunde den Gregorianischen Kalender, der jeden Tag vorrückt und den Monat druckt, in dem es ein Freitag und der 13. ist. Hier ist es in einer etwas besser lesbaren Form:

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

beeindruckende ecc aber nicht in 123456789 zu finden -> Januar, Oktober Oktober
RosLuP

Hmm, das tut es für mich. Könnte ich einen plattformabhängigen Grund haben? Es funktioniert für mich auf einem ziemlich modernen Macbook Pro, wenn ich mit Clang kompiliere. Beachten Sie, dass es 1:für 123456789, wo :Oktober bezeichnet , ausgibt . Ich habe die obige Kodierung geklärt.
Fors

Ja 1: auch hier; Ich verstand nicht ':' war für Oktober ...
RosLuP

0

Excel, 137 Bytes

Nimmt das Eingabejahr in A1 auf. Die Ausgabe ist eine nicht getrennte Liste von Hexidecimal. (Januar = 0, Dezember = B)

Verwendet den Gauß-Algorithmus für Januar und August.

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

Diese Antwort verwendet derzeit integrierte Datums- und Uhrzeitangaben, die explizit im Gegensatz zu den Regeln in der Challenge angegeben sind.
Fors

@Fors, vielen Dank für den Hinweis. Aktualisiert.
Wernisch

0

C, 276 219 Bytes

#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;}

Eingabe von STDIN-Ausgabe in STDOUT versuchen Sie, http://ideone.com/XtuhGj [die Debug-Funktion ist 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");
        }

}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.