Tính toán sự khác biệt giữa hai ngày.


11

Một vấn đề thao túng ngày tháng khác: P

Bài tập

Viết chương trình hoặc hàm tính toán chênh lệch giữa hai ngày do người dùng cung cấp.

Đầu ra đầu vào

Tương tự như trước , các đầu vào là hai YYYYMMDDs, được phân tách bằng dấu cách ,, dấu phẩy hoặc dấu trừ -.

Ví dụ về các giá trị đầu vào:

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

Đầu ra là một số nguyên, là sự khác biệt giữa hai ngày, tính theo ngày.

Ví dụ, 20110101-20100101sản lượng đầu vào 365, và 33320229 17000101sản lượng 596124.

Bạn có thể kiểm tra kết quả ở đây tại đây . (Xem bình luận của rintaun bên dưới.) Nếu hai ngày giống nhau, chương trình sẽ trả về 0, nếu ngày đó hợp lệ (xem Điểm ).

Sự hạn chế

Tất nhiên, bạn phải không sử dụng bất kỳ loại chức năng / lớp / ... có liên quan đến dấu thời gian hoặc ngày, và bạn nên sử dụng lịch Gregorian .

Ghi bàn

Nếu mã của bạn không giữ hạn chế, thì score = -∞.

Mặc định bonuslà 1.

  • Nếu mã của bạn hoạt động bất kể thứ tự đầu vào (ví dụ, 20100101,20110101trả về 365hoặc -365) , bonus+=1.
  • Nếu mã của bạn có thể xử lý năm 0 , bonus+=0.5.
  • Nếu mã của bạn nhận ra tháng không hợp lệ (trong khoảng từ 1 ~ 12) / ngày (trong khoảng từ 1 ~ 31), thích 20109901hoặc 34720132và in E(& chấm dứt chương trình hoặc trả về một cái gì đó như 0) , bonus+=1.
  • Bất kể quy tắc trên, nếu mã của bạn nhận ra số ngày không hợp lệ, giống như 20100230, 20100229hoặc 20111131, và in E(& chấm dứt chương trình hoặc trở về một cái gì đó giống như 0), bonus+=1.
  • Bất kể hai quy tắc trên, nếu mã của bạn nhận ra chuỗi đầu vào không hợp lệ, như 20100101|20100202hoặc 2010010120100202và in E(& chấm dứt chương trình hoặc trả về một cái gì đó như 0) , bonus+=1.

score = floor(-4.2*code.length/bonus). Mã có số điểm cao nhất sẽ thắng. Nếu hai mã hàng đầu có cùng số điểm, thì mã có tiền thưởng cao nhất sẽ thắng. Nếu hai mã hàng đầu có cùng số điểm và tiền thưởng, thì mã có số phiếu cao nhất sẽ thắng.

(Đến hạn: Khi có nhiều hơn 5 mã có nhiều hơn (hoặc bằng) +1phiếu bầu.)


Là 20030229 được coi là một ngày không hợp lệ bởi phần thưởng thứ ba?
rintaun

@rintaun Vâng. Nó không hợp lệ, không giống như 20040229. : P
JiminP

1
Liệu WolframAlpha thực sự trả lại kết quả chính xác? Tôi đang nhận được câu trả lời mâu thuẫn từ timeanddate.com . Chương trình của tôi, mà tôi tin là đang hoạt động chính xác (ít nhất là trong trường hợp đó: P), đồng ý với chương trình sau.
rintaun

@rintaun Tôi nghĩ Wolfram | Alpha đã sai, kể từ 365*4 + 2 + 2= 1464. Cảm ơn thông tin!
JiminP

1
Cần lưu ý rằng ngay cả với timeanddate.com, có một số vấn đề: nó chỉ chấp nhận năm 1-3999 và nó tự động điều chỉnh sự khác biệt trong 11 ngày giữa lịch Julian và Gregorian cho các ngày trước ngày 3 tháng 9 năm 1752 (vì vậy 17520903 đến 17520914 không phải là ngày hợp lệ). Hãy ghi nhớ điều này khi kiểm tra kết quả.
rintaun

Câu trả lời:


3

Perl 5,14, điểm = -162

-163 -181 -196 -214 -167 -213 -234
  • code.length = 211: 208 ký tự nguồn + 3 để chạy perl với -ptùy chọn
  • tiền thưởng = 5,5: mặc định, đơn hàng, năm 0, tháng / ngày không bao giờ hợp lệ, ngày không hợp lệ, đầu vào hoàn toàn không hợp lệ

$_=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

Tính số ngày Julian đã sửa đổi cho mỗi ngày (bỏ qua các điều chỉnh liên quan đến kỷ nguyên để lưu chiều dài mã) và trừ hai. (tham khảo "Ngày Julian" tại Wikipedia ).

  • yêu cầu perl 5.14+ cho /rtùy chọn thay thế
  • tính toán độ dài tháng để nhận phần thưởng ngày không hợp lệ: 30+($m&1^$m>7)phần này cho độ dài của bất kỳ tháng nào trừ tháng hai; phần còn lại điều chỉnh cho tháng hai trong một năm bình thường hoặc năm nhuận

