Tanggal berapa itu lagi?

10

Di situs web saya, pengguna memasukkan tanggal lahir dengan gaya xx.xx.xx- tiga angka dua digit yang dipisahkan oleh titik. Sayangnya, saya lupa memberi tahu pengguna format yang digunakan. Yang saya tahu adalah bahwa satu bagian digunakan untuk bulan itu, satu untuk tanggal, dan satu untuk tahun. Tahun pasti di abad ke-20 (1900-1999), jadi formatnya 31.05.75berarti 31 May 1975. Juga, saya berasumsi semua orang menggunakan kalender Gregorian atau Julian.

Sekarang, saya ingin membuka database saya untuk membersihkan kekacauan ini. Saya ingin memulai dengan berurusan dengan pengguna dengan tanggal yang paling ambigu, yaitu, di mana kisaran tanggal yang mungkin adalah yang terbesar.

Misalnya, tanggal 08.27.53berarti 27 August 1953dalam kalender Gregorian atau Julian. Tanggal dalam kalender Julian adalah 13 hari kemudian, jadi rentangnya adil 13 days.

Sebaliknya, notasi 01.05.12dapat merujuk pada banyak kemungkinan tanggal. Yang paling awal adalah 12 May 1901 (Gregorian), dan yang terbaru adalah 1 May 1912 (Julian). Kisarannya adalah 4020 days.

Aturan

  • Input adalah string dalam format xx.xx.xx, di mana setiap bidang adalah dua digit dan nol-empuk.
  • Output adalah jumlah hari dalam kisaran.
  • Anda dapat mengasumsikan bahwa input akan selalu menjadi tanggal yang valid.
  • Anda tidak boleh menggunakan fungsi tanggal atau kalender bawaan.
  • Kode terpendek (dalam byte) menang.

Testcases

  • 01.00.31 => 12
  • 29.00.02=> 0(Satu-satunya kemungkinan adalah 29 February 1900 (Julian))
  • 04.30.00 => 13
  • 06.12.15 => 3291
Ypnypn
sumber
Apakah 5, May 1975seharusnya 31st? Juga, apakah kita harus memperhitungkan tahun kabisat?
Maltysen
@Maltysen Ya, sudah diperbaiki. Iya.
Ypnypn
Mengapa itu tidak terjadi di abad ke-21?
ElefantPhace
@ElefantPhace Aturan menyatakan bahwa abad ke-20 diasumsikan; jika tidak, tidak akan ada tanggal maksimum.
Ypnypn

Jawaban:

6

Pyth, 118 byte

M++28@j15973358 4G&qG2!%H4FN.pmv>dqhd\0cz\.I&&&hN<hN13eN<eNhgFPNaYK+++*365JhtN/+3J4smghdJthNeNInK60aY-K+12>K60;-eSYhSY

Cobalah online: Demonstrasi atau Test Suite .

Pengetahuan yang diperlukan tentang Kalender Julian dan Gregorian

Kalender Julian dan Gregorian sangat mirip. Setiap kalender membagi satu tahun menjadi 12 bulan, masing-masing berisi 28-31 hari. Hari-hari yang tepat dalam sebulan adalah [31, 28/29 (depends on leap year), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]. Satu-satunya perbedaan antara kalender adalah definisi tahun kabisat. Dalam Kalender Julian setiap tahun yang dapat dibagi dengan 4 adalah tahun kabisat. Kalender Gregorian sedikit lebih spesifik. Setiap tahun yang habis dibagi 4 adalah tahun kabisat, kecuali tahun yang habis dibagi 100 dan tidak habis dibagi 400.

Jadi di abad ke-20 hanya satu tahun yang berbeda. Tahun 1900, yang merupakan tahun kabisat dalam Kalender Julian, tetapi bukan tahun kabisat dalam Kalender Gregorian. Jadi satu-satunya tanggal, yang ada di satu kalender tetapi tidak di kalender lainnya adalah hari 29.02.1900.

