Lập trình mê tín


19

Thử thách của bạn vô cùng đơn giản. Đưa ra một năm làm đầu vào, in tất cả các tháng trong năm đó sẽ chứa Thứ Sáu ngày 13 theo lịch Gregorian. Lưu ý rằng mặc dù Lịch Gregorian không được giới thiệu cho đến năm 1582, vì đơn giản, chúng tôi sẽ giả vờ rằng nó đã được sử dụng từ năm 0001 sau Công nguyên.

Quy tắc

  • Chương trình đầy đủ hoặc chức năng được cho phép.

  • Bạn có thể lấy đầu vào làm đối số hàm, từ STDIN hoặc làm đối số dòng lệnh.

  • Bạn không được phép sử dụng bất kỳ nội dung ngày và giờ nào.

  • Bạn có thể chắc chắn cho rằng đầu vào sẽ là một năm hợp lệ. Nếu đầu vào nhỏ hơn 1, không phải là số nguyên hợp lệ hoặc lớn hơn loại số gốc ngôn ngữ của bạn, bạn không phải xử lý việc này và bạn có hành vi không xác định.

  • Đầu ra có thể là số, bằng tiếng Anh hoặc ở bất kỳ định dạng nào có thể đọc được của con người, miễn là bạn chỉ định tiêu chuẩn.

  • Hãy chắc chắn rằng bạn chiếm tài khoản cho năm nhuận. Và hãy nhớ rằng, năm nhuận không xảy ra cứ sau 4 năm!

Lời khuyên

Vì có rất nhiều cách khác nhau để giải quyết vấn đề này, tôi không muốn nói cho bạn biết cách thực hiện. Tuy nhiên, có thể khó hiểu khi bắt đầu từ đâu, vì vậy đây là một vài cách đáng tin cậy khác nhau để xác định ngày trong tuần kể từ ngày.

IO mẫu

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

Như thường lệ, đây là môn đánh gôn, do đó, sơ hở tiêu chuẩn được áp dụng và câu trả lời ngắn nhất sẽ thắng.


5
Khi chạy vào thứ Sáu ngày 13, nó sẽ đảo ngược và xuất ra các tháng không có thứ Sáu ngày 13. (Tham khảo Thứ Sáu Freaky cho chiến thắng)
Addison Crump


Là ví dụ này đúng : 0001 --> 5? Theo trang này (và mã của tôi) nó phải là tháng Tư và tháng Bảy.
faubi

@faubiguy xấu của tôi, bạn nói đúng. Đó là trên Lịch Julian. Hãy để tôi sửa nó.
DJMcMayhem

Bởi "bạn không được phép sử dụng bất kỳ nội dung ngày hoặc giờ nào", có phải tôi cũng không thể chuyển đổi thành thời gian unix không?
busukxuan

Câu trả lời:


1

Bình, 73 byte

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

Hãy thử trực tuyến!

Sử dụng Thuật toán Gauss, như trong câu trả lời Python của tôi. ~ 55 byte mã là để tính toán ngày trong tuần, vì vậy việc chọn một thuật toán tốt hơn có thể làm giảm điều này rất nhiều, tôi cho rằng ... nhưng này, ít nhất là nó đang hoạt động ngay bây giờ! :)


2

Python 2, 157 144 136 byte

Giải pháp của tôi sử dụng Thuật toán Gauss. Đầu vào là năm như Integer. Đầu ra là danh sách các tháng có thứ sáu ngày 13 dưới dạng số (1-12). Có lẽ có thể chơi gôn nhiều hơn, nhưng đã muộn rồi ... Gonna chỉnh sửa cái này vào ngày mai và không làm nó giảm thêm một chút nữa. Đề xuất luôn được chào đón trong khi chờ đợi!

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]

chỉnh sửa: Giảm xuống 144 bằng cách thay thế vòng lặp for bằng cách hoàn thành danh sách và thực hiện một số điều chỉnh nhỏ khác.

edit2: Golfed nó xuống 136 với những gợi ý từ Morgan Thrapp và sửa lỗi ông phát hiện ra. Cảm ơn rất nhiều! :)


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

Điều này sử dụng một phiên bản sửa đổi của công thức cho ngày Julian để tính ngày trong tuần của ngày 13 tháng 3, sau đó sử dụng số ngày trong tuần mỗi tháng được bù từ tháng 1 để tìm ngày trong tuần cho phần còn lại của tháng, bắt đầu với 2 tháng cuối năm trước bắt đầu từ tháng 3, sau đó là 10 tháng đầu năm hiện tại (để tránh tính năm nhuận hai lần).


1

C - 164 153 112 byte

Tôi tìm thấy một giải pháp nhỏ đẹp bằng cách sử dụng một phiên bản sửa đổi mạnh mẽ của phương pháp Schwerdtfeger. Nó mã hóa bảng cần thiết trong một số nguyên bằng cách sử dụng cơ sở 7, được sửa đổi để phù hợp với một từ 32 bit đã ký. Nó xuất ra tháng dưới dạng ký tự ASCII, với tháng 1 được mã hóa vào 1tháng 2 2, v.v., với tháng 10 được mã hóa thành :, tháng 11 được mã hóa ;và tháng 12 được mã hóa thành <.

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

Ở đây nó hơi vô căn cứ:

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ôi chắc chắn có một số cách để làm cho nó nhỏ hơn nữa, nhưng tôi nghĩ rằng thuật toán, hoặc một biến thể nhỏ của nó, gần như lý tưởng để tìm ra những tháng thứ Sáu ngày 13 xảy ra (liên quan đến kích thước mã). Ghi chú:

  1. Nếu một từ 64 bit có thể được sử dụng, có thể loại bỏ một bổ sung gây phiền nhiễu ( +5).
  2. Biến mkhông thực sự cần thiết, vì tháng chúng ta đang xem là có thể khấu trừ t.

Tôi để lại câu trả lời cũ hơn của mình bên dưới, vì nó sử dụng một phương pháp hoàn toàn khác không thấy trong các câu trả lời khác ở đây.


Điều này dựa trên một giải pháp cho một vấn đề liên quan ( /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);}

Về cơ bản, nó mô phỏng lịch Gregorian, tiến lên từng ngày một, in tháng khi đó là thứ Sáu và ngày 13. Đây là một dạng dễ đọc hơn một chút:

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

ecc ấn tượng nhưng không tìm thấy trong 123456789 -> tháng 1, tháng 10 tháng 10
RosLuP

Hmm, nó làm cho tôi. Có thể cho tôi một số lý do phụ thuộc nền tảng? Nó hoạt động với tôi trên Macbook Pro khá hiện đại khi biên dịch với Clang. Lưu ý rằng nó xuất ra 1:cho 123456789, nơi :biểu thị tháng mười. Tôi đã làm rõ các mã hóa ở trên.
Dành cho

Có 1: ở đây cũng vậy; Tôi không hiểu ':' là cho tháng 10 ...
RosLuP

0

Excel, 137 byte

Mất năm đầu vào A1. Đầu ra là danh sách không tách rời của Hexidecimal. (Tháng 1 = 0, tháng 12 = B)

Sử dụng thuật toán của Gauss cho tháng 1 và tháng 8.

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

Câu trả lời này hiện đang sử dụng các nội dung ngày và thời gian, được tuyên bố rõ ràng là trái với các quy tắc trong thử thách.
Dành cho

@Fors, Cảm ơn bạn đã chỉ ra rằng. Cập nhật.
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;}

đầu vào từ đầu ra stdin trong thiết bị xuất chuẩn hãy thử http://ideone.com/XtuhGj [chức năng gỡ lỗi là 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");
        }

}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.