2日間の差を計算します。


11

別の日付操作の問題:P

仕事

ユーザーが指定した2つの日付の差を計算するプログラムまたは関数を作成します。

入出力

前のものと同様に、入力はYYYYMMDDスペース、コンマ,、またはマイナス記号で区切られた2つ-です。

入力値の例:

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

出力は整数であり、2つの日付の日数の差です。

たとえば、入力20110101-20100101yields 365および33320229 17000101yields 596124

結果をテストできます ここで ここで。(以下のrintaunのコメントを参照してください。)2つの日付が同じ0場合、日付が有効であればプログラムはを返します(スコアを参照)。

制限

もちろん、あなたがしなければならない使用しない任意の関数/クラスの種類/ ...タイムスタンプまたは日付に関連している、とあなたが使用する必要がありますグレゴリオ暦を

スコア

あなたのコードは、制限を守らない場合score = -∞

デフォルトbonusは1です。

  • 入力の順序(たとえば、20100101,20110101return 365または-365)に関係なくコードが機能する場合bonus+=1
  • あなたのコードが処理できる場合は年0bonus+=0.5
  • あなたのコードが/日付(1〜12の間)のように、(1〜31の間)、無効な月を認識した場合2010990134720132、および印刷物E(&などのプログラムや戻り何かを終了0)、 bonus+=1
  • かかわらず、上記のルールの、あなたのコードは無効な日付を認識した場合、のような2010023020100229あるいは20111131、および印刷物E(&プログラムまたは返すようなものを終了0)、 bonus+=1
  • 上記の2つのルールに関係なく、コードが20100101|20100202orなどの無効な入力文字列を認識し2010010120100202、印刷E(&がプログラムを終了する、またはのようなものを返す0)する場合bonus+=1

score = floor(-4.2*code.length/bonus)。最高スコアのコードが勝ちます。2つの上位コードのスコアが同じ場合、ボーナスが最も高いコードが勝ちます。2つの上位コードが同じスコアとボーナスの両方を持っている場合、最高得票のコードが勝ちます。

(期限:+1投票数が多い(または等しい)コードが5つ以上ある場合。)


20030229は3番目のボーナスで無効な日付と見なされますか?
リンタウン

@rintaunはい。とは異なり、無効20040229です。:P
JiminP

1
WolframAlphaは実際に正しい結果を返しますか?私はから相反する回答を得ている、それをしてtimeanddate.com。私のプログラムは(少なくともその場合:Pで)正しく動作していると思いますが、後者に同意します。
リンタウン

@rintaun Wolfram | Alphaは間違っていたと思う、365*4 + 2 + 2=1464。情報をありがとう!
JiminP

1
timeanddate.comでさえ、いくつかの問題があることに注意する必要があります。1〜3999年のみを受け入れ、1752年9月3日より前の日付のユリウス暦とグレゴリオ暦の11日間の不一致を自動調整します。 (したがって、17520903から17520914は有効な日付ではありません)。結果をテストするときは、このことに留意してください。
リンタウン

回答:


3

Perl 5.14、スコア= -162

-163 -181 -196 -214 -167 -213 -234
  • code.length = 211:-pオプションを使用してperlを実行する場合、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

各日付の修正されたユリウス日数を計算し(エポック関連の調整を無視してコード長を節約)、2つを減算します。(Wikipediaの「Julian Day」を参照)。

  • /r置換のオプションにはperl 5.14以降が必要です
  • 無効な日付ボーナスを取得するための月の長さの計算:30+($m&1^$m>7)パートは、2月以外の月の長さを示します。残りは通常またはうるう年の2月に調整されます

仮定

  • 「グレゴリオ暦を使用する」とは、使用しているユリウス暦からグレゴリオ暦への移行よりも前の日付の予測グレゴリオ暦を意味します。つまり、たとえば、1752年9月3日から1752年9月14日までの英国の移行期間をまたぐ間隔で11日を減算しないでください。
  • 「0年を処理する」とは、たとえば、00000101-000101010は400の整数倍であり、0年はうるう年であるため、366を与えることを意味します。

行った変更により、プログラムがreturnなどの無効な月と日を受け入れるよう20111300-20119999になりました2717
みぎ丸

@migimaru:私は確かに正確さを最適化しました。くそー 編集して戻ってくるかもしれません。
-Dチャーネス

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;

注意

指定された2つの間の有効な各日付を反復処理して、日数を計算します。大きな範囲ではかなり遅いです。これはこれを解決する最善の方法ではないと確信していますが、私はイライラしました。:)

また、「改変されていない」コードはまだ非常に読みやすいものではないことを知っていますが、完全に書き直すには手間がかかりすぎます。


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を含む)。
  • 正規表現は無効な入力ボーナスを処理します。
  • (!x[e]||e*f<1||f>x[e])条件が無効月/日/日付のボーナスを処理します。
  • 結果は最初の日付から2番目の日付を引いたものとして表示されるため、2番目の日付が後の場合は負の数として出力されます。
  • ユリウス暦とグレゴリオ暦の間の変更を調整しないため、33320229 17000101結果はになり596134ます。

ソリューションのエラーチェックを行い、改善を続けてくれてありがとう。ここでの2月の長さの計算が特に気に入っています。
-DCharness

@DCharness私も押してくれてありがとう。最初の投稿には改善の余地が十分にあることに気付きました。
みぎまる

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]の形式で展開を追加したことを願っています。


申し訳ありませんが、Python 2.7シェルでテストした場合、「20000001,20010101」のような無効な入力は印刷されませんE。(FYI、 、、0>-1>12 リターン)0>6>120>13>12False
JiminP

ありがとう。私はpythonを初めて使います。このスクリプトを書くと、Pythonがこのx<y<z比較を行うこと、またはx if y else z。それを修正しようとしました。
rplnt

@rpInt:ゴルフに[x,z][y]は、より短いがx if y else zありますが、if式とは異なりレイジーではないため、常に機能するとは限りません。
ライライアン

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コード<?は最初に実行する必要があります。それ以外の場合は、コードを出力するだけです。
ガレス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.