Que dia é hoje (ou outras datas)?


12

Tarefa

Escreva um programa ou uma função que calcule o nome do dia da semana de uma data inserida pelo usuário.

Entrada e Saída

Entrada é uma sequência YYYYMMDD,.

Exemplo de valores de entrada:

20110617: 17 de junho de 2011
19040229: 29 de fevereiro de 1904
06661225: 25 de dezembro de 666
00000101: 1 de janeiro de 0
99991231: 31 de dezembro de 9999

Você pode assumir que todas as entradas são válidas. Observe que o ano zero é válido.

A saída é um número inteiro entre 0e 6. Cada número inteiro representa um nome para o dia da semana. Você pode decidir livremente qual número inteiro representa um nome para o dia da semana, como este

0: segunda-feira
1: terça-feira
2: quarta-feira
...
6: domingo

(em ordem) ou este

0: segunda-feira
1: quarta-feira
2: domingo
...
6: sábado

(não está em ordem).

Casos de teste

Entrada Saída do dia da semana ([0..6 -> segunda-feira .. domingo] é usado neste exemplo.)

20110617 sexta-feira 4
19500101 domingo 6
22220202 sábado 5
19000228 quarta-feira 2
19000301 quinta-feira 3
19450815 quarta-feira 2
19040229 segunda-feira 0
19040301 terça-feira 1
17760704 quinta-feira 3
20000228 segunda-feira 0
20000229 terça-feira 1
20000301 quarta-feira 2
20121223 domingo 6
00000401 sábado 5
66660606 quarta-feira 2
59161021 sábado 5

Restrição

Você não deve usar nenhum tipo de função / classe / ... que esteja relacionada ao registro de data e hora, como Dateclasse em Java/ JavaScript/ ActionScriptou getdatefunção em PHP.

Você deve usar o calendário gregoriano , que é usado por muitas pessoas agora.

Obviamente, o código mais curto vence. Se dois códigos tiverem o mesmo comprimento, o código com mais votos vence.

(Vencimento: quando houver mais de 5 códigos com mais de (ou igual) +1voto).


Hoje? Dia de Natal!
Joey Adams

3
Solução optimista escrito em Bash (6 caracteres): echo 4.
trutheality

1
@ verdade, não, eu não quis dizer isso .. O que eu queria é um código que imprima / retorne o dia da semana de uma data que alguém digitou, e não apenas imprima o dia da semana de hoje.
JiminP

Oh eu sei. Isso é o que este faz.
trutheality

É certo pelo menos 14% do tempo!
Draco18s não confia mais no SE

Respostas:


2

Ruby, 95 92 caracteres

Implementação simples e simples de ruby ​​com 0: segunda-feira, ...

p ((y=(d=gets.to_i)/(k=100)/k-((m=d/k%k)<3?1:0))+y/4-y/k+y/400+"squsptrotqro"[-m].ord+d%k)%7

4

PHP - 101 97 103 125 caracteres

  • Algoritmo Sakamoto
  • 0 = domingo

Código

<?php fscanf(STDIN,"%4d%2d%2d",$y,$m,$d);@$a=a032503514624;$y-=$m<3;$z=$y+1;echo($y+$y/4%$z-$y/100%$z+$y/400%$z+$a[$m]+$d)%7;

Nota

Infelizmente, devido à digitação dinâmica e fraca do PHP, o algoritmo Sakamoto não funciona corretamente sem incluir explicitamente cada operação de divisão.


Você pode testar novamente? Durante alguns anos, obtive resultados diferentes (por exemplo, testcase 17760704 gera terça-feira em vez de quarta-feira).
Howard

@ Howard isso é muito estranho; para 17760704, recebo quarta-feira. Porém, eu recebo outras inconsistências que não posso explicar, por exemplo, 19040229 retorna terça-feira. Não tenho certeza do que poderia estar causando isso. Eu obtenho os mesmos resultados ao expandir o algoritmo para y+y/4-y/100+y/400.
rintaun

Eu posso ver isso acontecendo com 497 * y / 400: y=4nesse caso, retorna 4, em vez dos 5 corretos y+y/4+y/100+y/400(de onde apenas os dois primeiros termos entram em jogo). É isso que atormenta minha resposta em JavaScript. É possível que duplas estejam sendo criadas em vez de ints? (Meu PHP é fraco demais para saber.)
DocMax

