128 tahun? Reformasi tahun kabisat hipotetis

23

Tahun matahari adalah 365 hari, 5 jam, 48 menit, 45 detik, dan 138 milidetik, menurut video ini . Dengan kalender Gregorian saat ini, aturan untuk tahun kabisat adalah sebagai berikut:

if      year is divisible by 400, LEAP YEAR
else if year is divisible by 100, COMMON YEAR
else if year is divisible by 4,   LEAP YEAR
else,                             COMMON YEAR

Sayangnya, metode ini dimatikan satu hari setiap 3216 tahun.

Salah satu metode yang mungkin untuk mereformasi kalender adalah aturan berikut:

if      year is divisible by 128, COMMON YEAR
else if year is divisible by 4,   LEAP YEAR
else,                             COMMON YEAR

Ini bermanfaat karena tidak mengharuskan kami mengubah kalender kami lagi selama 625.000 tahun, memberi atau menerima.

Katakanlah seluruh dunia memutuskan bahwa, mulai sekarang, kami menggunakan sistem ini setiap tahun keempat adalah tahun kabisat kecuali setiap tahun ke-128, mengubah kalender kami sebagai berikut:

YEAR    GREGORIAN    128-YEAR
2044    LEAP         LEAP
2048    LEAP         COMMON
2052    LEAP         LEAP
 ...
2096    LEAP         LEAP
2100    COMMON       LEAP
2104    LEAP         LEAP
 ...
2296    LEAP         LEAP
2300    COMMON       LEAP
2304    LEAP         COMMON
2308    LEAP         LEAP

Bagaimana ini akan memengaruhi algoritma hari dalam seminggu?

Tantangan

  • Diberi tanggal dari tahun 2000 hingga tahun 100000, temukan hari dalam seminggu di bawah kalender baru ini.
  • Setiap format input dan output diizinkan selama Anda dengan jelas menentukan format mana yang Anda gunakan.
  • Ini kode golf, jadi cobalah membuat solusi Anda semenyenangkan mungkin!

Uji kasus

"28 February 2048" -> "Friday"
"March 1, 2048"    -> "Sat"
(2100, 2, 29)      -> 0           # 0-indexed with Sunday as 0
"2100-02-29"       -> 7           # 1-indexed with Sunday as 7
"28 Feb. 2176"     -> "Wednesday"
"1-Mar-2176"       -> "Th"
"28/02/100000"     -> "F"         # DD/MM/YYYYYY
"Feb. 29, 100000"  -> 6           # 1-indexed with Sunday as 7
"03/01/100000"     -> 1          # MM/DD/YYYYYY and 1-indexed with Sunday as 1

Saran dan umpan balik tentang tantangan ini disambut baik. Semoga berhasil dan bermain golf dengan baik!

Sherlock9
sumber
Untuk uji kasus # 4, maksud Anda 1-diindeks, bukan? Kalau tidak, harus ada 8 hari dalam minggu itu.
Sebastian
Juga, Anda mengatakan "golf bagus", jadi apakah ini tantangan # kode-golf? Jika demikian, masukkan kriteria kemenangan (mis. Jumlah byte / karakter terendah) dan tambahkan itu sebagai tag.
Sebastian
@Sebastian Anda benar dalam kedua hal. Saya sudah mengedit tantangannya. Terima kasih atas tanggapan Anda
Sherlock9
1
Saat membaca judulnya, saya langsung membaca video Matt Parker. Senang melihatnya tertaut di utas juga: D
PattuX
1
Ambil saja perpustakaan standar sehari-hari dan modifikasi konstanta global yang sesuai, bukan? ;)
Wildcard

Jawaban:

8

C (gcc) , 60 byte

f(m,d,y){y-=m<3;return(y+y/4-y/128+"-bed=pen+mad."[m]+d)%7;}

Cobalah online!

Modifikasi sederhana dari metode Sakamoto . Mengambil input sebagai argumen integer dalam urutan month, day, year, dan menampilkan jumlah hari (0-diindeks pada hari Minggu).

notjagan
sumber
Apa yang dilakukan "-bed=pen+mad."bagian itu?
ericw31415
@ ericw31415 Ini menyumbang panjang setiap bulan dalam hari, dan hanya demi penampilan itu digeser oleh kelipatan 7 bukannya karakter di ordinals (31, 28 ...).
notjagan
Benar, saya lupa yang charmasih mewakili angka, jadi Anda bisa mod 7langsung melakukannya .
ericw31415
6

Bahasa Wolfram (Mathematica) , 57 55 53 byte

