Pemrograman Takhayul

19

Tantangan Anda sangat sederhana. Diberikan satu tahun sebagai input, cetak semua bulan di tahun itu yang akan berisi hari Jumat tanggal 13 menurut kalender Gregorian. Perhatikan bahwa meskipun Kalender Gregorian tidak diperkenalkan sampai 1582, demi kesederhanaan kami akan berpura-pura bahwa Kalender ini telah digunakan sejak 0001 Masehi.

Aturan

  • Program atau fungsi penuh diizinkan.

  • Anda dapat mengambil input sebagai argumen fungsi, dari STDIN, atau sebagai argumen baris perintah.

  • Anda tidak diizinkan menggunakan tanggal dan waktu bawaan.

  • Anda dapat dengan aman berasumsi bahwa input akan menjadi tahun yang valid. Jika input lebih kecil dari 1, bukan bilangan bulat yang valid, atau lebih besar dari jenis nomor asli bahasa Anda, Anda tidak harus menangani ini, dan Anda mendapatkan perilaku yang tidak terdefinisi.

  • Output dapat berupa angka, dalam bahasa Inggris, atau dalam format lain yang dapat dibaca manusia, selama Anda menentukan standar.

  • Pastikan Anda memperhitungkan lompatan-tahun. Dan ingat, tahun kabisat tidak terjadi setiap 4 tahun!

Kiat

Karena ada begitu banyak cara untuk melakukan hal ini, saya tidak ingin memberi tahu Anda cara melakukannya. Namun, mungkin membingungkan dari mana harus memulai, jadi inilah beberapa cara yang dapat diandalkan untuk menentukan hari dalam seminggu dari tanggal.

Contoh IO

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

Seperti biasa, ini adalah kode-golf, sehingga celah standar berlaku, dan jawaban terpendek menang.

DJMcMayhem
sumber
5
Ketika dijalankan pada hari Jumat tanggal 13, itu harus mundur dan menghasilkan bulan yang tidak memiliki hari Jumat tanggal 13. (Referensi Freaky Friday untuk kemenangan)
Addison Crump
1
Terkait
Digital Trauma
Apakah contoh ini benar 0001 --> 5:? Menurut halaman ini (dan kode saya) itu harus April dan Juli.
faubi
@ Fahubiguy, salahku, kau benar. Itu ada di Kalender Julian. Biarkan saya memperbaikinya.
DJMcMayhem
Dengan "Anda tidak diperbolehkan menggunakan tanggal atau waktu bawaan", apakah saya tidak dapat mengonversi ke waktu unix juga?
busukxuan

Jawaban:

1

Pyth, 73 Bytes

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

Cobalah online!

Menggunakan Gauss-Algoritma, seperti pada jawaban Python saya. ~ 55 byte kode adalah untuk perhitungan hari kerja, jadi memilih algoritme yang lebih baik bisa mendapatkan ini dengan banyak kurasa ... tapi hei, setidaknya ini berfungsi sekarang! :)

Denker
sumber
2

Python 2, 157 144 136 Bytes

Solusi saya menggunakan Algoritma Gauss. Input adalah tahun sebagai Integer. Keluaran adalah daftar bulan dengan angka 13 sebagai angka (1-12) Mungkin beberapa golf lagi mungkin, tetapi sudah terlambat ... Akan mengedit yang satu ini besok dan turunkan ini sedikit lagi. Sementara itu, saran selalu diterima!

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]

sunting: Dapatkan hingga 144 dengan mengganti for-loop dengan daftar pemahaman dan membuat beberapa penyesuaian kecil lainnya.

sunting2 : Dorong ke 136 dengan saran dari Morgan Thrapp dan perbaiki bug yang ditemukannya. Terima kasih banyak! :)

Denker
sumber
1

Perl - 141 107 103 byte

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

Ini menggunakan versi modifikasi dari rumus untuk hari Julian untuk menghitung hari minggu 13 Maret, kemudian menggunakan jumlah hari dalam seminggu setiap bulan diimbangi dari Januari untuk menemukan hari dalam seminggu untuk sisa hari bulan, dimulai dengan 2 bulan terakhir tahun sebelumnya yang dimulai pada bulan Maret lalu 10 bulan pertama tahun ini (untuk menghindari penghitungan tahun kabisat dua kali).

faubi
sumber
1

C - 164 153 112 byte

Saya menemukan solusi kecil yang bagus menggunakan metode Schwerdtfeger's versi modifikasi. Ini mengkodekan tabel yang diperlukan dalam integer menggunakan basis 7, dimodifikasi agar sesuai dengan kata 32-bit yang ditandatangani. Ini output bulan sebagai karakter ASCII, dengan Januari dikodekan sebagai 1, Februari 2dan seterusnya, dengan Oktober dikodekan sebagai :, November dikodekan sebagai ;dan Desember dikodekan sebagai <.

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

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

Saya yakin ada beberapa cara untuk membuatnya lebih kecil, tetapi saya pikir algoritme, atau sedikit variasi darinya, hampir ideal untuk menemukan bulan di mana Jumat tanggal 13 terjadi (sehubungan dengan ukuran kode). Catatan:

  1. Jika kata 64-bit bisa digunakan, maka akan mungkin untuk menyingkirkan tambahan yang mengganggu (+5 ).
  2. Variabel mtidak benar-benar diperlukan, karena bulan yang kita lihat dapat dikurangkan darit .

Saya meninggalkan jawaban saya yang lebih tua di bawah ini, karena menggunakan metode yang sama sekali berbeda tidak terlihat dalam jawaban lain di sini.


Ini didasarkan pada solusi untuk masalah terkait ( /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);}

Ini pada dasarnya mensimulasikan kalender Gregorian, memajukan satu hari pada suatu waktu, mencetak bulan ketika itu adalah hari Jumat dan tanggal 13. Ini dia dalam bentuk yang sedikit lebih mudah dibaca:

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);
}
Untuk S
sumber
mengesankan ecc tetapi tidak ditemukan di 123456789 -> Januari, Oktober oktober
RosLuP
Hmm, itu cocok untuk saya. Bisakah saya alasan tergantung platform? Ini bekerja untuk saya pada Macbook Pro yang cukup modern ketika dikompilasi dengan Dentang. Perhatikan bahwa output 1:untuk 123456789, di mana :menunjukkan Oktober. Saya mengklarifikasi penyandian di atas.
Fors
Ya 1: di sini juga; Saya tidak mengerti ':' untuk Oktober ...
RosLuP
0

Excel, 137 byte

Mengambil tahun input dalam A1. Output adalah daftar Hexidecimal yang tidak terpisahkan. (Januari = 0, Desember = B)

Menggunakan Algoritma Gauss untuk Januari dan Agustus.

=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
sumber
Jawaban ini saat ini menggunakan tanggal dan waktu bawaan, yang secara eksplisit dinyatakan bertentangan dengan aturan dalam tantangan.
Fors
@Fors, Terima kasih telah menunjukkannya. Diperbarui.
Wernisch
0

C, 276 219 byte

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

input dari output stdin di stdout coba http://ideone.com/XtuhGj [fungsi debug 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
sumber