Vergessener Realms-Datumsrechner

18

Lassen Sie uns mit einem fiktiven Kalender arbeiten, um die Wettbewerbsbedingungen zwischen Sprachen mit und ohne eingebaute Datumsbibliotheken auszugleichen. Die Vergessenen Reiche sind ein ( das? ) Kampagneneinstellung für Dungeons & Dragons. Natürlich hat jeder seinen eigenen Kalender.

Der Kalender von Harptos

Praktischerweise hat ein Jahr in den Vergessenen Reichen auch 365 Tage. Darüber hinaus hat der Kalender auch 12 Monate. Hier wird es jedoch interessant. Jeder Monat ist genau 30 Tage lang. Die restlichen 5 Tage sind Feiertage, die zwischen den Monaten liegen. Hier sind die Monate und Feiertage in Reihenfolge (mit eingerückten Feiertagen):

1   Deepwinter
        Midwinter
2   The Claw of Winter
3   The Claw of the Sunsets
4   The Claw of the Storms
        Greengrass
5   The Melting
6   The Time of Flowers
7   Summertide
        Midsummer
        [Shieldmeet]
8   Highsun
9   The Fading
        Highharvestide
10  Leaffall
11  The Rotting
        The Feast of the Moon
12  The Drawing Down

Beachten Sie, dass ich einen sechsten Feiertag in Klammern eingefügt habe. Dies ist der Schalttag, der nur alle vier Jahre stattfindet (ja, das ist es - es gibt keine zusätzlichen Spielereien mit den Jahrhunderten).

Randnotiz zu Monatsnamen: Jeder Monat hat einen formalen und einen gemeinsamen Namen. Das Obige sind die gebräuchlichen Namen. Ich habe diese ausgewählt, weil ich denke, dass sie eine interessantere Komprimierung ermöglichen.

Es gibt mehrere Nummerierungen der Jahre, aber die am weitesten verbreitete ist Dalereckoning , abgekürzt auf DR . (Außerdem hat jedes Jahr einen oder mehrere Namen , aber wir werden uns nicht darum kümmern.)

Die Komponenten eines Datums sollten durch ein Komma und ein Leerzeichen getrennt werden. Alles in allem könnte ein gültiges Datum so aussehen:

4, The Melting, 1491 DR

oder

Shieldmeet, 1464 DR

Beachten Sie, dass für die Feiertage keine Tagesnummer vorhanden ist. (Ich nehme an, 4th of The Meltingdass es für die Tage der Monate schöner wäre, aber ich möchte keine Ordnungszahlen hinein ziehen.)

Fußnote: Ich kam auf diese Idee, als sich xnor beschwerte, dass jede einzelne Datumsherausforderung die Schaltjahrberechnung erfordert. Ich habe es nicht vollständig beseitigt, aber zumindest ist es nur ein einziges Modulo in diesem Kalender.

Die Herausforderung

Wenn ein gültiges Datum des Harptos-Kalenders sowie eine Ganzzahl angegeben sind D, geben Sie das Datum DTage später aus. Beachten Sie, dass Ddies negativ sein kann. In diesem Fall sollten Sie das Datum DTage früher zurückgeben.

Sie können ein Programm oder eine Funktion schreiben, indem Sie eine Eingabe über STDIN (oder die nächstgelegene Alternative), ein Befehlszeilenargument oder ein Funktionsargument vornehmen und das Ergebnis über STDOUT (oder die nächstgelegene Alternative), einen Funktionsrückgabewert oder einen Funktionsparameter (out) ausgeben.

Sie können davon ausgehen, dass das Jahr positiv ist und weniger als 2000.

Es gelten die Standardregeln für .

Testfälle

Die ersten rund ein Dutzend Testfälle sollten alle Randfälle rund um Feiertage und Schaltjahre testen. Im nächsten Satz soll getestet werden, dass Bereiche über mehrere Jahre hinweg arbeiten und alle Monate und Feiertage implementiert wurden. In der zweiten Hälfte sind wieder alle Testfälle gleich, jedoch mit negativen Offsets.

"30, Summertide, 1491 DR" 1                 => "Midsummer, 1491 DR"
"30, Summertide, 1491 DR" 2                 => "1, Highsun, 1491 DR"
"Midsummer, 1491 DR" 1                      => "1, Highsun, 1491 DR"
"30, Summertide, 1492 DR" 1                 => "Midsummer, 1492 DR"
"30, Summertide, 1492 DR" 2                 => "Shieldmeet, 1492 DR"
"30, Summertide, 1492 DR" 3                 => "1, Highsun, 1492 DR"
"Midsummer, 1492 DR" 1                      => "Shieldmeet, 1492 DR"
"Midsummer, 1492 DR" 2                      => "1, Highsun, 1492 DR"
"Shieldmeet, 1492 DR" 1                     => "1, Highsun, 1492 DR"
"1, Highsun, 1490 DR" 365                   => "1, Highsun, 1491 DR"
"1, Highsun, 1491 DR" 365                   => "Shieldmeet, 1492 DR"
"Shieldmeet, 1492 DR" 365                   => "Midsummer, 1493 DR"
"Midsummer, 1493 DR" 365                    => "Midsummer, 1494 DR"
"Shieldmeet, 1500 DR" 365                   => "Midsummer, 1501 DR"

