คำนวณความแตกต่างระหว่างสองวัน


11

ปัญหาการจัดการวันที่อื่น: P

งาน

เขียนโปรแกรมหรือฟังก์ชั่นที่คำนวณความแตกต่างระหว่างวันที่สองวันที่กำหนดโดยผู้ใช้

อินพุตและเอาต์พุต

คล้ายกับก่อนหน้านี้หนึ่งปัจจัยการผลิตเป็นสองYYYYMMDDs, คั่นด้วยช่องว่าง, เครื่องหมายจุลภาคหรือเครื่องหมายลบ,-

ตัวอย่างของค่าอินพุต:

20100101-20010911
20110620-20121223
19000101 20101010
33330101,19960229
00010101 99991231

เอาท์พุทเป็นจำนวนเต็มซึ่งเป็นความแตกต่างระหว่างวันที่สองวัน

ยกตัวอย่างเช่นการป้อนข้อมูล20110101-20100101อัตราผลตอบแทน365และอัตราผลตอบแทน33320229 17000101596124

คุณสามารถทดสอบผลลัพธ์ ที่นี่ ที่นี่ (ดูความคิดเห็นของ rintaun ด้านล่าง) หากสองวันเหมือนกันโปรแกรมควรกลับ0มาถ้าวันนั้นถูกต้อง (ดูคะแนน )

การ จำกัด

แน่นอนคุณจะต้องไม่ใช้ใด ๆชนิดของฟังก์ชั่น / ระดับ / ... ซึ่งจะเกี่ยวข้องกับการประทับเวลาหรือวันและคุณควรใช้ปฏิทินเกรกอเรียน

คะแนน

หากรหัสของคุณไม่ได้ จำกัดscore = -∞อยู่

ค่าเริ่มต้นbonusคือ 1

  • หากรหัสของคุณทำงานโดยไม่คำนึงถึงคำสั่งของปัจจัยการผลิต (ตัวอย่างเช่น20100101,20110101ผลตอบแทน365หรือ)-365bonus+=1
  • หากรหัสของคุณสามารถจัดการกับปีที่ 0bonus+=0.5 ,
  • หากรหัสของคุณตระหนักถึงเดือนไม่ถูกต้อง (ระหว่างวันที่ 1 ~ 12) / วัน (ระหว่างวันที่ 1 ~ 31) เช่น20109901หรือ34720132และพิมพ์E(และยุติโปรแกรมหรือผลตอบแทนสิ่งที่ต้องการ)0bonus+=1
  • โดยไม่คำนึงถึงกฎข้างต้นถ้ารหัสของคุณตระหนักถึงวันที่ไม่ถูกต้องเช่น20100230, 20100229หรือ20111131, และพิมพ์E(และยุติโปรแกรมหรือผลตอบแทนสิ่งที่ต้องการ)0bonus+=1
  • โดยไม่คำนึงถึงข้างต้นทั้งสองกฎถ้ารหัสของคุณตระหนักถึงสายป้อนไม่ถูกต้องเช่น20100101|20100202หรือ2010010120100202และพิมพ์E(และยุติโปรแกรมหรือผลตอบแทนสิ่งที่ต้องการ)0bonus+=1

score = floor(-4.2*code.length/bonus). รหัสที่มีคะแนนสูงสุดชนะ หากรหัสสองอันดับแรกมีคะแนนเท่ากันรหัสนั้นก็จะเป็นโบนัสที่มีรางวัลสูงสุด หากรหัสสองอันดับแรกมีทั้งคะแนนและโบนัสเท่ากันรหัสนั้นที่มีคะแนนโหวตสูงสุดจะเป็นฝ่ายชนะ

(ครบกำหนด: เมื่อมีมากกว่า 5 รหัสที่มีคะแนนมากกว่า (หรือเท่ากัน) +1)


20030229 ถือว่าเป็นวันที่ไม่ถูกต้องจากโบนัสตัวที่สามหรือไม่?
rintaun

@ printaun ใช่ 20040229มันเป็นเรื่องที่ไม่ถูกต้องซึ่งแตกต่างจาก : P
JiminP

1
WolframAlpha ส่งคืนผลลัพธ์ที่ถูกต้องจริงหรือไม่ ฉันได้รับคำตอบที่ขัดแย้งกันจากมันและtimeanddate.com โปรแกรมของฉันซึ่งฉันเชื่อว่าทำงานอย่างถูกต้อง (อย่างน้อยในกรณีนั้น: P) เห็นด้วยกับโปรแกรมหลัง
rintaun