@DocMax: Deixar a expressão expandida tem o mesmo resultado (497y / 400 deve ser equivalente: y / 100 é subtraído e y / 400 adicionado novamente independentemente). Eu estou supondo que o PHP está cortando tudo após o decimal em vez de arredondá-lo. Eu testei isso arredondando antes do módulo. Isso corrige duas das anomalias, mas 19040229 ainda retorna o mesmo resultado. Alguma outra ideia?
rintaun

@rintaun eu não acho que é o arredondamento. Eles são fundamentalmente diferentes. Veja o exemplo acima (y = 4): 497 * 4/400 = 1988/400 = 4, mas, por outro lado, 4 + 4 / 4-4 / 100 + 4/400 = 4 + 1-0 + 0 = 5 . Os termos / 100 e / 400 ganham muito peso em seu cálculo, de modo que o 2000 não pode ser alcançado.
Howard

2

C - 129

main(y,m,d,s)
{
    scanf("%04d%02d%02d",&y,&m,&d);
    y-=s=86400;
    d+=y+"-addgbegcfadf"[m];
    m>2?y++:0;
    putchar(48+(d+y/4-y/100+y/400+s+s)%7);
}

Isso abusa de como a divisão se aproxima de zero, pelo menos no meu sistema (Linux x86).

A constante mágica 86400, serve a dois propósitos:

  • Subtraia do ano para torná-lo negativo, sem afetar o dia da semana. Isso torna as divisões arredondadas para cima, em vez de para baixo.
  • Mude o número do dia para que segunda-feira seja 0.

Também é o número de segundos em um dia.


Use em y+=m>2;vez de m>2?y++:0;e raspe alguns bytes.
Clearer

2

Javascript, 126 123 caracteres

Usando o algoritmo de Sakamoto com 0 = domingo:

prompt().replace(/(....)(..)(..)/,function(_,y,m,d){y-=m<3;alert((+d+y-~(y/4)+~(y/100)-~(y/400)+ +".621462403513"[+m])%7)})

Suspeito que as divisões possam estar em colapso, mas no momento não estou vendo.

Editar: Melhorou as divisões (não é necessário ~~quando você pode apenas ~).


2

Python 2 , 83 116 113 109 bytes

Implementa o algoritmo de Sakamoto . Sugestões de golfe são bem-vindas. Experimente online!

Edit: Eu deveria ter corrigido isso há muito tempo. -6 bytes das sugestões de Jonathan Allan +2 bytes para realmente corrigir o código.

def w(s):m=int(s[4:6]);y,d=int(s[:4])-(m<3),int(s[6:]);return(y+y/4-y/100+y/400+int('032503514624'[m-1])+d)%7

A entrada deve ser uma única sequência.
precisa saber é o seguinte

int('032503514624'[m-1])salva 6
Jonathan Allan

0

Perl - 110 bytes

Aqui está uma solução a ser executada com o perl -p source.pl OU o perl -pe 'here-is-code'.

s/((..)(..))(..)(..)/(1+3*$1+$2-2*($1%4+$2%4)-(2<$4?$4+(1&$4&&4-(8&$4)):(2^$4)+(!($3%4)-!-$3+!($2%4)))+$5)%7/e

Simplesmente copie e cole os casos de teste no stdin.

Este parece ser o único código sem variáveis, constantes de string e divisões.


0

JavaScript (ES6), 73 bytes (Não concorrente)

d=>(w=new Date(d[s="slice"](0,4),d[s](4,6)-1,d[s](-2)).getDay())-(w?1:-6)

Tente

f=
d=>(w=new Date(d[s="slice"](0,4),d[s](4,6)-1,d[s](-2)).getDay())-(w?1:-6)
o.innerText=f(i.value="59161021")
oninput=_=>i.value.length==8&&(o.innerText=f(i.value))
<input id=i type=number><pre id=o>


Por que não competir?
Programmer5000

@ programmer5000, verifique a data do desafio foi publicado;)
Shaggy
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.