Rollover-Kalender

17

Dies ist inspiriert von einer der Fragen von Downgoat in Sandbox, in der ich vorgeschlagen habe, den 31. April als Pi-Tag für Personen mit Tag / Monat-Format aufzunehmen, nur damit er mir mitteilt, dass es keinen 31. April gibt!

Bei einer Datumszeichenfolge im Format Monat / Tag , die möglicherweise ungültig ist, geben Sie das richtige Datum mit dem Rollover aus. (Zuerst den Monat und dann den Tag verschieben).

Beispiele:

"15/43" - Dies ist der 43. Tag des 15. Monats. Zuerst verschieben wir den Monat auf das nächste Jahr, sodass wir am Ende 3 (März) haben. Da der März nur 31 Tage hat, verlängern wir die Verlängerungstage auf April, sodass wir das aktuelle Datum als "4/12" (12. April) ausgeben .

"3/16" - Dies ist ein gültiges Datum (16. März). Geben Sie es so zurück, wie es ist.

"12/64" - Ah, so viele schöne Erinnerungen vom 64. Dezember ... Der Dezember hat 31 Tage, der Januar hat 31 Tage, also meine ich wirklich "2/2" (2. Februar).

"19/99" - Zuerst wird die 19 eine 7 (Juli). Juli hat 31 Tage, August hat 31 Tage, September hat 30 Tage, die Ausgabe ist also "10/7" (7. Oktober).

"1/99999" - Ein Jahr hat 365 Tage. 99999 (Mod 365) = 354. Der 354. Tag des Jahres ist "12/20" .

"9999999/10" - Anscheinend 9999999 (Mod 12) = 3, dies ist also "3/10" (10. März).

Kriterien:

Der Eingabemonat ist eine Ganzzahl> 0. Der Eingabetag ist eine Ganzzahl> 0. Das Jahr muss nie angegeben werden, da keine Schaltjahre zu behandeln sind.

Aktualisieren:

Da ich der Meinung bin, dass dies die Herausforderung übermäßig vereinfachen würde, sind Kalenderfunktionen wie die in der Java Calendar- Klasse gesperrt. Datumsanalyse- / Formatierungsfunktionen sind jedoch weiterhin zulässig.

Geokavel
quelle
1
Verbunden.
Katze
1
Ein weiterer wichtiger Testfall wäre ein Testfall mit genügend Tagen für einen Zeitraum von mehr als 8 Jahren, sodass Antworten, die integrierte Funktionen verwenden, den integrierten Funktionen mit Schaltjahren Aufmerksamkeit schenken müssen.
Martin Ender
Oh, das beantwortet das ... Ich wollte gerade eine Mathematica-Antwort posten, die eine eingebaute Funktion verwendet. : /
Martin Ender
@ Martin Sorry darüber;).
Geokavel
Als Referenz war die Mathematica-Lösung immer noch 90 Byte lang (obwohl dies massiv von der Zeichenfolgenverarbeitung dominiert wurde). Wer dennoch einen solchen Testfall hinzufügen möchte, 1/99999sollte nachgeben, 12/19denke ich.
Martin Ender

Antworten:

11

LabVIEW, 32 LabVIEW-Grundelemente

Eumel
quelle
Das war schnell.
Addison Crump
Können Sie mir versichern, dass hier keine Kalenderfunktionen verwendet werden?
Geokavel
Das Gute an LabVIEW ist, dass es im Grunde genommen so aussieht, wie es aussieht. Als erstes scannt die Box Zahlen aus einem String 2 Modulos, die Box ist eine Schaltergehäusestruktur, die 28, 30 oder 31 ausgibt und dann wieder als String zusammengesetzt wird.
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;}

