¿Qué día es hoy (u otras fechas)?


12

Tarea

Escriba un programa o una función que calcule el nombre del día de la semana de una fecha que ingresa un usuario.

De entrada y salida

Entrada es una cadena, YYYYMMDD.

Ejemplo de valores de entrada:

20110617: 17 de junio de 2011
19040229: 29 de febrero de 1904
06661225: 25 de diciembre de 666
00000101: 1 de enero de 0
99991231: 31 de diciembre de 9999

Puede suponer que todas las entradas son válidas. Tenga en cuenta que el año cero es válido.

La salida es un entero entre 0y 6. Cada entero representa un nombre de día de la semana. Puede decidir libremente qué número entero representa un nombre de día de la semana, como este

0: lunes
1: martes
2: miércoles
...
6: domingo

(en orden) o este

0: lunes
1: miércoles
2: domingo
...
6: sábado

(Desordenado).

Casos de prueba

Entrada Semana-día Salida ([0..6 -> Lunes ... Domingo] se utiliza en este ejemplo).

20110617 viernes 4
19500101 Domingo 6
22220202 Sábado 5
19000228 miércoles 2
19000301 jueves 3
19450815 Miércoles 2
19040229 Lunes 0
19040301 martes 1
17760704 jueves 3
20000228 Lunes 0
20000229 martes 1
20000301 miércoles 2
20121223 domingo 6
00000401 Sábado 5
66660606 miércoles 2
59161021 Sábado 5

Restricción

No debe usar ningún tipo de función / clase / ... que esté relacionada con la marca de tiempo o la fecha, como la Dateclase en Java/ JavaScript/ ActionScript, o la getdatefunción en PHP.

Debería usar el calendario gregoriano , que es utilizado por muchas personas ahora.

Por supuesto, el código más corto gana. Si dos códigos tienen la misma longitud, gana el código con los votos más altos.

(Debido: cuando hay más de 5 códigos que tienen más de (o igual) +1votos).


¿Hoy? ¡Por qué el día de Navidad!
Joey Adams

3
Solución optimista escrito en Bash (6 caracteres): echo 4.
trutheality

1
@trutheality No, no quise decir eso ... Lo que quería es un código que imprima / devuelva el día de la semana de una fecha que alguien escribió, no solo imprime el día de la semana de hoy.
JiminP

Oh, lo sé. Eso es lo que hace este.
trutheality

¡Es correcto al menos el 14% del tiempo!
Draco18s ya no confía en SE

Respuestas:


2

Ruby, 95 92 caracteres

Implementación sencilla de rubí con 0: lunes, ...

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

Desafortunadamente, debido al tipeo dinámico y débil de PHP, el algoritmo Sakamoto no funciona correctamente sin explícitamente poner en el suelo cada operación de división.


¿Puedes probar de nuevo? Durante algunos años me da resultados diferentes (por ejemplo, el caso de prueba 17760704 produce el martes en lugar del miércoles).
Howard

@Howard eso es muy extraño; para 17760704, me llega el miércoles. Sin embargo, tengo otras inconsistencias que no puedo explicar, por ejemplo, 19040229 regresa el martes. No estoy seguro de qué podría estar causando esto. Obtengo los mismos resultados cuando vuelvo a expandir el algoritmo y+y/4-y/100+y/400.
rintaun

Puedo ver que sucede con 497 * y / 400: y=4en ese caso, devuelve 4, en lugar del 5 correcto de y+y/4+y/100+y/400(donde solo entran en juego los dos primeros términos). Eso es lo que plaga mi respuesta de JavaScript. ¿Es posible que se estén creando dobles en lugar de ints? (Mi PHP es demasiado débil para saberlo)
DocMax

@DocMax: Dejar la expresión expandida tiene el mismo resultado (497y / 400 debería ser equivalente: y / 100 se resta yy / 400 se agrega de nuevo independientemente). Supongo que PHP solo está cortando todo después del decimal en lugar de redondearlo. Probé esto redondeando antes del módulo. Esto corrige dos de las anomalías, pero 19040229 aún devuelve el mismo resultado. ¿Alguna otra idea?
rintaun

@rintaun, no creo que sea el redondeo. Son fundamentalmente diferentes. Tomemos el ejemplo de arriba (y = 4): 497 * 4/400 = 1988/400 = 4 pero por otro lado 4 + 4 / 4-4 / 100 + 4/400 = 4 + 1-0 + 0 = 5 . Los términos / 100 y / 400 tienen demasiado peso en su cálculo, de modo que no se puede alcanzar el 2000.
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);
}

Esto abusa de cómo la división se redondea hacia cero, al menos en mi sistema (Linux x86).

La constante mágica 86400, tiene dos propósitos:

  • Reste del año para que sea negativo, sin afectar el día de la semana. Esto hace que las divisiones se redondeen hacia arriba en lugar de hacia abajo.
  • Cambie el número del día para que el lunes sea 0.

También es la cantidad de segundos en un día.


Use en y+=m>2;lugar de m>2?y++:0;y afeite unos pocos bytes.
Más claro

2

Javascript, 126 123 caracteres

Usando el algoritmo de Sakamoto con 0 = domingo:

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

Sospecho que las divisiones pueden colapsarse, pero en este momento no lo veo.

Editar: Mejora las divisiones (no es necesario ~~cuando solo puedes ~).


2

Python 2 , 83 116 113 109 bytes

Implementa el algoritmo de Sakamoto . Sugerencias de golf bienvenidas. Pruébalo en línea!

Editar: debería haber solucionado esto hace mucho tiempo. -6 bytes de las sugerencias de Jonathan Allan +2 bytes para arreglar el 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

La entrada debe ser una sola cadena.
msh210

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

0

Perl - 110 bytes

Aquí hay una solución para ejecutarse con perl -p source.pl 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

Simplemente copie y pegue los casos de prueba en stdin.

Este parece ser el único código sin variables, constantes de cadena y divisiones.


0

JavaScript (ES6), 73 bytes (no competitivos)

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

Intentalo

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 qué no competir?
programador

@ programmer5000, verifique la fecha en que se publicó el desafío;)
Shaggy
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.