Calendario de renovación

17

Esto está inspirado en una de las preguntas de Downgoat en Sandbox, donde le sugerí que incluyera el 31 de abril como día Pi para las personas que usan el formato día / mes, ¡solo para que él me informe que no hay 31 de abril!

Dada una cadena de fecha en mes / día formato de que puede no ser válida, envíe la fecha correcta utilizando la renovación. (Primero reinvierta el mes, luego reinvierta el día).

Ejemplos:

"15/43" - Esto se lee como el día 43 del mes 15. Primero, pasamos el mes al próximo año, por lo que terminamos con 3 (marzo). Ahora, dado que marzo solo tiene 31 días, transferimos los días adicionales a abril, por lo que mostramos la fecha real como "4/12" (12 de abril).

"3/16" : esta es una fecha válida (16 de marzo). Devuélvelo como está.

"12/64" - Ah, tantos buenos recuerdos del 64 de diciembre ... Diciembre tiene 31 días, enero tiene 31 días, así que lo que realmente quiero decir es "2/2" (2 de febrero).

"19/99" - Primero, el 19 se convierte en un 7 (julio). Julio tiene 31 días, agosto tiene 31 días, septiembre tiene 30 días, por lo que la salida es "10/7" (7 de octubre).

"1/99999" : un año tiene 365 días. 99999 (mod 365) = 354. El día 354 del año es "12/20" .

"9999999/10" - Aparentemente, 9999999 (mod 12) = 3, entonces esto es "3/10" (10 de marzo).

Criterios

El mes de entrada es un entero> 0. El día de entrada es un entero> 0. El año nunca necesita ser especificado, por lo que no hay años bisiestos que tratar.

Actualizar:

Como creo que simplificaría demasiado el desafío, las funciones de calendario, como las de la clase Java Calendar , están prohibidas. Sin embargo, las funciones de análisis / formato de fechas todavía están permitidas.

geokavel
fuente
1
Otro caso de prueba importante sería uno con suficientes días para pasar más de 8 años, de tal manera que las respuestas que usan incorporados tengan que prestar atención a aquellos incorporados que utilizan años bisiestos.
Martin Ender
Oh, eso responde que ... Estaba a punto de publicar una respuesta de Mathematica que usa una función incorporada. : /
Martin Ender
@ Martin Lo siento por eso;).
geokavel
Como referencia, la solución de Mathematica todavía tenía 90 bytes de longitud (aunque eso estaba dominado masivamente por el procesamiento de cadenas). Sin embargo, si desea agregar un caso de prueba, 1/99999debería ceder 12/19, creo.
Martin Ender

Respuestas:

11

LabVIEW, 32 primitivas de LabVIEW

Eumel
fuente
Eso fue rápido.
Addison Crump
¿Me puede asegurar que no se utilizan funciones de calendario aquí?
geokavel
Lo bueno de LabVIEW es que es básicamente lo que parece ser. Lo primero escanea los números de una cadena de 2 módulos, la caja es una estructura de caja de interruptor que da 28,30 o 31 y luego se vuelve a armar como una cadena.
Eumel
4

C #, 269 223

string v(string n){var x=new[]{31,28,31,30,31,30,31,31,30,31,30,31};var s=n.Split('/');Func<string,int> p=int.Parse;var m=p(s[0]);var d=p(s[1]);m=m>=12?m%12:m;while(d>x[m]){d-=x[m];m=++m>=12?m%12:m;}return(m==0?1:m)+"/"+d;}

Editar : arreglado para funcionar en casos como 24/1, 36/1, etc. y jugó un poco al golf. Gracias por los comentarios, ¡hay varios lugares que guardé un poco!

Sin golf:

string v(string n)
{
    var x = new [] { 31 ,28, 31, 30, 31, 30,31, 31, 30, 31, 30, 31 };

    var s = n.Split('/');
    Func<string,int> p = int.Parse;
    var m = p(s[0]);
    var d = p(s[1]);
    m = m >= 12 ? m % 12 : m;
    while (d > x[m])
    {
        d -= x[m];
        m = ++m >= 12 ? m % 12 : m;
    }
    return (m==0?1:m) + "/" + d;
}
DrewJordan
fuente
Primero que nada: ¡Bienvenido a la comunidad! Supongo que podría guardar algunos Bytes asignando el diccionario en un bucle o usando una función de cambio (sin embargo, no hay C # pro aquí). También imprimir directamente ´m + "/" + d´ podría ayudar un poco. Y por último (esto podría o no funcionar) usando char * en lugar de string en los argumentos.
Eumel
Esto falla en ciertos casos de prueba, por ejemplo 24/1.
LegionMammal978
@Eumel gracias! La impresión directa utiliza Console.Writemás return, y en C # lo usaría char[]como reemplazo string, pero es la misma cantidad de caracteres y hace que la división sea /más problemática. ¡Pero su nota en el Diccionario me llevó a una versión mucho mejor!
DrewJordan
4

R, 208 182 bytes

m=c(31,28,31,30,31,30,31,31,30,31,30,31)
e=scan(sep="/");n=(e[1]/12-1)*12;if(!n%%12)n=12;if(n<0)n=e[1];j=e[2];while((j<-j-m[n])>0){n=n+1;if(n>12)n=1};j=m[n]+j;cat(n,j,sep="/")

Obtenga el mes dividiéndolo por 12, luego repita, eliminando el número de días del mes actual hasta obtener un número negativo., Invierta el último paso e imprima.

En varias líneas (necesita usar un archivo y obtenerlo):

m=c(31,28,31,30,31,30,31,31,30,31,30,31)
e=scan(sep="/")
n=(e[1]/12-1)*12
if(!n%%12)n=12
if(n<0)n=e[1]
j=e[2]
while((j<-j-m[n])>0){n=n+1;if(n>12)n=1}
j=m[n]+j;cat(n,j,sep="/")
Tensibai
fuente
Este es el mensaje que recibo cuando intento ejecutar su programa en R: pastebin.com/dPh1n64a
geokavel
Extraño volveré a
verificar
También recibí este mensaje. Su programa parece tener problemas con algunos meses. De lo contrario, se está ejecutando. pastebin.com/g3BCUDi8
geokavel
Gracias por la respuesta. Estoy en el camino en realidad, lo corregiré
Tensibai
1
@Tensibai sí, tienes razón, mi mal (debería haber recordado que el mensaje de error dice que espera "un verdadero").
plannapus
3

PHP> = 5.5, 181 bytes

list($m,$d)=explode("/",$argv[1]);$m%=12;$d%=365;$i=0;while($d>100)$d-=[31,28,31,30,31,30,31,31,30,31,30,31][$i++];$m+=$i;echo date_create_from_format("m/d","$m/$d")->format("n/j");

PHP casi admite la transferencia con solo el análisis de fechas y las instrucciones de formateo. Por ejemplo:

echo date_create_from_format("m/d","12/64")->format("n/j"); // Output: 2/2

Sin embargo, una vez que cualquiera de los números sea mayor que 100, PHP rechaza analizarlo y devuelve un error (probablemente por alguna razón arbitraria). Entonces, la teoría con esta respuesta es regresarlo a donde PHP lo analizará y luego enviarlo date_create_from_format().

Sin golf:

list($month, $day) = explode("/", $argv[1]);
$month = $month % 12;
$day = $day % 365;
$i = 0;
$days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
while($day > 31) $day -= $days[$i++];
$month += $i;
echo DateTime::createFromFormat("m/d", $month . "/" . $day)->format("n/j");

Pruébalo en línea

nickb
fuente
1
Necesita darme una manera de ingresar la cadena de fecha, o hacer que sea una función.
geokavel
Los parámetros GET no son aceptables como método de entrada en PHP . Necesitará hacer de esto una función y pasar la entrada como parámetros de función, u obtener entrada de $argvo STDIN.
Mego
@Mego Jeeze, dame un poco de tiempo para actualizar mi respuesta ya que la OP no indicó ningún requisito para la entrada - es lo suficientemente simple para el cambio $tde $argv[1]y ahora se lee de la entrada de línea de comandos.
nickb
Los requisitos de OP para la entrada son irrelevantes; tenemos una lista de métodos de E / S aceptables predeterminados (que he vinculado) para que los autores de desafíos no tengan que especificarlos en cada desafío.
Mego
2

JavaScript (ES6), 106 bytes

s=>eval('q="030101001010";p=s.split`/`;for(d=i=p[1],m=p[0]-1;i--;d>n&&(m++,d-=n))n=31-q[m%=12];m+1+"/"+d')

Explicación

s=>
  eval(`              // use eval to enable for loop without needing to write {} or return
    q="030101001010"; // q = array of 31 - days in each month
    p=s.split\`/\`;   // p = array of [ month, day ]
    for(
      d=i=p[1],       // d = day
        m=p[0]-1;     // m = month - 1
      i--;            // loop for each day, this is more iterations than needed but extra
                      //     iterations do not affect the result and it's the shortest way
                      //     to guarantee all months have been subtracted from d, it also
                      //     ensures the loop runs at least once to get m % 12
      d>n&&(m++,d-=n) // if too many days, subtract the month's days and increment month
    )
      n=31-q[m%=12];  // n = number of days in month, get m % 12
    m+1+"/"+d         // return the result
  `)

Prueba

usuario81655
fuente
1

Respuesta no competitiva - Bash + coreutils, 55

date -d1-$[(${1%/*}-1)%12+1]-1+$[${1#*/}-1]day +%-m/%-d

"Sin embargo, las funciones de análisis / formateo de fechas todavía están permitidas" . Supongo que esto significa que la dateutilidad está permitida.

La entrada se lee desde la línea de comando, por ejemplo:

$ ./rollovercal.sh 15/43
4/12
$ 

Esto no es competitivo porque el comando de fecha se expande a algo como esto, que agrega varios días:

date -d1-3-1+42day +%-m/%-d
Trauma digital
fuente
Está permitido siempre que no esté haciendo nada como date.add(875)aumentar la fecha en 875 días. Eso es principalmente lo que buscaba.
geokavel
@geokavel oh, ya veo. El datecomando completamente expandido aquí es date -d1-3-1+42day +%-m/%-d, así que está haciendo exactamente eso. Supongo que esta es una respuesta no competitiva :(
Digital Trauma