"14, Deepwinter, 654 DR" 5069               => "The Feast of the Moon, 667 DR"
"Midwinter, 17 DR" 7897                     => "15, The Fading, 38 DR"
"3, The Claw of Winter, 1000 DR" 813        => "25, The Claw of the Storms, 1002 DR"
"Greengrass, 5 DR" 26246                    => "9, The Claw of the Sunsets, 77 DR"
"30, The Melting, 321 DR" 394               => "29, The Time of Flowers, 322 DR"
"17, The Time of Flowers, 867 DR" 13579     => "20, Highsun, 904 DR"
"Highharvestide, 1814 DR" 456               => "30, The Drawing Down, 1815 DR"
"23, The Rotting, 1814 DR" 3616             => "16, Leaffall, 1824 DR"
"1, Deepwinter, 1 DR" 730499                => "30, The Drawing Down, 2000 DR"

"Midsummer, 1491 DR" -1                     => "30, Summertide, 1491 DR"
"1, Highsun, 1491 DR" -2                    => "30, Summertide, 1491 DR"
"1, Highsun, 1491 DR" -1                    => "Midsummer, 1491 DR"
"Midsummer, 1492 DR" -1                     => "30, Summertide, 1492 DR"
"Shieldmeet, 1492 DR" -2                    => "30, Summertide, 1492 DR"
"1, Highsun, 1492 DR" -3                    => "30, Summertide, 1492 DR"
"Shieldmeet, 1492 DR" -1                    => "Midsummer, 1492 DR"
"1, Highsun, 1492 DR" -2                    => "Midsummer, 1492 DR"
"1, Highsun, 1492 DR" -1                    => "Shieldmeet, 1492 DR"
"1, Highsun, 1491 DR" -365                  => "1, Highsun, 1490 DR"
"Shieldmeet, 1492 DR" -365                  => "1, Highsun, 1491 DR"
"Midsummer, 1493 DR" -365                   => "Shieldmeet, 1492 DR"
"Midsummer, 1494 DR" -365                   => "Midsummer, 1493 DR"
"Midsummer, 1501 DR" -365                   => "Shieldmeet, 1500 DR"

"The Feast of the Moon, 667 DR" -5069       => "14, Deepwinter, 654 DR"
"15, The Fading, 38 DR" -7897               => "Midwinter, 17 DR"
"25, The Claw of the Storms, 1002 DR" -813  => "3, The Claw of Winter, 1000 DR"
"9, The Claw of the Sunsets, 77 DR" -26246  => "Greengrass, 5 DR"
"29, The Time of Flowers, 322 DR" -394      => "30, The Melting, 321 DR"
"20, Highsun, 904 DR" -13579                => "17, The Time of Flowers, 867 DR"
"30, The Drawing Down, 1815 DR" -456        => "Highharvestide, 1814 DR"
"16, Leaffall, 1824 DR" -3616               => "23, The Rotting, 1814 DR"
"30, The Drawing Down, 2000 DR" -730499     => "1, Deepwinter, 1 DR"
Martin Ender
quelle
1
DragonLance ist eine weitere wichtige Einstellung für D & D-Kampagnen. Ich kann mich nur an die drei Monde erinnern, deren Umlaufbahnen in einem Nachschlagewerk detailliert erklärt wurden.
CJ Dennis

Antworten:

5

Ruby, 543 523 521 498 511 509 Bytes

Um mehr Antworten auf diese Frage zu erhalten, werde ich eine Ruby-Version meiner Python-Antwort veröffentlichen, da ich angenommen habe, dass sie kürzer sein würde. Diese Antwort ist kürzer, aber nicht viel. Kannst du es besser machen?

Edit: Mit Dank an Martin Büttner und seinem Vorschlag hier .

Edit: Ich habe die "Anzahl der Tage in einem Monat" -Liste erheblich gesenkt.

Bearbeiten: Beim Golfspielen, wie ich d[10]=r%4<1?1:0es d[10]=0**(r%4)für ein Byte gemacht habe, ist mir aufgefallen, dass ich beim Golfspielen einen Fehler entdeckt habe d, nämlich die Anzahl der Tage, die Shieldmeet aus Versehen 30 Tage hatte. Und so ist die Byteanzahl zurückgekehrt. Ich werde auch die Python-Antwort bearbeiten, um diesen Fehler dort zu beheben.

Edit: Ich habe vergessen, dass Funktionen in dieser Frage nicht benannt werden müssen.