Bearbeiten : Wurde behoben, um für Fälle wie 24/1, 36/1 usw. zu funktionieren und ein wenig Golf zu spielen. Vielen Dank für die Kommentare, es gibt mehrere Orte, die ich ein bisschen gespeichert habe!

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;
}
DrewJordan
quelle
Zuallererst: Willkommen in der Community! Ich würde vermuten, Sie könnten einige Bytes sparen, indem Sie das Wörterbuch in einer Schleife zuweisen oder eine Switch-Funktion verwenden (hier jedoch kein C # -Pro). Auch das direkte Drucken von ´m + "/" + d´ könnte ein wenig helfen. Und zuletzt (dies könnte funktionieren oder nicht) mit char * anstelle von string in den Argumenten.
Eumel
Dies schlägt in bestimmten Testfällen fehl, z 24/1.
LegionMammal978
@Eumel danke! Direktes Drucken verwendet, Console.Writewas mehr ist als return, und in C # würde ich char[]als Ersatz für verwenden string, aber es ist die gleiche Menge an Zeichen, und macht das Aufteilen auf das /problematischere. Ihre Anmerkung zum Wörterbuch hat mich jedoch zu einer viel besseren Version geführt!
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="/")

Ermitteln Sie den Monat, indem Sie ihn durch 12 teilen. Entfernen Sie dann die Anzahl der Tage des aktuellen Monats, bis Sie eine negative Zahl erhalten. Kehren Sie den letzten Schritt um und drucken Sie.

In mehreren Zeilen (muss eine Datei verwenden und als Quelle dienen):

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
quelle
Dies ist die Botschaft , die ich erhalten , wenn Sie versuchen Ihr Programm in R laufen: pastebin.com/dPh1n64a
geokavel
Seltsam, ich werde es später noch einmal überprüfen
Tensibai
Ich habe auch diese Nachricht erhalten. Ihr Programm scheint mit einigen Monaten Probleme zu haben. Ansonsten läuft es. pastebin.com/g3BCUDi8
geokavel
Danke für die Rückmeldung. Eigentlich bin ich unterwegs, ich werde es korrigieren
Tensibai
1
@Tensibai ja du hast recht, mein böser (ich hätte daran denken sollen, dass die fehlermeldung besagt, dass sie "einen echten" erwartet).
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 unterstützt Rollover fast nur mit Anweisungen zum Parsen und Formatieren von Datumsangaben. Beispielsweise:

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

Sobald jedoch eine der beiden Zahlen größer als 100 wird, lehnt PHP das Parsen ab und gibt einen Fehler zurück (wahrscheinlich aus einem beliebigen Grund). Die Theorie mit dieser Antwort ist also, sie wieder dahin zu bringen, wo PHP sie parsen wird, und sie dann zu übermitteln 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");

Probieren Sie es online aus

nickb
quelle
1
Sie müssen mir eine Möglichkeit geben, die Datumszeichenfolge einzugeben oder sie zu einer Funktion zu machen.
Geokavel
GET-Parameter sind als Eingabemethode in PHP nicht zulässig . Sie müssen dies entweder zu einer Funktion machen und die Eingabe als Funktionsparameter übergeben oder eine Eingabe von $argvoder STDIN erhalten.
Mego
@Mego Jeeze, gib mir etwas Zeit, um meine Antwort zu aktualisieren, da das OP keine Eingabevoraussetzungen angab - es ist einfach genug, um zu wechseln $t, $argv[1]und liest jetzt von der Befehlszeileneingabe.
Nickb
Die OP-Anforderungen für die Eingabe sind irrelevant. Wir haben eine Liste der akzeptablen Standard-E / A-Methoden (die ich verlinkt habe), damit die Herausforderungsautoren sie nicht bei jeder Herausforderung angeben müssen.
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')

Erläuterung

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

Prüfung

user81655
quelle
1

Nicht konkurrierende Antwort - Bash + Coreutils, 55

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

"Datumsanalyse- / Formatierungsfunktionen sind jedoch weiterhin zulässig" - Ich gehe davon aus, dass dies bedeutet, dass das dateDienstprogramm zulässig ist.

Die Eingabe wird von der Kommandozeile gelesen, zB:

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

Dies ist nicht konkurrierend, da der Datumsbefehl zu etwas erweitert wird, das eine Anzahl von Tagen hinzufügt:

date -d1-3-1+42day +%-m/%-d
Digitales Trauma
quelle
Es ist zulässig, solange date.add(875)das Datum nicht um 875 Tage erhöht wird. Das ist meistens das, wonach ich gesucht habe.
Geokavel
@geokavel oh, ich verstehe. Der vollständig erweiterte dateBefehl ist hier date -d1-3-1+42day +%-m/%-d, also macht er genau das. Ich denke, das ist dann eine nicht konkurrierende Antwort :(
Digital Trauma