128 años? Reforma hipotética del año bisiesto

23

El año solar es de 365 días, 5 horas, 48 ​​minutos, 45 segundos y 138 milisegundos, según este video . Con el calendario gregoriano actual, las reglas para los años bisiestos son las siguientes:

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

Desafortunadamente, este método se desactiva un día cada 3216 años.

Un posible método para reformar el calendario es la siguiente regla:

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

Esto tiene el beneficio de no requerir que cambiemos nuestros calendarios nuevamente por otros 625,000 años, más o menos.

Digamos que el mundo entero decide que, a partir de ahora, usamos este sistema de cada cuarto año, es un año bisiesto, excepto cada 128 años, cambiando nuestros calendarios de la siguiente manera:

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

¿Cómo afectaría esto a nuestros algoritmos del día de la semana?

El reto

  • Dada una fecha del año 2000 al año 100000, encuentre el día de la semana en este nuevo calendario.
  • Cualquier formato de entrada y salida está permitido siempre que especifique claramente qué formatos está utilizando.
  • Este es el código de golf, así que trate de hacer que sus soluciones sean lo más golficas posible.

Casos de prueba

"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

Sugerencias y comentarios sobre el desafío son bienvenidos. ¡Buena suerte y buen golf!

Sherlock9
fuente
Para el caso de prueba # 4, te refieres a 1 indexado, ¿verdad? De lo contrario, tendría que haber 8 días en esa semana.
Sebastian
Además, dices "buen golf", ¿es este un desafío de código # golf? Si es así, ingrese los criterios ganadores (por ejemplo, el menor número de bytes / caracteres) y agréguelo como etiqueta.
Sebastian
@Sebastian Tienes razón en ambos aspectos. Ya he editado el desafío. Gracias por sus comentarios
Sherlock9
1
Al leer el título, inmediatamente pensé en el video de Matt Parker. Es bueno verlo vinculado en el hilo también: D
PattuX
1
Simplemente tome las bibliotecas estándar del día de la semana y modifique las constantes globales en consecuencia, ¿verdad? ;)
Comodín el

Respuestas:

8

C (gcc) , 60 bytes

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

Pruébalo en línea!

Modificación simple del método de Sakamoto . Toma la entrada como argumentos enteros en el orden month, day, yeary genera el número del día (indexado en 0 el domingo).

notjagan
fuente
¿Qué hace la "-bed=pen+mad."parte?
ericw31415
@ ericw31415 Representa la duración de cada mes en días, y simplemente por el bien de la apariencia, se desplaza por múltiplos de 7 en lugar de ser caracteres en ordinales (31, 28 ...).
notjagan
Bien, olvidé que chartodavía representa un número, así que puedes hacerlo mod 7directamente.
ericw31415
6

Wolfram Language (Mathematica) , 57 55 53 bytes

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

Pruébalo en línea!

Toma tres entradas: el año, el mes y el día, en ese orden. Por ejemplo, si guarda la función anterior como fun, le fun[2048,2,28]indica el día de la semana del 28 de febrero de 2048.

Cómo funciona

La fórmula m=#~Mod~128;6+Mod[(9#-m)/8-6Clip@m,28]convierte el año en un año equivalente (un año con exactamente los mismos días de la semana) entre 6 DC y 33 DC. Para hacer esto, restamos un desplazamiento y luego tomamos el año mod 28; pero la compensación cambia cada 128 años, y durante años divisibles por 128, tenemos que hacer un nuevo ajuste porque el año equivalente no debería ser bisiesto.

De todos modos, una vez hecho esto, buscamos el mes y el día en ese año equivalente usando el incorporado DayName.

Misha Lavrov
fuente
3

Python 2 , 67 bytes

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

Pruébalo en línea!

int("..."[m])puede ser sustituido por ord("-bed=pen+mad."[m]).

Sr. Xcoder
fuente
3

JavaScript, 65 59 bytes

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

Utiliza el método de Sakamoto. Da0=Sunday, 1=Monday, 2=Tuesday...

-2 bytes gracias a Misha Lavrov
-4 bytes gracias a Arnauld

ericw31415
fuente
1
Creo que ~~ysolo se puede cambiar a y. No vas a obtener un año fraccionario en la entrada, ¿verdad? Pero admito que no soy fluido en JavaScript.
Misha Lavrov
2
¿Qué tal +y+(y>>2)-(y>>7)?
Arnauld
@MishaLavrov Sí, eso es cierto. Por alguna razón, decidí que debía hacer todo.
ericw31415
2

En realidad , 37 bytes

Este es un puerto de modificación de notjagan del algoritmo de Sakamoto , pero con algunos trucos basados ​​en pila como se describe a continuación. El formato de entrada es day, year, month. El formato de salida es 0-indexed with Sunday as 0. Sugerencias de golf bienvenidas! Pruébalo en línea!

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

Explicación

                     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
fuente
2

Jalea , 32 31 30 28 bytes

Otro puerto de modificación de notjagan del algoritmo de Sakamoto pero con un número base-250 en lugar de 032503514624(no necesita el extra 0porque Jelly está indexado en 1). El formato de entrada es month, year, day. El formato de salida es 0-based with Sunday as 0. Las sugerencias de golf son muy bienvenidas ya que la forma en que los enlaces fueron difíciles de organizar y aún puede ser fácil de jugar. Pruébalo en línea!

Editar: -1 byte por usar bit shift en lugar de división entera. -1 byte de reorganizar el comienzo y el formato de entrada. -2 bytes gracias a Erik the Outgolfer y caird coinheringaahing.

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

Explicación

         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
fuente
29 bytes
caird coinheringaahing