@ printaun ฉันคิดว่า Wolfram | Alpha ผิดตั้งแต่365*4 + 2 + 2= 1464 ขอบคุณสำหรับข้อมูล!
JiminP

1
ควรสังเกตว่าถึงแม้จะมี timeanddate.com แต่ก็มีปัญหาบางอย่าง: มันยอมรับเฉพาะปี 1-3999 เท่านั้นและปรับอัตโนมัติสำหรับความคลาดเคลื่อน 11 วันระหว่างปฏิทินจูเลียนและเกรกอเรียนสำหรับวันที่ก่อนวันที่ 3 ก.ย. 1752 (ดังนั้น 17520903 ถึง 17520914 ไม่ใช่วันที่ที่ถูกต้อง) โปรดระลึกไว้เสมอเมื่อทำการทดสอบผลลัพธ์
rintaun

คำตอบ:


3

Perl 5.14, คะแนน = -162

-163 -181 -196 -214 -167 -213 -234
  • code.length = 211: 208 ตัวอักษรต้นฉบับ + 3 สำหรับการเรียกใช้ Perl ด้วย-pตัวเลือก
  • bonus = 5.5: ค่าเริ่มต้นคำสั่งปีที่ 0 เดือน / วันที่ไม่ถูกต้องวันที่ไม่ถูกต้องอินพุตที่ไม่ถูกต้องทั้งหมด

รหัส

