Calendario di rollover


17

Questo è ispirato da una delle domande di Downgoat in Sandbox, in cui gli ho suggerito di includere il 31 aprile come Pi day per le persone che usano il formato giorno / mese, solo per lui che mi informa che non c'è 31 aprile!

Data una stringa di data nel formato mese / giorno che potrebbe non essere valida, emettere la data corretta usando il rollover. (Rollover prima il mese, quindi rollover il giorno).

Esempi:

"15/43" - Questo si legge come il 43 ° giorno del 15 ° mese. Innanzitutto, passiamo al mese successivo, quindi finiamo con il 3 (marzo). Ora, poiché marzo ha solo 31 giorni, passiamo al rollover dei giorni in più fino ad aprile, quindi produciamo la data effettiva come "4/12" (12 aprile).

"3/16" - Questa è una data valida (16 marzo). Restituirlo così com'è.

"12/64" - Ah, tanti bei ricordi dal 64 dicembre ... Dicembre ha 31 giorni, gennaio ha 31 giorni, quindi quello che intendo davvero è "2/2" (2 febbraio).

"19/99" - Innanzitutto, il 19 diventa un 7 (luglio). Luglio ha 31 giorni, agosto ha 31 giorni, settembre ha 30 giorni, quindi l'output è "10/7" (7 ottobre).

"1/99999" - Un anno ha 365 giorni. 99999 (mod 365) = 354. Il giorno 354 dell'anno è "12/20" .

"9999999/10" - Apparentemente, 9999999 (mod 12) = 3, quindi questo è "3/10" (10 marzo).

criteri:

Il mese di input è un numero intero> 0. Il giorno di input è un numero intero> 0. L'anno non deve mai essere specificato, pertanto non ci sono anni bisestili da affrontare.

Aggiornare:

Poiché penso che semplificherebbe eccessivamente la sfida, le funzioni del calendario, come quelle della classe Calendar Java , sono vietate. Le funzioni di analisi / formattazione della data sono comunque consentite.



1
Un altro caso di test importante sarebbe quello con giorni sufficienti per un periodo di tempo superiore a 8 anni, in modo tale che le risposte che utilizzano gli incorporamenti debbano prestare attenzione a quegli incorporamenti negli anni bisestili.
Martin Ender,

Oh, questo risponde che ... Stavo per pubblicare una risposta Mathematica che utilizza un built-in. : /
Martin Ender il

@Martin Mi dispiace per quello;).
geokavel,

Per riferimento, la soluzione Mathematica era ancora lunga 90 byte (anche se era ampiamente dominata dall'elaborazione delle stringhe). Se si desidera aggiungere un simile test, ciò nonostante, si 1/99999dovrebbe 12/19pensare.
Martin Ender,

Risposte:


11

LabVIEW, 32 LabVIEW Primitives


È stato veloce.
Addison Crump,

Potete assicurarmi che non ci sono funzioni di calendario utilizzate qui?
geokavel,

La cosa positiva di LabVIEW è che è sostanzialmente quello che sembra essere. La prima cosa che scansiona i numeri da un modulo di stringa 2, la scatola è una struttura a scatola di commutazione che emette 28,30 o 31 e quindi viene rimessa insieme come stringa.
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;}

Modifica : risolto per funzionare per casi come 24/1, 36/1, ecc. E golfato un po '. Grazie per i commenti, ci sono diversi posti che ho salvato un po '!

Ungolfed:

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;
}

Prima di tutto: benvenuto nella community! Immagino che potresti salvare alcuni byte assegnando il dizionario in un ciclo o usando una funzione di commutazione (nessun C # pro qui però). Anche la stampa diretta ´m + "/" + d´ potrebbe essere di aiuto. E ultimo (questo potrebbe o non potrebbe funzionare) usando char * invece di string negli argomenti.
Eumel,

Ciò fallisce in alcuni casi di test, ad es 24/1.
LegionMammal978,

@Eumel grazie! La stampa diretta usa un valore Console.Writemaggiore di return, e in C # lo userei char[]come sostituto string, ma è la stessa quantità di caratteri e rende /più problematica la scissione . Ma la tua nota sul dizionario mi ha portato a una versione molto migliore!
DrewJordan,

4

R, 208 182 byte

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="/")

Ottieni il mese dividendo per 12, quindi esegui il ciclo, rimuovendo il numero di giorni del mese corrente fino a quando non ottieni un numero negativo., Inverti l'ultimo passaggio e stampa.

Su più righe (è necessario utilizzare un file e sorgente):

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="/")

Questo è il messaggio che ricevo quando provo a eseguire il programma in R: pastebin.com/dPh1n64a
geokavel


Ho anche ricevuto questo messaggio. Il tuo programma sembra avere problemi con alcuni mesi. Altrimenti sta funzionando. pastebin.com/g3BCUDi8
geokavel,

Grazie per il feedback. In realtà sono sulla strada, lo correggerò
Tensibai il

1
@Tensibai sì hai ragione, mio ​​male (avrei dovuto ricordare che il messaggio di errore dice che si aspetta "un vero").
plannapus,

3

PHP> = 5,5, 181 byte

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 supporta quasi il rollover con le sole analisi della data e le istruzioni di formattazione. Per esempio:

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

Tuttavia, una volta che uno dei due numeri supera 100, PHP rifiuta di analizzarlo e restituisce un errore (probabilmente per qualche motivo arbitrario). Quindi, la teoria con questa risposta è di riportarla nel punto in cui PHP la analizzerà, quindi inviarla a date_create_from_format().

Ungolfed:

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");

Provalo online


1
Devi darmi un modo per inserire la stringa della data o renderla una funzione.
geokavel,

I parametri GET non sono accettabili come metodo di input in PHP . Sarà necessario rendere questa una funzione e passare l'input come parametro di funzione, oppure ottenere input da $argvo STDIN.
Mego

@Mego jeeze, dammi un po 'di tempo per aggiornare la mia risposta in quanto l'OP non ha precisato i requisiti per l'ingresso - è abbastanza semplice per il cambiamento $tper $argv[1]ora si legge da input a riga di comando.
Nick

I requisiti di indicazione dell'OP per l'input sono irrilevanti; abbiamo un elenco di metodi I / O accettabili predefiniti (che ho collegato) in modo che gli autori delle sfide non debbano specificarli su ogni sfida.
Mego

2

JavaScript (ES6), 106 byte

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')

Spiegazione

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
  `)

Test


1

Risposta non concorrenziale - Bash + coreutils, 55

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

"Le funzioni di analisi / formattazione della data sono comunque consentite" - Presumo che ciò significhi che l' dateutilità è consentita.

L'input viene letto dalla riga di comando, ad es .:

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

Questo non è competitivo perché il comando date si espande in qualcosa del genere che sta aggiungendo un numero di giorni:

date -d1-3-1+42day +%-m/%-d

È consentito a condizione che non stia facendo nulla di simile date.add(875)per aumentare la data di 875 giorni. Questo è principalmente quello che stavo cercando.
geokavel,

@geokavel oh, capisco. Il datecomando completamente esteso qui è date -d1-3-1+42day +%-m/%-d, quindi sta facendo esattamente questo. Immagino che questa sia una risposta non competitiva quindi :(
Digital Trauma,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.