DayName@{m=#~Mod~128;6+Mod[(9#-m)/8-6Clip@m,28],##2}&

Cobalah online!

Mengambil tiga input: tahun, bulan, dan hari, dalam urutan itu. Misalnya, jika Anda menyimpan fungsi di atas sebagai fun, maka fun[2048,2,28]memberi tahu Anda hari minggu 28 Februari 2048.

Bagaimana itu bekerja

Rumus m=#~Mod~128;6+Mod[(9#-m)/8-6Clip@m,28]mengubah tahun menjadi tahun yang setara (tahun dengan hari yang persis sama dalam seminggu) antara 6 AD dan 33 AD. Untuk melakukan ini, kita kurangi offset dan kemudian ambil tahun mod 28; tetapi offset berubah setiap 128 tahun, dan selama bertahun-tahun dapat dibagi 128, kita harus melakukan penyesuaian lebih lanjut karena tahun yang setara tidak boleh menjadi tahun kabisat.

Ngomong-ngomong, begitu selesai, kita mencari bulan dan hari di tahun yang setara itu menggunakan built-in DayName.

Misha Lavrov
sumber
3

Python 2 , 67 byte

def f(m,d,y):y-=m<3;return(y+y/4-y/128+int("0032503514624"[m])+d)%7

Cobalah online!

int("..."[m])dapat digantikan oleh ord("-bed=pen+mad."[m]).

Tuan Xcoder
sumber
3

JavaScript, 65 59 byte

(d,m,y)=>(y-=m<3,(+"0032503514624"[m]+y+(y>>2)-(y>>7)+d)%7)

(d,m,y)=>(y-=m<3,(+"0032503514624"[m]+~~y+~~(y/4)-~~(y/128)+d)%7)

Menggunakan metode Sakamoto. Memberi0=Sunday, 1=Monday, 2=Tuesday...

-2 byte berkat Misha Lavrov
-4 byte terima kasih kepada Arnauld

ericw31415
sumber
1
Saya pikir ~~ybisa diubah menjadi y. Anda tidak akan mendapatkan tahun fraksional di input, kan? Tapi saya akui saya tidak fasih dalam JavaScript.
Misha Lavrov
2
Bagaimana dengan +y+(y>>2)-(y>>7)?
Arnauld
@MishaLavrov Ya, itu benar. Untuk beberapa alasan saya memutuskan saya harus lantai segalanya.
ericw31415
2

Sebenarnya , 37 byte

Ini adalah pelabuhan modifikasi notjagan dari algoritma Sakamoto , tetapi dengan beberapa trik berbasis tumpukan seperti yang dijelaskan di bawah ini. Format input adalah day, year, month. Format keluaran adalah 0-indexed with Sunday as 0. Selamat datang saran bermain golf! Cobalah online!

;"0032503514624"Ei)3>±+;¼L;¼¼½L±kΣ7@%

Penjelasan

                     Implicit input: day, year, month (month is at TOS)
;"0032503514624"Ei)  Get the month code, convert to float, rotate to bottom of the stack
3>±+                 If 3>month, add -1 to year
;¼L                  Push floor(year/4) to stack
;¼¼½L±               Push floor(year/4) and append -floor(year/128) to stack.
kΣ                   Wrap the stack (y/128, y/4, y, month_code, d) in a list and sum
7@%                  Get the sum modulo 7
                     Implicit return
Sherlock9
sumber
2

Jelly , 32 31 30 28 byte

Port lain dari modifikasi notjagan ini dari algoritma Sakamoto tetapi dengan sejumlah basis-250 di tempat 032503514624(tidak perlu ekstra 0karena Jelly adalah 1-diindeks). Format input adalah month, year, day. Format keluaran adalah 0-based with Sunday as 0. Saran bermain golf sangat diterima karena cara tautannya sulit untuk diatur dan mungkin masih bisa golf. Cobalah online!

Sunting: -1 byte dari menggunakan bit shift bukannya pembagian integer. -1 byte dari mengatur ulang format awal dan input. -2 byte terima kasih kepada Erik the Outgolfer dan caird coinheringaahing.

3>_@µæ»7,2I+µ“Ṿ⁵Ḥ9{’D³ị+⁵+%7

Penjelasan

         Three arguments: month, year, day
3>_@     Subtract (month<3) from year. Call it y.
µ        Start a new monadic chain.
æ»7,2    Bit shift y by both 7 and 2 (equivalent to integer division by 128 and by 4).
I+       y + y/4 - y/128
µ        Start a new monadic chain.
“Ṿ⁵Ḥ9{’  The number 732573514624 in base 250.
D        The list [7, 3, 2, 5, 7, 3, 5, 1, 4, 6, 2, 4].
³ị       Get the month code from the list (1-based indexing).
+⁵+      Add y, our month code, and day together.
%7       Modulus 7.
Sherlock9
sumber
29 byte
caird coinheringaahing