$_=eval(join'-',map{($y,$m,$d)=/(....)(..)(..)/;die"E\n"if!($m*$d)||$m>12||$d>30+($m&1^$m>7)-($m==2)*(2-!($y=~s/00$//r%4));$y-=($m<3)-400;$d+int(($m+9)%12*30.6+.4)+int(365.2425*$y)}/^(\d{8})[ ,-](\d{8})$/)//E

คำนวณจำนวนวัน Julian ที่ถูกแก้ไขสำหรับแต่ละวัน (ละเว้นการปรับที่เกี่ยวข้องกับยุคเพื่อบันทึกความยาวโค้ด) และลบทั้งสอง (อ้างถึง"Julian Day" ที่ Wikipedia )

  • ต้องใช้ Perl 5.14+ สำหรับ/rตัวเลือกในการทดแทน
  • การคำนวณความยาวรายเดือนเพื่อรับโบนัสวันที่ไม่ถูกต้อง: 30+($m&1^$m>7)ส่วนที่ให้ความยาวของเดือนใดก็ได้ แต่กุมภาพันธ์ ส่วนที่เหลือปรับสำหรับเดือนกุมภาพันธ์ในปีธรรมดาหรือปีอธิกสุรทิน

สมมติฐาน

  • "ใช้ปฏิทินเกรโกเรียน" หมายถึงปฏิทินเกรโกเรียนที่เป็นแบบ Proleptic สำหรับวันที่ก่อนหน้าว่าจูเลียนเปลี่ยนเป็นเกรกอเรียนที่เราใช้อยู่ นั่นคืออย่าลบ 11 วันสำหรับช่วงเวลาที่ข้ามเช่น 3 ก.ย. 1752 - 14 ก.ย. 1752 การเปลี่ยนผ่านของอังกฤษ
  • "จัดการปี 0" หมายถึงยกตัวอย่างเช่น00000101-00010101ควรให้ 366 เนื่องจาก 0 เป็นผลคูณของ 400 และดังนั้นปี 0 เป็นปีอธิกสุรทิน

ด้วยการเปลี่ยนแปลงที่คุณทำดูเหมือนว่าโปรแกรมของคุณตอนนี้ยอมรับเดือนที่ไม่ถูกต้องและวันเช่นผลตอบแทน20111300-20119999 2717
migimaru

@migimaru: ฉันได้ปรับความถูกต้องออกไปแล้ว ยี้ ฉันจะแก้ไขและอาจกลับมาอีก
DCharness

2

PHP, คะแนน: -539.1

  • 706 ตัวอักษร
  • รายการโบนัสทั้งหมด โบนัส = 5.5

รหัส

<?php $a='(\d{4})(0[0-9]|1[0-2])([0-2][0-9]|3[01])';@$p=preg_match;if(!$p('/^(\d{8})[- ,](\d{8})$/',fgets(STDIN),$z))@die(E);unset($z[0]);sort($z);foreach($z AS$x){if(!$p('/(\d{4})(0[0-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])/',$x,$w))die(E);$n[]=$w;}$m=array(31,28,31,30,31,30,31,31,30,31,30,31);$r=0;$b=$n[0][1];$c=$n[0][2];$d=$n[0][3];$e=$n[1][1];$f=$n[1][2];$g=$n[1][3];@$t=str_pad;if((($b.$e==229)&&(!(!($b%4)+!($b%100)-!($b%400))))||($c>12))die(E);for($z=$b.$c.$d;;$s=$d,$r++){if($z==$e.$f.$g)break;if($z>$e.$f.$g)@die(E);if(@$s==$d)$d++;if((($c!=2)&&($d>$m[$c-1]))||(($c==2)&&($d>($m[$c-1]+!($b%4)-!($b%100)+!($b%400))))){$c++;$d=1;}if($c>12){$b++;$c=1;}$z=$b.$t($c,2,0,0).$t($d,2,0,0);}echo($r>0)?--$r:0;

Ungolfed

<?php
$a='(\d{4})(0[0-9]|1[0-2])([0-2][0-9]|3[01])';
@$p=preg_match;
if(!$p('/^(\d{8})[- ,](\d{8})$/',fgets(STDIN),$z)) @die(E);
unset($z[0]);
sort($z);
foreach($z AS $x)
{
        if (!$p('/(\d{4})(0[0-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])/',$x,$w)) die(E);
        $n[]=$w;
}
$m=array(31,28,31,30,31,30,31,31,30,31,30,31);
$r=0;
$b=$n[0][1];
$c=$n[0][2];
$d=$n[0][3];
$e=$n[1][1];
$f=$n[1][2];
$g=$n[1][3];
@$t=str_pad;
if ((($b.$e==229)&&(!(!($b%4)+!($b%100)-!($b%400))))||($c>12)) die(E);
for ($z=$b.$c.$d;;$s=$d,$r++)
{
        if ($z==$e.$f.$g)break;
        if ($z>$e.$f.$g)@die(E);
        if (@$s==$d)$d++;
        if ((($c!=2)&&($d>$m[$c-1]))||(($c==2)&&($d>($m[$c-1]+!($b%4)-!($b%100)+!($b%400)))))
        {
                $c++;
                $d=1;
        }
        if ($c>12)
        {
                $b++;
                $c=1;
        }
        $z=$b.$t($c,2,0,0).$t($d,2,0,0);
}
echo($r>0)?--$r:0;

บันทึก

คำนวณจำนวนวันโดยทำซ้ำในแต่ละวันที่ถูกต้องระหว่างวันที่ให้ไว้ มันค่อนข้างช้าในช่วงที่มีขนาดใหญ่กว่า ฉันแน่ใจว่านี่ไม่ใช่วิธีที่ดีที่สุดในการแก้ปัญหานี้ แต่ฉันก็ใจร้อนและนี่คือสิ่งที่ฉันต้องการ :)

นอกจากนี้ฉันรู้ว่ารหัส "ungolfed" ยังไม่สามารถอ่านได้มาก แต่การเขียนใหม่ทั้งหมดจะต้องใช้ความพยายามมากเกินไป


2

Ruby 1.9, คะแนน: -175 -186 -191 -199

  • ความยาวรหัส: 229 243 250 260ตัวอักษร
  • โบนัส: 5.5 (ค่าเริ่มต้นคำสั่งปีที่ 0 เดือน / วันที่ไม่ถูกต้องวันที่ไม่ถูกต้องข้อมูลที่ไม่ถูกต้อง)

รหัสรับอินพุตผ่าน stdin

h=->n{n/4-n/100+n/400+1}
u,v=gets.split(/[ ,-]/).map{|s|s=~/^\d{8}$/?(d,e,f=[s[0,4],s[4,2],s[6,2]].map &:to_i;x=[0,y=31,28+h[d]-z=h[d-1]]+[y,30,y,30,y]*2
(!x[e]||e*f<1||f>x[e])?0:d*365+z+eval(x[0,e]*?+)+f):0}
puts (v*u>0)?u-v :?E

หมายเหตุ:

  • h ส่งคืนจำนวนปีอธิกสุรทินจนถึงปีนั้น (รวมทั้งปี 0 สำหรับโบนัส)
  • regex จัดการโบนัสอินพุตที่ไม่ถูกต้อง
  • (!x[e]||e*f<1||f>x[e])สภาพจัดการเดือน / วัน / โบนัสวันที่ไม่ถูกต้อง
  • ผลลัพธ์จะแสดงเป็นวันที่แรกลบด้วยวันที่ที่สองดังนั้นหากวันที่ที่สองเป็นวันหลังจากนั้นมันจะออกมาเป็นจำนวนลบ
  • ไม่ปรับสำหรับการเปลี่ยนแปลงระหว่างจูเลียนและปฏิทินเกรกอเรียนเพื่อให้ผลในการ33320229 17000101596134

ขอบคุณสำหรับการตรวจสอบข้อผิดพลาดของฉันและขอให้ฉันปรับปรุงต่อไป ฉันชอบการคำนวณเดือนกุมภาพันธ์ของคุณที่นี่โดยเฉพาะ
DCharness

@Dcharness ขอบคุณสำหรับการผลักดันฉันเช่นกัน ฉันรู้ว่ามีห้องมากมายสำหรับการปรับปรุงในการส่งต้นฉบับของฉัน
migimaru

1

Python คะแนน: -478

  • ตัวละคร: 455
  • โบนัส: วันที่กลับวัน / เดือนไม่ถูกต้องวันที่ไม่ถูกต้อง

วิธีการแก้:

import re
a=re.split('[-, ]',raw_input())
def c(x):return x[0]
def f(x,y=3):return(1if x%400==0 or x%100!=0and x%4==0 else 0)if y>2 else 0
t=[31,28,31,30,31,30,31,31,30,31,30,31]
[q,w,e],[i,o,p]=sorted([map(int,[a[x][:4],a[x][4:6],a[x][6:]])for x in[0,1]],key=c)
print sum(map(f,range(q,i)))+(i-q)*365+p+sum(t[:o-1])-e-sum(t[:w-1])+f(i,o)-f(q,w)if 0<w<13and 0<e<32and 0<o<13and 0<p<32and(e<=t[w-1]or(f(q)and e==29))and(p<=t[o-1]or(f(i)and p==29))else 'E'

ฉันไม่มีเวอร์ชัน "ungolfed" เนื่องจากนี่เป็นวิธีที่ฉันเขียน ฉันไม่ได้ทดสอบอย่างถูกต้องดังนั้นหากคุณพบข้อผิดพลาด - โปรดแสดงความคิดเห็น

แก้ไข: หวังว่าจะแก้ไขข้อผิดพลาดที่ชี้ให้เห็นในความคิดเห็นและเพิ่มการเปิดออกในรูปแบบของ [a, b], [c, d] = [[1,2], [3,4]


ขออภัย แต่เมื่อผมทดสอบกับงูหลาม 2.7 Shell, ปัจจัยการผลิตที่ไม่ถูกต้องเช่น '20000001,20010101' Eไม่พิมพ์ (FYI, 0>-1>12, 0>6>12, 0>13>12ผลตอบแทนFalse.)
JiminP

ขอบคุณ ฉันค่อนข้างใหม่กับงูหลาม การเขียนสคริปต์นี้ผมได้เรียนรู้หลามที่ไม่นี้เปรียบเทียบหรือมีการx<y<z x if y else zพยายามแก้ไขมัน
rplnt

@rpInt: สำหรับการเล่นกอล์ฟก็มีสิ่ง[x,z][y]ที่สั้นกว่าx if y else zแม้ว่ามันจะไม่ได้ผลเสมอไปเพราะต่างจาก if-expression มันไม่ได้ขี้เกียจ
Lie Ryan

1

PHP, คะแนน: -516

ตัวอักษร: 685 676

โบนัส: 5.5

<? $z='/((\d{1,4})(\d\d)(\d\d))[- ,]((\d{1,4})(\d\d)(\d\d))/';if(!preg_match($z,$argv[1],$m))die('E');$s=1;if($m[1]>$m[5]){if(!preg_match($z,"$m[5] $m[1]",$m))die('E');$s=-1;}$b=array(31,28,31,30,31,30,31,31,30,31,30,31);list($x,$v,$c,$d,$e,$w,$f,$g,$h)=$m;if($d>12||1>$d||$g>12||1>$g||1>$e||1>$h||($e>$b[$d-1]&&!($d==2&&$e<30&&$c%4==0))||($h>$b[$g-1]&&!($g==2&&$h<30&&$f%4==0)))die('E');$z='array_slice';$y='array_sum';$x=$d!=$g||$e>$h;$r=$x?$b[$d-1]+$h-$e:$h-$e;$d+=$x;if($d>12){$c++;$d=1;}$r+=$d>$g?$y($z($b,$d-1,13-$d))+$y($z($b,0,$g-1)):($d!=$g?$y($z($b,$d-1,$g-$d)):0);$r+=($f-$c-($d>$g))*365;for($i=$c;$i<=$f;$i++)if($i%4==0&&$i.'0229'>$v&&$i.'0229'<$w)$r++;echo $s*$r;

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