이틀 간의 차이를 계산하십시오.


11

다른 날짜 조작 문제 : P

직무

사용자가 제공 한 두 날짜의 차이를 계산하는 프로그램이나 함수를 작성하십시오.

입출력

이전 입력과 유사하게 입력은 YYYYMMDD공백 , 쉼표 ,또는 빼기 부호 로 구분 된 두 개의 입력 -입니다.

입력 값의 예 :

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

출력은 정수이며, 두 날짜 사이의 차이 (일)입니다.

예를 들어, input 20110101-20100101yields 36533320229 17000101yields 596124입니다.

결과를 테스트 할 수 있습니다 여기에 여기에 . (아래의 rintaun의 의견을 참조하십시오.) 두 날짜가 동일 0하면 날짜가 유효하면 프로그램에서을 반환해야합니다 ( 점수 참조 ).

제한

물론, 당신은 해야한다 사용하지 어떤 / ... 타임 스탬프 또는 날짜에 관련된 기능 / 클래스의 종류, 당신은 사용해야 그레고리력을 .

점수

코드가 제한을 유지하지 않으면 score = -∞.

기본값 bonus은 1입니다.

  • 코드 (예, 대한 입력 순서에 관계없이 작동하는 경우 20100101,20110101반환 365또는 -365) bonus+=1.
  • 코드가 처리 할 수있는 경우 0 년 , bonus+=0.5.
  • 코드가 / 날짜 (1 ~ 12 사이)와 같은, (1 ~ 31 일 사이에) 유효하지 않은 달을 인식하는 경우 2010990134720132, 및 인쇄 E(같은 프로그램이나 반환 뭔가를 종료 0) bonus+=1.
  • 에 관계없이 위의 규칙, 코드가 유효하지 않은 날짜, 같은 인식하는지 20100230, 20100229또는 20111131, 및 인쇄 E(같은 프로그램이나 반환 뭔가를 종료를 0) bonus+=1.
  • 에 관계없이 두 가지 규칙 위의 코드가 같은 잘못된 입력 문자열을 인식하는 경우 20100101|201002022010010120100202, 및 인쇄 E(같은 프로그램이나 반환 뭔가를 종료 0) bonus+=1.

score = floor(-4.2*code.length/bonus). 가장 높은 점수를 얻은 코드가 승리합니다. 두 개의 최상위 코드의 점수가 같으면 보너스가 가장 높은 코드가 승리합니다. 두 개의 최상위 코드가 동일한 점수와 보너스를 모두 가진 경우, 가장 높은 표를 얻은 코드가 승리합니다.

(사유 : +1투표 수가 5 이상인 코드가있는 경우 )


20030229는 세 번째 보너스로 유효하지 않은 날짜로 간주됩니까?
rintaun

@rintaun 예. 와 달리 유효하지 않습니다 20040229. : P
JiminP

1
WolframAlpha가 실제로 올바른 결과를 반환합니까? 그것timeanddate.com 에서 충돌하는 답변을 얻고 있습니다. 내가 올바르게 작동한다고 생각하는 내 프로그램 (적어도 그 경우 : P)은 후자에 동의합니다.
rintaun

@rintaun Wolfram | Alpha가 잘못되었다고 생각합니다. 365*4 + 2 + 2= 1464. 정보 주셔서 감사합니다!
JiminP

1
timeanddate.com에서도 몇 가지 문제가 있습니다. 1-3999 년만 허용하며, 1752 년 9 월 3 일 이전의 율리우스 달력과 그레고리력 간의 11 일 불일치에 대해 자동 조정됩니다. 17520903에서 17520914까지의 날짜는 유효하지 않습니다. 결과를 테스트 할 때이 점을 명심하십시오.
rintaun

답변:


3

펄 5.14, 점수 = -162

-163 -181 -196 -214 -167 -213 -234
  • code.length = 211 : -p옵션으로 펄을 실행하기위한 208 개의 소스 문자 + 3
  • 보너스 = 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

각 날짜에 대해 수정 된 율리우스 일 수를 계산하고 (코드 길이를 절약하기 위해 에포크 관련 조정 무시) 두 날짜를 뺍니다. ( Wikipedia의 "Julian Day" 참조 ).

  • /r대체 옵션에 perl 5.14 이상 필요
  • 유효하지 않은 날짜 보너스를 얻기위한 월 길이 계산 : 30+($m&1^$m>7)부분은 2 월을 제외한 모든 월의 길이를 제공합니다. 나머지는 보통 또는 윤년에 2 월을 조정합니다

가정

  • "그레고리력 사용"은 우리가 사용하는 율리우스에서 그레고리력으로 전환하기 전의 날짜에 대한 그레고리력 캘린더를 의미합니다. 즉, 1752 년 9 월 3 일-1752 년 9 월 14 일 영국 전환과 같은 간격에 대해 11 일을 빼지 마십시오.
  • "handle year 0"은 예를 들어 00000101-000101010은 400의 정수배이므로 0은 윤년입니다.

변경 사항이 있으면 프로그램이 이제 20111300-20119999return 과 같이 유효하지 않은 월과 일을 받아들이는 것처럼 보입니다 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;

언 골프

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

루비 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 년 포함).
  • 정규식은 유효하지 않은 입력 보너스를 처리합니다.
  • (!x[e]||e*f<1||f>x[e])조건은 무효 월 / 일 / 날짜 보너스를 처리합니다.
  • 결과는 첫 번째 날짜에서 두 번째 날짜를 뺀 것으로 표시되므로 두 번째 날짜가 나중에 나면 음수로 출력됩니다.
  • Julian과 Gregorian 캘린더 사이의 변경에 대해서는 조정하지 않으므로 33320229 17000101결과는 596134입니다.

솔루션 오류를 확인하고 개선을 계속하도록 도와 주셔서 감사합니다. 나는 특히 당신의 2 월 길이 계산을 좋아합니다.
DCharness

@DCharness 저를 밀어 주셔서 감사합니다. 원래 제출물을 개선 할 여지가 많다는 것을 깨달았습니다.
migimaru

1

파이썬, 점수 : -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]의 형태로 포장 풀기 추가


죄송하지만 Python 2.7 Shell로 테스트했을 때 '20000001,20010101'과 같은 잘못된 입력은 인쇄되지 않습니다 E. (참고로, 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.