Día de la semana del próximo 29 de febrero.


14

Escriba una función que tome una fecha y regrese el día de la semana del próximo 29 de febrero después de esa fecha.

  • La entrada es una cadena en el formato ISO extendido: AAAA-MM-DD (por ejemplo, el 27 de mayo de 2010 sería "2010-05-27").

  • La salida es una cadena que es el nombre del día de la semana (por ejemplo, "lunes"). Las mayúsculas no importan, pero da el nombre completo en inglés.

  • Si la fecha dada es el 29 de febrero, regrese el día de la semana del próximo 29 de febrero .

  • Utilice los cálculos para el calendario gregoriano proleptico (por lo tanto, utiliza los cálculos del año bisiesto gregoriano para toda su longitud). No se preocupe por el calendario juliano o cuando ocurrió el cambio de juliano a gregoriano. Solo asume Gregorian para todo.

  • La función debería funcionar al menos para el rango de "0001-01-01" - "2100-01-01".

  • Siéntase libre de usar las bibliotecas estándar que le proporcione el idioma de su elección, pero no use bibliotecas de terceros a menos que desee incluir ese código como parte de su solución.

  • El código más corto (menos caracteres) gana.

Ejemplos:

  • func("0001-01-01") -> "Sunday"
  • func("1899-12-03") -> "Monday"
  • func("1970-01-01") -> "Tuesday"
  • func("1999-07-06") -> "Tuesday"
  • func("2003-05-22") -> "Sunday"
  • func("2011-02-17") -> "Wednesday"
  • func("2100-01-01") -> "Friday"

(y no, no tienes que nombrar la función func)

Consejos:

  • Recuerde que los años que terminan en 00 que no son divisibles por 400 no son años bisiestos.
  • El 1 de enero de 0001 es un lunes.

Respuestas:


7

Windows PowerShell, 65

Bastante sencillo.

filter f{for($d=date $_;($d+='1').day*$d.month-58){}$d.dayofweek}

Como de costumbre, podemos reducir dos bytes si estamos dispuestos a esperar mucho tiempo hasta su finalización:

filter f{for($d=date $_;($d+=9).day*$d.month-58){}$d.dayofweek}

Prueba:

> '0001-01-01','1899-12-03','1970-01-01','1999-07-06','2003-05-22','2011-02-17','2100-01-01'|f
Sunday
Monday
Tuesday
Tuesday
Sunday
Wednesday
Friday

Historia:

  • 18/02/2011 00:06 (65) Primer intento.

¿Qué camino es necesario para que esto funcione? Tengo una cita de GnuWin en mi camino, que la está rompiendo.
Peter Taylor

@ Peter: Podría chocar con date. Simplemente elimine GNUWin32 de la RUTA y debería funcionar. O cambie datea Get-Date(ese tipo de comportamiento alternativo solo funciona cuando no se encuentra ningún comando, para verificar, solo use gcm date). De todos modos, no considero que haya un problema particular con este script ya que GNUWin32 no forma parte de ninguna instalación estándar de Windows.
Joey

La razón por la que pregunté fue porque ya intenté usar get-datey recibí el mensaje de error Method invocation failed because [System.Management.Automation.PSObject] doesn't contain a method named 'op_Addition'.¿Necesita PS2 o .Net 4 o algo así?
Peter Taylor

@ Peter: probé PowerShell v2. .NET 4 no funciona porque PowerShell está vinculado al tiempo de ejecución 2.0. En cualquier caso, no debería haber un PSObject regresando Get-Datesino a System.DateTime.
Joey

Es muy raro $d=Get-Date "0400-01-01"; $d++da un mensaje de error acerca de ++no estar definido en DateTime. El mismo reemplazo ++con +=1o +="1"o +='1'da el mensaje de error sobre PSObject. Y solo +"1"funciona.
Peter Taylor

5

Ruby 1.9, 85 caracteres

f=->a{require"date";d=Date.parse(a,0,0)+1;d+=1until d.day*d.month==58;d.strftime"%A"}

Solución directa. Llama a la función con f[args].

  • Editar: (87 -> 97) Se 0001-01-01corrigió el caso de prueba.
  • Edición 2: (97 -> 91) Date.parse también permite especificar la fecha de la reforma del calendario.
  • Edición 3: (91 -> 87) Use una lambda en lugar de una función. Gracias dogbert !
  • Edición 4: (87 -> 85) Eliminar espacios innecesarios. Gracias de nuevo, Dogbert !

44
Falla el caso de prueba para "0001-01-01". La fecha de Ruby es demasiado poderosa, tiene en cuenta las fechas de Julian.
steenslag

@Ventero ¿Qué hace def *? Nunca lo había visto antes.
steenslag

@steenslag: Gracias, arreglé ese caso de prueba. def*solo define una función llamada *. De esa manera no necesito un espacio entre defy el nombre de la función.
Ventero

1
¿No podrías definir una lambda en su lugar? a = -> {...}
Dogbert

