Ngày nào lại là ngày đó?


10

Trên trang web của tôi, người dùng nhập ngày sinh của họ theo kiểu xx.xx.xx- ba số có hai chữ số được phân tách bằng dấu chấm. Thật không may, tôi quên nói với người dùng chính xác định dạng sử dụng. Tất cả những gì tôi biết là một phần được sử dụng cho tháng, một phần cho ngày và một phần cho năm. Năm chắc chắn là vào thế kỷ 20 (1900-1999), vì vậy định dạng 31.05.75có nghĩa 31 May 1975. Ngoài ra, tôi cho rằng tất cả mọi người sử dụng lịch Gregorian hoặc Julian.

Bây giờ, tôi muốn đi qua cơ sở dữ liệu của mình để dọn dẹp mớ hỗn độn. Tôi muốn bắt đầu bằng cách giao dịch với người dùng với những ngày mơ hồ nhất, đó là những ngày mà phạm vi ngày có thể là lớn nhất.

Ví dụ: ngày 08.27.53có nghĩa là 27 August 1953trong lịch Gregorian hoặc Julian. Ngày trong lịch Julian là 13 ngày sau đó, vì vậy phạm vi chỉ là 13 days.

Ngược lại, ký hiệu 01.05.12có thể đề cập đến nhiều ngày có thể. Sớm nhất là 12 May 1901 (Gregorian), và mới nhất là 1 May 1912 (Julian). Phạm vi là 4020 days.

Quy tắc

  • Đầu vào là một chuỗi trong định dạng xx.xx.xx, trong đó mỗi trường có hai chữ số và không có đệm.
  • Đầu ra là số ngày trong phạm vi.
  • Bạn có thể cho rằng đầu vào sẽ luôn là một ngày hợp lệ.
  • Bạn không được sử dụng bất kỳ chức năng ngày hoặc lịch tích hợp nào.
  • Mã ngắn nhất (tính bằng byte) thắng.

Tủ thử

  • 01.00.31 => 12
  • 29.00.02=> 0(Khả năng duy nhất là 29 February 1900 (Julian))
  • 04.30.00 => 13
  • 06.12.15 => 3291

5, May 1975được cho là 31st? Ngoài ra, chúng ta có phải tính đến năm nhuận không?
Maltysen

@Maltysen Có, đã sửa. Đúng.
Ypnypn

Tại sao nó không thể ở thế kỷ 21?
ElefantPhace

@ElefantPhace Các quy tắc nêu rõ rằng thế kỷ 20 được giả định; nếu không sẽ không có ngày tối đa.
Ypnypn

Câu trả lời:


6

Bình thường, 118 byte

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

Dùng thử trực tuyến: Trình diễn hoặc Test Suite .

Kiến thức cần thiết về lịch Julian và Gregorian

Lịch Julian và Gregorian khá giống nhau. Mỗi lịch chia một năm thành 12 tháng, mỗi tháng chứa 28-31 ngày. Những ngày chính xác trong một tháng là [31, 28/29 (depends on leap year), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]. Sự khác biệt duy nhất giữa các lịch là định nghĩa của một năm nhuận. Trong Lịch Julian, bất kỳ năm nào chia hết cho 4 là một năm nhuận. Lịch Gregorian cụ thể hơn một chút. Bất kỳ năm nào chia hết cho 4 là một năm nhuận, ngoại trừ năm chia hết cho 100 và không chia hết cho 400.

Vì vậy, trong thế kỷ 20 chỉ có một năm là khác nhau. Năm 1900, là một năm nhuận trong Lịch Julian, nhưng không phải là năm nhuận trong Lịch Gregorian. Vì vậy, ngày duy nhất, tồn tại trong một lịch nhưng không có trong lịch khác là ngày 29.02.1900.

Do định nghĩa năm nhuận khác nhau, có một sự khác biệt giữa một ngày trong Lịch Julian và Lịch Gregorian. Chênh lệch 12 ngày cho một ngày trước 29.02.1900và 13 ngày chênh lệch cho các ngày sau 29.02.1900.

Mã giả đơn giản hóa

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

Giải thích mã chi tiết

Phần đầu tiên M++28@j15973358 4G&qG2!%H4xác định hàm g(G,H), tính toán số ngày trong tháng Gcủa một năm Htrong Lịch 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)

Và phần tiếp theo chỉ là vòng lặp for và ifs. Lưu ý rằng tôi giải thích Ntrong định dạng (month, year, day). Chỉ vì nó tiết kiệm một số 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))

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

Hãy thử trực tuyến!

298 byte khi dấu cách, dòng mới và nhận xét bị xóa.

Các dòng 1-4 khởi tạo (nếu không được thực hiện) %g%jbăm trong đó các giá trị là số ngày của Gregorian và Julian tương ứng tính từ Jaunary 1st 1900 đến 31/12/1999.

Dòng 5 đặt ngày đầu vào thành $ 1, $ 2 và $ 3.

Dòng 9 liệt kê tất cả sáu hoán vị của ba số đầu vào.

Dòng 8 chuyển đổi sáu số đó thành hai số mỗi số, số ngày Gregorian và Julian, nhưng chỉ những người là ngày hợp lệ.

Dòng 7 đảm bảo điều đó, nó lọc ra các số ngày không tồn tại.

Dòng 6 sắp xếp danh sách các số ngày hợp lệ từ nhỏ nhất đến lớn nhất.

Dòng 10 trả về sau đó chênh lệch giữa cuối cùng và đầu tiên (tối đa và tối thiểu), đó là phạm vi mong muốn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.