วันที่อะไรอีกครั้ง


10

ในเว็บไซต์ของฉันผู้ใช้ป้อนวันเดือนปีเกิดในรูปแบบxx.xx.xx- ตัวเลขสองหลักสามตัวคั่นด้วยจุด น่าเสียดายที่ฉันลืมบอกผู้ใช้ว่าต้องใช้รูปแบบใด ทั้งหมดที่ฉันรู้คือส่วนหนึ่งใช้สำหรับเดือนหนึ่งสำหรับวันที่และอีกหนึ่งสำหรับปี ปีแน่นอนในศตวรรษที่ 20 (1900-1999) ดังนั้นรูปแบบวิธีการ31.05.75 31 May 1975นอกจากนี้ฉันสมมติว่าทุกคนใช้ปฏิทินเกรโกเรียนหรือจูเลียน

ตอนนี้ฉันต้องการผ่านฐานข้อมูลของฉันเพื่อล้างความยุ่งเหยิง ฉันต้องการเริ่มต้นด้วยการจัดการกับผู้ใช้ที่มีวันที่คลุมเครือมากที่สุดนั่นคือผู้ที่ช่วงวันที่เป็นไปได้ที่ใหญ่ที่สุด

ตัวอย่างเช่นวันที่08.27.53หมายถึง27 August 1953ในปฏิทิน Gregorian หรือ Julian วันที่ในปฏิทินจูเลียนเป็น 13 13 daysวันในภายหลังดังนั้นช่วงเป็นเพียง

ในทางตรงกันข้ามสัญกรณ์01.05.12สามารถอ้างถึงวันที่เป็นไปได้มากมาย เร็วที่สุดเท่าที่เป็นและล่าสุดคือ12 May 1901 (Gregorian) ช่วงคือ1 May 1912 (Julian)4020 days

กฎระเบียบ

  • อินพุตเป็นสตริงในรูปแบบxx.xx.xxโดยที่แต่ละฟิลด์เป็นตัวเลขสองหลักและไม่มีการเติมเบาะ
  • เอาต์พุตคือจำนวนวันในช่วง
  • คุณสามารถสันนิษฐานได้ว่าอินพุตจะเป็นวันที่ที่ถูกต้องเสมอ
  • คุณไม่สามารถใช้ฟังก์ชันวันที่หรือปฏิทินในตัว
  • รหัสที่สั้นที่สุด (เป็นไบต์) ชนะ

Testcases

  • 01.00.31 => 12
  • 29.00.02=> 0(ความเป็นไปได้เพียงอย่างเดียวคือ29 February 1900 (Julian))
  • 04.30.00 => 13
  • 06.12.15 => 3291

คือ5, May 1975ควรจะเป็น31st? นอกจากนี้เราต้องพิจารณาเป็นปีอธิกสุรทินด้วยหรือไม่
Maltysen

@Maltysen ใช่แก้ไขแล้ว ใช่.
Ypnypn

ทำไมในศตวรรษที่ 21 ไม่ได้?
ElefantPhace

@ElefantPhace กฎระบุว่าสันนิษฐานว่าศตวรรษที่ 20; มิฉะนั้นจะไม่มีวันที่สูงสุด
Ypnypn

คำตอบ:


6

Pyth, 118 ไบต์

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

ลองมันออนไลน์: สาธิตหรือTest Suite

ความรู้ที่จำเป็นของ Julian และ Gregorian Calendars

ปฏิทิน Julian และ Gregorian ค่อนข้างคล้ายกัน แต่ละปฏิทินแบ่งปีเป็น 12 เดือนโดยแต่ละปฏิทินประกอบด้วย 28-31 วัน [31, 28/29 (depends on leap year), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]วันที่แน่นอนในเดือนมี ข้อแตกต่างระหว่างปฏิทินคือคำจำกัดความของปีอธิกสุรทิน ในปฏิทินจูเลียนปีที่หารด้วย 4 จะเป็นปีอธิกสุรทิน ปฏิทินเกรกอเรียนมีความเฉพาะเจาะจงมากกว่านี้เล็กน้อย ปีใด ๆ ที่หารด้วย 4 คือปีอธิกสุรทินยกเว้นปีหารด้วย 100 และไม่หารด้วย 400

ดังนั้นในศตวรรษที่ 20 มีเพียงหนึ่งปีเท่านั้นที่แตกต่างกัน ปี 1900 ซึ่งเป็นปีอธิกสุรทินในปฏิทินจูเลียน แต่ไม่ใช่ปีอธิกสุรทินในปฏิทินเกรกอเรียน ดังนั้นวันเท่านั้นที่มีอยู่ในปฏิทินหนึ่ง แต่ไม่ได้อยู่ในปฏิทินอื่น ๆ 29.02.1900เป็นวันที่

เนื่องจากความหมายปีอธิกสุรทินที่แตกต่างกันมีความแตกต่างระหว่างวันที่ในปฏิทินจูเลียนและปฏิทินเกรกอเรียน 12 วันความแตกต่างสำหรับวันก่อนที่29.02.190013 29.02.1900และวันที่แตกต่างกันสำหรับวันหลังจากที่

ย่อหลอกรหัส

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

คำอธิบายรหัสโดยละเอียด

ส่วนแรกM++28@j15973358 4G&qG2!%H4กำหนดฟังก์ชั่นg(G,H)ซึ่งคำนวณจำนวนวันในเดือนGของปีHในปฏิทินจูเลียน

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)

และส่วนถัดไปเป็นเพียงการวนรอบและส่วนอื่น ๆ แจ้งให้ทราบว่าผมตีความในรูปแบบN (month, year, day)เพียงเพราะมันช่วยประหยัดไบต์

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 ไบต์

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

ลองออนไลน์!

298 ไบต์เมื่อเว้นวรรคบรรทัดใหม่และข้อคิดเห็นถูกลบ

บรรทัดที่ 1-4 เริ่มต้น (ถ้าไม่ได้ทำ) %gและ%jแฮชที่ค่าเป็นตัวเลขวันเกรโกเรียนและจูเลียนตามนับจาก Jaunary 1 1900 ถึง 31 ธันวาคม 1999

บรรทัด 5 ใส่วันที่ป้อนเข้าเป็น $ 1, $ 2 และ $ 3

บรรทัดที่ 9 แสดงการเปลี่ยนลำดับทั้งหกของหมายเลขอินพุตทั้งสาม

บรรทัดที่ 8 แปลงตัวเลขหกตัวนั้นเป็นสองตัวเลขแต่ละตัวคือตัวเลขเกรกอเรียนและจูเลียน แต่เป็นเฉพาะวันที่ที่ถูกต้องเท่านั้น

บรรทัด 7 ตรวจสอบให้แน่ใจว่ามันกรองหมายเลขวันที่ไม่มีอยู่

บรรทัดที่ 6 เรียงลำดับรายการหมายเลขวันที่ที่ถูกต้องจากเล็กที่สุดไปหามากที่สุด

บรรทัด 10 จะส่งคืนความแตกต่างระหว่างช่วงสุดท้ายและช่วงแรก (สูงสุดและต่ำสุด) ซึ่งเป็นช่วงที่ต้องการ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.