Karena definisi tahun kabisat yang berbeda, ada perbedaan antara tanggal di Kalender Julian dan Kalender Gregorian. Perbedaan 12 hari untuk tanggal sebelum 29.02.1900, dan 13 hari perbedaan untuk tanggal setelah 29.02.1900.

Kode Pseudo Sederhana

Y = []  # empty list
for each permutation N of the input date:
   if N is valid in the Julian Calendar:
      K = number of days since 0.01.1900
      append K to Y
      if K != 60:  # 60 would be the 29.02.1900
         L = K - (12 if K < 60 else 13) 
         append L to Y
print the difference between the largest and smallest value in Y

Penjelasan Kode Lengkap

Bagian pertama M++28@j15973358 4G&qG2!%H4mendefinisikan fungsi g(G,H), yang menghitung jumlah hari dalam sebulan Gdari setahun Hdi Kalender Julian.

M                            def g(G,H): return
      j15973358 4               convert 15973358 into base 4
     @           G              take the Gth element
  +28                           + 28
 +                &qG2!%H4      + (G == 2 and not H % 4)

Dan bagian selanjutnya hanyalah for for loop, dan ifs. Perhatikan bahwa saya menafsirkan Ndalam format (month, year, day). Hanya karena menghemat beberapa byte.

FN.pmv>dqhd\0cz\.
             cz\.        split input by "."
    mv>dqhd\0            map each d of ^ to: eval(d[d[0]=="0":])
FN.p                     for N in permutations(^):

I&&&hN<hN13eN<eNhgFPN   
I                          if 
    hN                        month != 0
   &                          and
      <hN13                   month < 13
  &                           and
           eN                 day != 0
 &                            and
             <eNhgFPN         day < 1 + g(month,year):

aYK+++*365JhtN/+3J4smghdJthNeN
          JhtN                    J = year
     +*365J   /+3J4               J*365 + (3 + J)/4
    +              smghdJthN      + sum(g(1+d,year) for d in [0, 1, ... month-2])
   +                        eN    + day
  K                               K = ^
aYK                               append K to Y

InK60aY-K+12>K60            
InK60                             if K != 60:
     aY-K+12>K60                    append K - (12 + (K > 60)) to Y

;-eSYhSY
;          end for loop
 -eSYhSY   print end(sorted(Y)) - head(sorted(Y))
Jakube
sumber
0

Perl 5 , 294 byte

sub f{map/(\d\d)(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])/             #1             
      &&$3<29+($2==2?!($1%4):2+($2/.88)%2)                        #2  
      &&($j{$_}=++$j+12)                                          #3
      &&$j!#1=60?$g{$_}=++$g:0,'000101'..'991231'if!%g;           #4
      pop=~/(\d\d).(\d\d).(\d\d)/;                                #5
      @n=sort{$a<=>$b}                                            #6
         grep$_,                                                  #7
         map{($j{$_},$g{$_})}                                     #8
         ("$1$2$3","$1$3$2","$2$1$3","$2$3$1","$3$1$2","$3$2$1"); #9
      $n[-1]-$n[0]}                                               #10

Cobalah online!

298 byte saat spasi, baris baru, dan komentar dihapus.

Baris 1-4 menginisialisasi (jika tidak dilakukan) %gdan %jhash di mana nilainya adalah angka hari Gregorian dan Julian yang dihitung dari Jaunary 1 1900 hingga 31 Desember 1999.

Baris 5 memasukkan tanggal input ke dalam $ 1, $ 2 dan $ 3.

Baris 9 mencantumkan semua enam permutasi dari ketiga nomor input tersebut.

Jalur 8 mengubah enam angka itu menjadi dua angka masing-masing, angka Gregorian dan hari Julian, tetapi hanya mereka yang merupakan tanggal yang valid.

Jalur 7 memastikan hal itu, menyaring nomor hari yang tidak ada.

Baris 6 mengurutkan daftar nomor tanggal yang valid dari yang terkecil hingga yang terbesar.

Jalur 10 mengembalikan lalu perbedaan antara yang terakhir dan yang pertama (maks dan min), yang merupakan rentang yang diinginkan.

Kjetil S.
sumber