->s,n{x=s[0..-4].split(", ");x=x[2]?x:[1,*x];t=(["Deepwinter,Midwinter","Winter","Sunsets","the Storms,Greengrass,The Melting,The Time of Flowers,Summertide,Midsummer,Shieldmeet,Highsun,The Fading,Highharvestide,Leaffall,The Rotting,The Feast of the Moon,The Drawing Down"]*',The Claw of ').split(?,);p,q,r=x[0].to_i+n,t.index(x[1]),x[2].to_i;d=[30,1,30,30]*4+[1,30];d[10]=0**(r%4);(a=p<1?1:-1;q=(q-a)%18;p+=a*d[a<0?q-1:q];r-=a*0**q;d[10]=0**(r%4))until(1..d[q])===p;z=d[q]<2?[t[q],r]:[p,t[q],r];z*", "+" DR"}

Ungolfed:

def h(s,n)
  x=s[0..-4].split(", ")
  x=x[2]?x:[1,*x]
  t=["Deepwinter,Midwinter","Winter","Sunsets","the Storms,Greengrass,The Melting,The Time of Flowers,Summertide,Midsummer,Shieldmeet,Highsun,The Fading,Highharvestide,Leaffall,The Rotting,The Feast of the Moon,The Drawing Down"]
  t=t*',The Claw of '           # turns the above array into a string with "Claw"s inserted
  t=t.split(?,)                 # then splits that string back up again by ","
  p=x[0].to_i+n
  q=t.index(x[1])
  r=x[2].to_i
  d=[30,1,30,30]*4+[1,30]
  d[10]=0**(r%4)
  until(1..d[q])===p
    a=p<1?1:-1
    q=(q-a)%18
    p+=a*d[a<0?q-1:q]
    r-=a*0**q
    d[10]=0**(r%4)
  end
  z=d[q]<2?[t[q],r]:[p,t[q],r]  # putting z=[t[q],r] on another line saved me no bytes
  z*", "+" DR"
end
Sherlock9
quelle
5

Python 3, 712 652 636 567 563 552 550 548 529 540 Bytes

Endlich fand ich Zeit, eine Antwort auf diese ausgezeichnete Frage zu schreiben. Es ist noch nicht sehr erfolgreich (die Liste der Monatsnamen und der Anzahl der Tage ist in diesem Fall besonders ungeheuerlich und die Tatsache, dass für die Bearbeitung von Negativen Deine separate while-Schleife erforderlich ist ), aber es ist zumindest eine Antwort.

Bearbeiten: Beheben eines Fehlers

def h(s,n):
 x=s[:-3].split(", ");x=[1]*(len(x)<3)+x;t="Deepwinter,Midwinter,The Claw of Winter,The Claw of the Sunsets,The Claw of the Storms,Greengrass,The Melting,The Time of Flowers,Summertide,Midsummer,Shieldmeet,Highsun,The Fading,Highharvestide,Leaffall,The Rotting,The Feast of the Moon,The Drawing Down".split(",");p,q,r=int(x[0])+n,t.index(x[1]),int(x[2]);d=[30,1,30,30]*4+[1,30];d[10]=r%4<1
 while p>d[q]or p<1:a=[-1,1][p<1];q=(q-a)%18;p+=a*d[q-(a<0)];r-=a*0**q;d[10]=r%4<1
 return', '.join([str(p)]*(d[q]>2)+[t[q],str(r)])+" DR"

Ungolfed:

def harptos(date, num):
    t = "Deepwinter,Midwinter,The Claw of Winter,The Claw of the Sunsets,The Claw of the Storms,Greengrass,The Melting,The Time of Flowers,Summertide,Midsummer,Shieldmeet,Highsun,The Fading,Highharvestide,Leaffall,The Rotting,The Feast of the Moon,The Drawing Down"
    t = t.split(",")        # split up the names of the months
    x = date[:-3]           # removes " DR"
    x = x.split(", ")
    if len(x) < 3:
        x = [1] + x         # if we have two items (holiday), append a "day of the month"
    p = int(x[0]) + num     # initialize the "date" by adding num to it
    q = t.index(x[1])
    r = int(x[2])
    d=[30,1,30,30]*4+[1,30] # all the month lengths
    d[10] = r%4 < 1         # leap year toggle
    while p > d[q]:         # while the "date" > the number of days in the current month
        p -= d[q]           # decrement by number of days in current month
        q = (q+1)%18        # increment month
        r += 0**q           # increment year if the incremented month == the first month
        d[10] = r%4 < 1     # leap year toggle
    while p < 1:            # while the "date" is negative
        q = (q-1)%18        # decrement month first
        p += d[q]           # add the number of days in the decremented month
        r -= 0**q            # decrement year if the decremented month == the first month
        d[10] = r%4 < 1     # leap year toggle
    m = [t[q],str(r)]       # start the result array
    if d[q] > 2:
        m = [str(p)] + m    # if the month is NOT a holiday, add the day
    return ", ".join(m) + " DR"
Sherlock9
quelle