1
Además, no hay necesidad de ningún espacio después del strftime.
Dogbert

3

T-SQL 166185 caracteres

CREATE PROCEDURE f29 (@d DATETIME) AS
DECLARE @i int
SET @i=YEAR(DATEADD(M,-2,@d)+3)
SET @i=@i+(4-@i%4)
IF @i%100=0 AND @i%400<>0 SET @i=@i+4
SELECT DATENAME(W,CAST(@i AS CHAR)+'-2-29')

Ya estaba jugando con las funciones de fecha T-SQL, así que pensé por qué no ...

La solución original era incorrecta ...

Esto es lo que realmente tengo que hacer para conseguir que la estrategia para el trabajo:

CREATE PROCEDURE f29 (@d DATE) AS
DECLARE @i int
SET @i = YEAR(@d)
BEGIN TRY 
SET @i=YEAR(DATEADD(D, 3, DATEADD(M,-2,@d)))
END TRY
BEGIN CATCH
END CATCH
SET @i=@i+(4-@i%4)
IF @i%100=0 AND @i%400<>0 SET @i=@i+4
SELECT DATENAME(W,CAST(@i AS CHAR)+'-2-29')

Dado que creo un desbordamiento restando 2 meses de 0001-01-01, incluso si uso el tipo de datos correcto, renuncio a crear algo corto y válido para esta pregunta. O_o. Trixsy cuestiona.
Mootinator

Me encanta ver estas soluciones T-SQL. :)
Steve

3

C #, 176

Func<String,String>f=(d)=>{DateTime n;for(n=DateTime.Parse(d).AddDays(307);!(DateTime.IsLeapYear(n.Year));n=n.AddYears(1)){}return new DateTime(n.Year,2,29).ToString("dddd");};

Puede guardar 8 bytes utilizando una definición de función normal:string f(string d){...}
Joey

.ToString("dddd")imprime la fecha en la configuración regional actual, sin embargo, no en inglés.
Joey

165 caracteres => cadena f (cadena d) {var n = DateTime.Parse (d) .AddDays (307); while (! (DateTime.IsLeapYear (n.Year))) n = n.AddYears (1); return (nuevo DateTime (n.Year, 2,29)). DayOfWeek.ToString ();}
Stephan Schinkel

Mejorado aún más a 127 caracteres:string f(string d){var n=DateTime.Parse(d).AddDays(1);return DateTime.IsLeapYear(n.Year)&&n.DayOfYear==60?n.DayOfWeek+"":f(n+"");}
Patrik Westerlund

3

Bash, 96 bytes

Gracias Peter ... Versión altamente golfista, 96 bytes:

i=1;until [ `date -d"$1 $i days" +%m-%d` = "02-29" ];do((i++));done
date -d "${1} ${i} days" +%A

Versión anterior, 229 bytes

#!/bin/bash
from=$1
i=1
while [ "$isFeb" = "" ] || [ "$is29" = "" ]
do
isFeb=`date -d "${from} ${i} days" | grep Feb`
is29=`date -d "${from} ${i} days" +%Y-%m-%d | grep "\-29"`
((i++))
done
((i--))
date -d "${from} ${i} days" +%A

Muestra de E / S

:~/aman>./29Feb.sh 0001-01-01
Sunday
:~/aman>./29Feb.sh 1899-12-03
Monday
:~/aman>./29Feb.sh 1970-01-01
Tuesday

podría tener que establecer TZ si no se establece una zona horaria predeterminada, aprendí cyberciti.biz/faq/... mientras hacía esto en algún IDE en línea
Aman ZeeK Verma

1
¿Vas a jugar al golf esto? ; p Puedes reemplazar todo antes de la línea final coni=0;d=;until [ `date -d"$1 $i days" +%m-%d` = "02-29" ];do((i++));done
Peter Taylor

:-) como ya discutimos acerca de mi crudeza sobre bash! ... Por alguna razón, no juego mucho con bash ... ¡son tan propensos a errores! ... Gracias por su sugerencia ... ¡actualizado!
Aman ZeeK Verma

1
La crudeza con bash no es excusa para usar nombres de variables de cuatro letras: P
Peter Taylor

Sí señor, tengo su punto.
Aman ZeeK Verma

2

Perl, ninguna biblioteca fecha: 160 159 155

sub f {($ y, $ m) = split / - /, @ _ ​​[0], 2; $ y ++ if ($ m> '02 -28 '); $ y = ($ y + 3)% 400 >> 2; $ y + = $ y &&! ($ Y% 25); @ r = (martes, miércoles, jueves, viernes, sábado, domingo, lunes); @ r [(5 * $ y - ($ y / 25 y 3))% 7]. "Día";}

El beneficio real de estas bibliotecas de fechas es enviar la longitud de los nombres de los días a otra persona.

Por otro lado, creo que esta es la única solución hasta ahora que funciona independientemente de la configuración regional.


2

FECHA y algo de pegamento BASHy (90)

La función:

