128 lat? Hipotetyczna reforma roku przestępnego

23

Zgodnie z tym filmem rok słoneczny wynosi 365 dni, 5 godzin, 48 minut, 45 sekund i 138 milisekund . W obecnym kalendarzu gregoriańskim zasady dotyczące lat przestępnych są następujące:

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

Niestety ta metoda jest wyłączona o jeden dzień co 3216 lat.

Jedną z możliwych metod reformowania kalendarza jest następująca zasada:

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

Ma to tę zaletę, że nie wymaga od nas zmiany kalendarzy przez kolejne 625 000 lat, dawania lub przyjmowania.

Powiedzmy, że cały świat decyduje, że od teraz używamy tego systemu co cztery lata, co roku przestępnym, z wyjątkiem co 128 lat, zmieniając nasze kalendarze w następujący sposób:

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

Jak wpłynęłoby to na nasze algorytmy dnia tygodnia?

Wyzwanie

  • Biorąc pod uwagę datę od roku 2000 do roku 100000, znajdź dzień tygodnia w tym nowym kalendarzu.
  • Dowolny format wejściowy i wyjściowy jest dozwolony, o ile wyraźnie określisz, jakich formatów używasz.
  • To jest golf golfowy, więc postaraj się, aby Twoje rozwiązania były jak najbardziej golfowe!

Przypadki testowe

"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

Sugestie i opinie na temat wyzwania są mile widziane. Powodzenia i dobrej gry w golfa!

Sherlock9
źródło
W przypadku testowym nr 4 masz na myśli indeksowanie 1, prawda? W przeciwnym razie w tym tygodniu musi być 8 dni.
Sebastian
Mówisz też: „dobry golf”, więc czy to wyzwanie #-golf-golf? Jeśli tak, wprowadź kryteria zwycięstwa (np. Najmniejszą liczbę bajtów / znaków) i dodaj to jako znacznik.
Sebastian
@Sebastian Masz rację w obu kwestiach. Zredagowałem już wyzwanie. Dziękujemy za opinię
Sherlock9,
1
Czytając tytuł, natychmiast natknąłem się na wideo Matta Parkera. Miło też widzieć, że jest to połączone w wątku: D
PattuX
1
Po prostu weź standardowe biblioteki dnia tygodnia i odpowiednio zmodyfikuj stałe globalne, prawda? ;)
Wildcard,

Odpowiedzi:

8

C (gcc) , 60 bajtów

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

Wypróbuj online!

Prosta modyfikacja metody Sakamoto . Pobiera dane wejściowe jako liczby całkowite w kolejności month, day, yeari wypisuje liczbę dni (indeksowane w niedzielę przez 0).

notjagan
źródło
Co robi ta "-bed=pen+mad."część?
ericw31415
@ ericw31415 Uwzględnia długość każdego miesiąca w dniach i po prostu ze względu na wygląd jest przesuwana w górę o wielokrotność 7 zamiast być znakami na rzędnych (31, 28 ...).
notjagan
Racja, zapomniałem, że charwciąż oznacza liczbę, więc możesz zrobić to mod 7bezpośrednio.
ericw31415
6

Wolfram Language (Mathematica) , 57 55 53 bajtów

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

Wypróbuj online!

Pobiera trzy dane wejściowe: rok, miesiąc i dzień w tej kolejności. Na przykład, jeśli zapiszesz powyższą funkcję jako fun, a następnie fun[2048,2,28]powiesz dzień tygodnia 28 lutego 2048 r.

Jak to działa

Formuła m=#~Mod~128;6+Mod[(9#-m)/8-6Clip@m,28]konwertuje rok na rok równoważny (rok z dokładnie tymi samymi dniami tygodnia) między 6 AD a 33 AD. Aby to zrobić, odejmujemy przesunięcie, a następnie bierzemy mod roku 28; ale przesunięcie zmienia się co 128 lat i dla lat podzielnych przez 128 musimy dokonać dalszej korekty, ponieważ równoważny rok nie powinien być rokiem przestępnym.

W każdym razie, gdy to zrobimy, sprawdzamy miesiąc i dzień w tym samym roku za pomocą wbudowanego DayName.

Misza Ławrow
źródło
3

Python 2 , 67 bajtów

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

Wypróbuj online!

int("..."[m])można zastąpić ord("-bed=pen+mad."[m]).

Pan Xcoder
źródło
3

JavaScript, 65 59 bajtów

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

Wykorzystuje metodę Sakamoto. Daje0=Sunday, 1=Monday, 2=Tuesday...

-2 bajty dzięki Misha Lavrov
-4 bajty dzięki Arnauldowi

ericw31415
źródło
1
Myślę, że ~~ymożna po prostu zmienić na y. Nie dostaniesz ułamka roku na wejściu, prawda? Ale przyznaję, że nie jestem biegły w JavaScript.
Misha Lavrov,
2
Jak o +y+(y>>2)-(y>>7)?
Arnauld,
@MishaLavrov Tak, to prawda. Z jakiegoś powodu zdecydowałem, że powinienem posadzić wszystko.
ericw31415
2

Właściwie 37 bajtów

Jest to port modyfikacji notjagan jest z algorytmem Sakamoto , ale z kilku sztuczek stos oparte, jak opisano poniżej. Format wejściowy to day, year, month. Format wyjściowy to 0-indexed with Sunday as 0. Zapraszamy do gry w golfa! Wypróbuj online!

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

Wyjaśnienie

                     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
źródło
2

Galaretka , 32 31 30 28 bajtów

Kolejny port modyfikacji notjagan jest z algorytmem Sakamoto , ale z numerem w miejscu base-250 032503514624(nie potrzebują dodatkowych 0ponieważ Jelly jest 1-indeksowane). Format wejściowy to month, year, day. Format wyjściowy to 0-based with Sunday as 0. Sugestie dotyczące gry w golfa są bardzo mile widziane, ponieważ sposób połączenia był trudny do zorganizowania i nadal może być golfowy. Wypróbuj online!

Edycja: -1 bajta przy użyciu przesunięcia bitowego zamiast podziału na liczby całkowite. -1 bajt od przestawienia początku i formatu wejściowego. -2 bajty dzięki Erikowi Outgolfer i cairdowi coinheringaahing.

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

Wyjaśnienie

         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
źródło
29 bajtów
caird coinheringaahing