Programowanie przesądne

19

Twoje wyzwanie jest niezwykle proste. Biorąc pod uwagę rok, wydrukuj wszystkie miesiące w tym roku, które będą zawierać piątek 13 zgodnie z kalendarzem gregoriańskim. Zauważ, że chociaż kalendarz gregoriański został wprowadzony dopiero w 1582 r., Dla uproszczenia będziemy udawać, że jest używany od 0001 rne.

Zasady

  • Pełne programy lub funkcje są dozwolone.

  • Dane wejściowe można przyjmować jako argumenty funkcji, ze STDIN lub jako argumenty wiersza poleceń.

  • Nie możesz używać żadnych wbudowanych dat i godzin.

  • Możesz bezpiecznie założyć, że wprowadzony rok będzie prawidłowy. Jeśli wartość wejściowa jest mniejsza niż 1, nie jest prawidłową liczbą całkowitą lub jest większa niż rodzimy typ liczbowy w Twoim języku, nie musisz sobie z tym poradzić i otrzymasz niezdefiniowane zachowanie.

  • Dane wyjściowe mogą być liczbami, w języku angielskim lub w innym formacie czytelnym dla człowieka, o ile podany zostanie standard.

  • Upewnij się, że bierzesz pod uwagę lata przestępne. I pamiętaj, że lata przestępne nie zdarzają się co 4 lata!

Porady

Ponieważ istnieje tak wiele różnych sposobów, aby to zrobić, nie chcę ci mówić, jak to zrobić. Jednak może to być mylące, od czego zacząć, więc oto kilka różnych niezawodnych sposobów określania dnia tygodnia od daty.

Próbka IO

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

Jak zwykle jest to gra w golfa, więc obowiązują standardowe luki i wygrywa najkrótsza odpowiedź.

DJMcMayhem
źródło
5
Uruchomiony w piątek 13-go powinien odwrócić i wygenerować miesiące, które nie mają piątku 13-go. (Zakręcony piątek odniesienia do zwycięstwa)
Addison Crump
1
Powiązane
Cyfrowa trauma
Czy ten przykład jest właściwy 0001 --> 5:? Według tej strony (i mojego kodu) powinien to być kwiecień i lipiec.
faubi
@faubiguy my bad, masz rację. To było w kalendarzu juliańskim. Pozwól mi to naprawić.
DJMcMayhem
Czy „nie wolno mi używać żadnych wbudowanych dat ani godzin”, czy nie mogę też konwertować na czas uniksowy?
busukxuan

Odpowiedzi:

1

Pyth, 73 bajtów

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

Wypróbuj online!

Używając algorytmu Gaussa, jak w mojej odpowiedzi w Pythonie. ~ 55 bajtów kodu służy do obliczeń w dni powszednie, więc wybranie lepszego algorytmu mogłoby to znacznie obniżyć, ale ... hej, przynajmniej działa teraz! :)

Denker
źródło
2

Python 2, 157 144 136 bajtów

Moje rozwiązanie wykorzystuje algorytm Gaussa. Dane wejściowe to rok jako liczba całkowita. Wyjście to lista miesięcy z piątkiem 13 jako liczby (1-12). Prawdopodobnie trochę więcej gry w golfa, ale robi się późno ... Zmienię to jutro i jeszcze bardziej ją obniżę. Tymczasem sugestie są zawsze mile widziane!

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]

edycja: zredukowałem ją do 144, zastępując pętlę for spójnością listy i wprowadzając inne niewielkie poprawki.

edit2: Grał w golfa do 136 dzięki sugestiom Morgana Thrappa i naprawił wykryty błąd. Wielkie dzięki! :)

Denker
źródło
1

Perl - 141 107 103 bajtów

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

Wykorzystuje zmodyfikowaną wersję formuły dla dnia juliańskiego, aby obliczyć dzień tygodnia 13 marca, a następnie wykorzystuje liczbę dni tygodnia, w których każdy miesiąc jest przesunięty w stosunku do stycznia, aby znaleźć dzień tygodnia dla reszty miesięcy, zaczynając od ostatnich 2 miesięcy poprzedniego roku, rozpoczynając w marcu, a następnie pierwszych 10 miesięcy bieżącego roku (aby uniknąć dwukrotnego liczenia lat przestępnych).

faubi
źródło
1

C - 164 153 112 bajtów

Znalazłem fajne małe rozwiązanie, używając mocno zmodyfikowanej wersji metody Schwerdtfeger. Koduje niezbędną tabelę w liczbie całkowitej za pomocą podstawy 7, zmodyfikowanej w celu dopasowania do 32-bitowego słowa ze znakiem. Wyprowadza miesiąc jako znak ASCII, z kodowaniem stycznia jako 1, lutym 2i tak dalej, z kodowaniem października jako :, kodowaniem listopada ;i kodowaniem grudnia <.

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

Tutaj jest nieco nie golfa:

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

Jestem pewien, że istnieje kilka sposobów, aby uczynić go jeszcze mniejszym, ale myślę, że algorytm lub jego niewielka odmiana jest prawie idealny do znalezienia miesięcy, w których występuje piątek trzynasty (w odniesieniu do rozmiaru kodu). Uwagi:

  1. Gdyby można było użyć słowa 64-bitowego, można byłoby pozbyć się irytującego dodatku ( +5).
  2. Zmienna mnie jest tak naprawdę konieczna, ponieważ miesiąc, na który patrzymy, można wydedukować t.

Zostawiam moją starszą odpowiedź poniżej, ponieważ używa ona zupełnie innej metody, której nie widziano w innych odpowiedziach tutaj.


Jest to oparte na rozwiązaniu powiązanego problemu ( /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);}

Zasadniczo symuluje kalendarz gregoriański, przesuwając się jeden dzień na raz, drukując miesiąc, w którym jest piątek i trzynasty. Tutaj jest w nieco bardziej czytelnej formie:

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);
}
Fors
źródło
imponujący ecc, ale nie można go znaleźć w 123456789 -> styczeń, październik październik
RosLuP
Hmm, robi to dla mnie. Czy może być jakiś powód zależny od platformy? Działa dla mnie na dość nowoczesnym Macbooku Pro podczas kompilacji z Clangiem. Zauważ, że wyświetla dane wyjściowe 1:dla 123456789, gdzie :oznacza październik. Wyjaśniłem kodowanie powyżej.
Fors
Tak 1: tutaj też; Nie zrozumiałem „:” było na październik ...
RosLuP
0

Excel, 137 bajtów

Zajmuje rok wejścia w A1. Dane wyjściowe to niepodzielona lista szesnastkowa. (Styczeń = 0, grudzień = B)

Używa algorytmu Gaussa dla stycznia i sierpnia.

=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)
Wernisch
źródło
Ta odpowiedź korzysta obecnie z wbudowanej daty i godziny, co jest wyraźnie stwierdzone wbrew regułom wyzwania.
Fors
@Dziękujemy za zwrócenie na to uwagi. Zaktualizowano
Wernisch
0

C, 276 219 bajtów

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

wejście z wyjścia stdin w stdout spróbuj http://ideone.com/XtuhGj [funkcja debugowania to 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");
        }

}
RosLuP
źródło