Giả định

  • "sử dụng lịch Gregorian" có nghĩa là lịch Gregorian phổ biến cho các ngày trước khi chuyển đổi từ Julian sang Gregorian mà chúng ta đang sử dụng. Đó là, không trừ 11 ngày cho các khoảng thời gian giao nhau, ví dụ, chuyển đổi ngày 3 tháng 9 năm 1752 - 14 tháng 9 năm 1752 của Anh.
  • "Xử lý năm 0" có nghĩa là, ví dụ, 00000101-00010101nên đưa ra 366, vì 0 là bội số tổng của 400 và vì vậy năm 0 là năm nhuận.

Với những thay đổi bạn đã thực hiện, có vẻ như chương trình của bạn hiện chấp nhận tháng và ngày không hợp lệ, như 20111300-20119999tiền lãi 2717.
Migimaru

@migimaru: Tôi thực sự đã tối ưu hóa tính chính xác. Chết tiệt. Tôi sẽ chỉnh sửa và có thể quay lại với nó.
DCharness

2

PHP, Điểm: -539.1

  • 706 ký tự
  • Tất cả các mục thưởng; tiền thưởng = 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;

Ung dung

<?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;

Ghi chú

Tính số ngày bằng cách lặp qua từng ngày hợp lệ giữa hai ngày được cung cấp. Nó khá chậm trên phạm vi lớn hơn. Tôi chắc chắn đây không phải là cách tốt nhất để giải quyết vấn đề này, nhưng tôi đã mất kiên nhẫn và đây là điều tôi đã kết thúc. :)

Ngoài ra, tôi biết mã "không được mã hóa" vẫn không thể đọc được, nhưng viết lại nó hoàn toàn sẽ đòi hỏi quá nhiều nỗ lực.


2

Ruby 1.9, Điểm: -175 -186 -191 -199

  • Độ dài mã: 229 243 250 260 ký tự
  • Tiền thưởng: 5,5 (mặc định, đơn hàng, năm 0, tháng / ngày không hợp lệ, ngày không hợp lệ, đầu vào không hợp lệ)

Mã chấp nhận đầu vào thông qua 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

Ghi chú:

  • h trả về số năm nhuận cho đến năm đó (bao gồm cả năm 0 cho tiền thưởng).
  • Regex xử lý phần thưởng đầu vào không hợp lệ.
  • Điều (!x[e]||e*f<1||f>x[e])kiện xử lý tiền thưởng tháng / ngày / ngày không hợp lệ.
  • Kết quả được hiển thị dưới dạng ngày đầu tiên trừ ngày thứ hai, vì vậy nếu ngày thứ hai muộn hơn, nó sẽ xuất ra dưới dạng số âm.
  • Không điều chỉnh cho sự thay đổi giữa lịch Julian và Gregorian, vì vậy 33320229 17000101kết quả là 596134.

Cảm ơn đã kiểm tra lỗi của tôi và đã thúc đẩy tôi tiếp tục cải thiện. Tôi đặc biệt thích tính toán độ dài tháng hai của bạn ở đây.
DCharness

@DCharness Cảm ơn vì đã đẩy tôi là tốt. Tôi nhận ra có rất nhiều chỗ để cải thiện trong bài dự thi ban đầu của mình.
Migimaru

1

Python, Điểm: -478

  • ký tự: 455
  • tiền thưởng: ngày đảo ngược, ngày / tháng không hợp lệ, ngày không hợp lệ

giải pháp:

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'

Tôi không có phiên bản "vô danh" vì đây là cách tôi viết nó. Tôi đã không kiểm tra đúng cách vì vậy nếu bạn tìm thấy một lỗi - vui lòng bình luận.

chỉnh sửa: hy vọng đã sửa một lỗi được chỉ ra trong một nhận xét và thêm giải nén dưới dạng [a, b], [c, d] = [[1,2], [3,4]


Xin lỗi, nhưng khi tôi thử nghiệm với Python 2.7 Shell, các đầu vào không hợp lệ như '20000001,20010101' không in E. (FYI, 0>-1>12, 0>6>12, 0>13>12lợi nhuận False.)
JiminP

Cảm ơn. Tôi còn khá mới với python. Viết kịch bản này tôi đã học được rằng python thực hiện x<y<zso sánh này hoặc có một x if y else z. Đã cố gắng để sửa nó.
rplnt

@rpInt: để chơi gôn, cũng [x,z][y]có cái ngắn hơn x if y else z, mặc dù nó không luôn hoạt động vì không giống như biểu thức if, nó không lười biếng.
Lie Ryan

1

PHP, điểm: -516

ký tự: 685 676

tiền thưởng: 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;

Mã PHP cần <?ngay từ đầu để chạy, nếu không nó chỉ in ra mã.
Gareth
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.