128 anos? Reforma hipotética do ano bissexto

23

O ano solar é de 365 dias, 5 horas, 48 ​​minutos, 45 segundos e 138 milissegundos, de acordo com este vídeo . Com o atual calendário gregoriano, as regras para os anos bissextos são as seguintes:

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

Infelizmente, esse método é desativado em um dia a cada 3216 anos.

Um método possível de reformar o calendário é a seguinte regra:

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

Isso tem o benefício de não exigir que alteremos nossos calendários novamente por mais 625.000 anos, mais ou menos.

Digamos que o mundo inteiro decida que, a partir de agora, usamos esse sistema a cada quarto ano é um ano bissexto, exceto a cada 128 anos, alterando nossos calendários da seguinte forma:

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

Como isso afetaria nossos algoritmos do dia da semana?

O desafio

  • Dada uma data do ano 2000 ao ano 100000, encontre o dia da semana nesse novo calendário.
  • Qualquer formato de entrada e saída é permitido, desde que você especifique claramente quais formatos você está usando.
  • Este é um código de golfe, então tente tornar suas soluções o mais golfistas possível!

Casos de teste

"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

Sugestões e comentários sobre o desafio são bem-vindos. Boa sorte e bom golfe!

Sherlock9
fonte
Para o caso de teste nº 4, você quer dizer 1 indexado, certo? Caso contrário, teria que haver 8 dias nessa semana.
Sebastian
Além disso, você diz "bom golfe", então este é um desafio # de código-golfe? Nesse caso, insira os critérios de vencimento (por exemplo, número mais baixo de bytes / caracteres) e adicione-o como uma tag.
Sebastian
@ Sebastian Você está correto em ambos os aspectos. Eu já editei o desafio. Obrigado por seus comentários
Sherlock9
1
Ao ler o título, pensei no vídeo de Matt Parker. É bom vê-lo vinculado no tópico também: D
PattuX 30/11
1
Basta pegar as bibliotecas padrão do dia da semana e modificar as constantes globais de acordo, certo? ;)
Curinga

Respostas:

8

C (gcc) , 60 bytes

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

Experimente online!

Modificação simples do método de Sakamoto . Recebe entrada como argumentos inteiros na ordem month, day, yeare gera o número do dia (indexado 0 no domingo).

notjagan
fonte
O que a "-bed=pen+mad."peça faz?
precisa saber é o seguinte
@ ericw31415 É responsável pela duração de cada mês em dias e, simplesmente pela aparência, é aumentada por múltiplos de 7, em vez de ser personagem nos ordinais (31, 28 ...).
notjagan
Certo, esqueci que charainda representa um número, para que você possa fazer mod 7diretamente.
precisa saber é o seguinte
6

Wolfram Language (Mathematica) , 57 55 53 bytes

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

Experimente online!

Toma três entradas: o ano, o mês e o dia, nessa ordem. Por exemplo, se você salvar a função acima como fun, fun[2048,2,28]informa o dia da semana de 28 de fevereiro de 2048.

Como funciona

A fórmula m=#~Mod~128;6+Mod[(9#-m)/8-6Clip@m,28]converte o ano em um ano equivalente (um ano exatamente com os mesmos dias da semana) entre 6 dC e 33 dC. Para fazer isso, subtraímos um deslocamento e depois pegamos o ano mod 28; mas a compensação muda a cada 128 anos, e nos anos divisíveis por 128, temos que fazer um ajuste adicional porque o ano equivalente não deve ser um ano bissexto.

De qualquer forma, uma vez feito isso, procuramos o mês e o dia nesse ano equivalente usando o built-in DayName.

Misha Lavrov
fonte
3

Python 2 , 67 bytes

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

Experimente online!

int("..."[m])pode ser substituído por ord("-bed=pen+mad."[m]).

Mr. Xcoder
fonte
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)

Usa o método de Sakamoto. Dá0=Sunday, 1=Monday, 2=Tuesday...

-2 bytes graças a Misha Lavrov
-4 bytes graças a Arnauld

ericw31415
fonte
1
Eu acho que ~~ypode ser mudado para y. Você não receberá um ano fracionário na entrada, certo? Mas admito que não sou fluente em JavaScript.
Misha Lavrov
2
Que tal +y+(y>>2)-(y>>7)?
Arnauld
@MishaLavrov Sim, isso é verdade. Por alguma razão, decidi que deveria andar com tudo.
precisa saber é o seguinte
2

Na verdade , 37 bytes

Esta é uma porta da modificação do algoritmo de Sakamoto por notjagan , mas com alguns truques baseados em pilha, conforme descrito abaixo. O formato de entrada é day, year, month. O formato de saída é 0-indexed with Sunday as 0. Sugestões de golfe são bem-vindas! Experimente online!

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

Explicação

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

Geléia , 32 31 30 28 bytes

Outra maneira de modificar o algoritmo de Sakamoto por notjagan, mas com um número de base 250 no lugar de 032503514624(não precisa do extra 0porque o Jelly é indexado em 1). O formato de entrada é month, year, day. O formato de saída é 0-based with Sunday as 0. Sugestões de golfe são muito bem-vindas, pois a maneira como os links foram difíceis de organizar e ainda podem ser jogáveis. Experimente online!

Edit: -1 byte usando deslocamento de bits em vez de divisão inteira. -1 byte de reorganizar o início e o formato de entrada. -2 bytes graças a Erik the Outgolfer e caird coinheringaahing.

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

Explicação

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