f(){ while :;do $(date -d$1+1day +'set - %F %A 1%m%d');(($3==10229))&&break;done;echo $2;}

Pruebas:

$ for x in 0001-01-01 1899-12-03 1970-01-01 1999-07-06 2003-05-22 2011-02-17 2100-01-01 ; do f $x ; done
Sunday
Monday
Tuesday
Tuesday
Sunday
Wednesday
Friday

1

D: 175 caracteres

S f(S)(S s){auto d=Date.fromISOExtString(s)+days(1);while(d.month!=Month.feb||d.day!=29)d+=days(1);return["Sun","Mon","Tues","Wednes","Thurs","Fri","Sat"][d.dayOfWeek]~"day";}

Más legible:

S f(S)(S s)
{
    auto d = Date.fromISOExtString(s) + days(1);

    while(d.month != Month.feb || d.day != 29)
        d += days(1);

    return ["Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Sat"][d.dayOfWeek] ~ "day";
}

Es muy fácil escribir en D, pero definitivamente no va a ganar ningún concurso de golf de código. Aún así, fuera del golf de código, preferiría que sea fácil de escribir y comprender, pero mucho más que tener un término breve pero difícil de escribir y comprender.


1

Java 8 - 252 caracteres

Golfizado:

import java.time.*;
import java.time.format.*;
public class S{public static void main(String[] a){LocalDate d=LocalDate.parse(a[0]).plusDays(1);while(d.getMonthValue()!=2||d.getDayOfMonth()!=29){d=d.plusDays(1);}System.out.println(d.getDayOfWeek());}}

Sin golf:

import java.time.*;
import java.time.format.*;
public class S {
    public static void main(String[] a) {
        LocalDate d = LocalDate.parse(a[0]).plusDays(1);

        while(d.getMonthValue()!=2 || d.getDayOfMonth()!=29) {
            d = d.plusDays(1);
        }
        System.out.println(d.getDayOfWeek());
    }
}

Acepto los votos negativos, pero ¿podría explicar "el necro es real" y vincular a una pregunta frecuente que explique su punto? No pensé que ganaría, pero pensé que sería interesante ver cómo Java podría hacerlo, especialmente. dado Java 8. Considero que el código de golf tiene "clases de peso" frente a una competencia absoluta. Java rara vez vencerá a Ruby o Python directamente.
Michael Easter

El OP prohíbe las bibliotecas de terceros, por lo que en 2011, una solución de Java sería desagradable, ya que uno no podría usar la popular biblioteca Joda Time. Sin embargo, Java 8 (lanzado en marzo de 2014) contiene la biblioteca JSR-310 DateTime - en.wikipedia.org/wiki/… . Mi razón es que pensé que Java 8 sería divertido y potencialmente interesante para algunos lectores. (Si no eres uno de esos, está bien: todavía hay una razón para la publicación.)
Michael Easter

1

Rebol - 78

f: func[d][system/locale/days/(until[d: d + 1 d/day * d/month = 58]d/weekday)]

Sin golf:

f: func [d] [
    system/locale/days/(
        until [
            d: d + 1
            d/day * d/month = 58
        ]
        d/weekday
    )
]

Ejemplo de uso (en la consola Rebol):

>> f 0001-01-01
== "Sunday"

>> f 2100-01-01
== "Friday"

1

PHP, 104 bytes

function f($s){for($y=$s-(substr($s,5)<"02-29");!date(L,$t=strtotime(++$y."-2-1")););return date(l,$t);}

Descompostura

for($y=$s-;                 // "-" casts the string to int; decrement year if ...
    (substr($s,5)<"02-29")  // ... date is before feb 29
    !date(L,                        // loop while incremented $y is no leap year
        $t=strtotime(++$y."-2-1")   // $t=feb 01 in that year (same weekday, but shorter)
    );
);
return date(l,$t);          // return weekday name of that timestamp

date(L): 1para el año bisiesto, de lo 0contrario
date(l): representación textual completa del día de la semana


0

GNU coreutils, 71 bytes

f(){
seq -f "$1 %gday" 2921|date -f- +'%m%d%A'|sed 's/0229//;t;d;:;q'
}

Búsqueda lineal de los próximos 8 años (peor caso, dado 2096-02-29). Sed encuentra y emite la primera línea que coincide con el 29 de febrero.

Me sorprendió descubrir que t;d;:;qera más corto que probar para ver si los dígitos permanecían ( /[01]/d;q), a pesar de tener el doble de comandos.

Pruebas

Agregué una línea adicional de pruebas para casos de esquina difíciles:

for i in 0001-01-01.Sunday 1899-12-03.Monday \
    1970-01-01.Tuesday     1999-07-06.Tuesday \
    2003-05-22.Sunday      2011-02-17.Wednesday 2100-01-01.Friday \
    2000-02-28.Tuesday     2000-02-29.Sunday    2000-03-01.Sunday   2096-02-29.Friday
do
    printf "%s => %s (expected %s)\n" ${i%.*} $(f ${i%.*}) ${i#*.}
done
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.