Kalkulator tanggal Realm yang Terlupakan

18

Dalam upaya untuk meratakan lapangan bermain antara bahasa dengan pustaka tanggal bawaan dan yang tidak, mari kita bekerja dengan kalender fiksi. The Forgotten Realms adalah pengaturan kampanye ( the? ) Untuk Dungeons & Dragons. Tentu saja, masing-masing memiliki kalender sendiri.

Kalender Harpa

Mudahnya, setahun di Alam Lupa juga memiliki 365 hari. Selanjutnya, kalender juga memiliki 12 bulan. Namun, ini adalah hal yang menarik. Setiap bulan persis 30 hari panjang. 5 hari tersisa adalah hari libur yang jatuh di antara bulan-bulan. Berikut adalah bulan dan liburan secara berurutan (dengan lekukan liburan):

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

Perhatikan bahwa saya telah memasukkan libur keenam dalam kurung. Ini adalah hari kabisat yang hanya terjadi setiap empat tahun (ya, itu saja - tidak ada kejahatan tambahan selama berabad-abad).

Catatan samping tentang nama bulan: setiap bulan memiliki nama resmi dan umum. Di atas adalah nama umum. Saya memilih itu karena saya pikir mereka memungkinkan kompresi yang lebih menarik.

Ada beberapa penomoran tahun, tetapi yang paling luas adalah Dalereckoning , disingkat DR . (Juga, setiap tahun memiliki satu atau lebih nama , tapi kami tidak akan repot dengan itu.)

Komponen tanggal harus dipisahkan oleh koma dan spasi. Secara keseluruhan, tanggal yang valid mungkin terlihat seperti:

4, The Melting, 1491 DR

atau

Shieldmeet, 1464 DR

Perhatikan bahwa tidak ada nomor hari untuk liburan. (Saya kira 4th of The Meltingakan lebih baik untuk hari-hari bulan, tapi saya tidak ingin menyeret nomor urut ke dalam ini.)

Catatan Kaki: Saya membuat ini ketika xnor mengeluh bahwa setiap tantangan tanggal membutuhkan perhitungan tahun kabisat. Saya telah gagal menghilangkannya sepenuhnya, tetapi setidaknya itu hanya modulo tunggal dalam kalender ini.

Tantangan

Diberikan tanggal yang valid dari Kalender Harpa, serta bilangan bulat D, mengeluarkan tanggal Dbeberapa hari kemudian. Catatan yang Dmungkin negatif, dalam hal ini Anda harus mengembalikan tanggal Dhari sebelumnya.

Anda dapat menulis sebuah program atau fungsi, mengambil input melalui STDIN (atau alternatif terdekat), argumen baris perintah atau argumen fungsi dan mengeluarkan hasilnya melalui STDOUT (atau alternatif terdekat), nilai pengembalian fungsi atau parameter function (out).

Anda dapat berasumsi bahwa tahun itu positif dan kurang dari 2000.

Aturan standar berlaku.

Uji Kasus

Sekitar selusin kasus uji pertama harus menguji semua kasus tepi di sekitar hari libur dan tahun kabisat. Set berikutnya adalah untuk menguji bahwa rentang kerja beberapa tahun dan semua bulan dan hari libur telah dilaksanakan. Paruh kedua adalah semua test case yang sama lagi tetapi dengan offset negatif.

"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
sumber
1
DragonLance adalah pengaturan kampanye D & D utama lainnya. Saya tidak dapat mengingat banyak tentang kalender mereka kecuali tiga bulan mereka, orbitnya dijelaskan secara rinci dalam beberapa buku referensi.
CJ Dennis

Jawaban:

5

Ruby, 543 523 521 498 511 509 byte

Untuk mendorong lebih banyak jawaban untuk pertanyaan ini, saya akan memposting versi Ruby dari jawaban Python saya, karena saya pikir itu akan lebih pendek. Jawaban ini lebih pendek tetapi tidak banyak. Bisakah kamu berbuat lebih baik?

Sunting: Dengan terima kasih kepada Martin Büttner dan sarannya di sini .

Sunting: Saya mencatat "jumlah hari dalam sebulan" dengan sangat baik.

Edit: Sementara golf turun bagaimana saya ditangani d[10]=r%4<1?1:0untuk d[10]=0**(r%4)untuk byte, saya melihat aku memperkenalkan bug sementara bermain golf turun d, jumlah daftar hari, sehingga Shieldmeet memiliki 30 hari oleh kecelakaan. Jadi, jumlah byte telah kembali. Saya juga akan mengedit jawaban Python untuk memperbaiki bug ini di sana.

Sunting: Saya lupa bahwa fungsi tidak perlu disebutkan dalam pertanyaan ini.

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

Tidak Disatukan:

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
sumber
5

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

Akhirnya, saya menemukan waktu untuk menulis jawaban untuk pertanyaan yang sangat bagus ini. Itu belum sangat golf (daftar nama bulan dan jumlah hari sangat mengerikan dalam kasus ini , dan fakta bahwa penanganan negatif Dmemerlukan loop sementara yang terpisah ) tetapi setidaknya itu adalah jawaban.

Sunting: Memperbaiki bug

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"

Tidak Disatukan:

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
sumber