日付範囲のギャップを見つける


15

r入力、出力として日付範囲のリストを指定するか、にない範囲を返しますr

この例では、入力はYYYY-MM-DD形式になります。

3つの日付範囲があるとします。

[2019-01-01, 2019-02-01]
[2019-02-02, 2019-04-05]
[2019-06-01, 2019-07-01]

あなたは、間にギャップがあることがわかります2019-04-05とは2019-06-01

出力はそのギャップになります: [2019-04-06, 2019-05-31]

ルール

  • 入力と出力は、一貫している限り、任意の妥当な日付またはコレクションの形式にすることができます。
  • 入力が順序付けられていないと仮定します。
  • 日付範囲はである必要はありませんが[latest, earliest]、ルール2に従う必要があります。
  • 入力に重複する日付がないと仮定します

テストケース:

入力: [[2019-01-01, 2019-02-01],[2019-02-02, 2019-04-05],[2019-06-01, 2019-07-01]]

出力: [[2019-04-06, 2019-05-31]]


入力: [[2019-01-01, 2019-02-01],[2018-02-02, 2018-04-05],[2019-06-01, 2019-07-01]]

出力: [[2018-04-06, 2018-12-31], [2019-02-02, 2019-05-31]]


入力: [[2019-01-01, 2019-02-01],[2019-02-02, 2019-03-02],[2019-03-03, 2019-07-01]]

出力: []


入力: [[2019-01-01, 2019-02-01], [2019-11-02, 2019-11-20]]

出力: [[2019-02-02, 2019-11-01]]


入力: [[2019-01-01, 2019-02-01],[2019-02-03, 2019-04-05]]

出力:[[2019-02-02, 2019-02-02]]または[[2019-02-02]]


5
YYYY-MM-DD現在の形式は多くの人々にとって異質であり、月の日数が12以下であるために解析がさらに難しくなるため、すべての例の日付をISO形式に作り直すことをお勧めします。
アダム

@Adám良いアイデア、更新。
オリバー

.NET OLE Automation Datesとして入力できますか?
アダム

@Adámはい。妥当な日付形式であれば問題ありません。
オリバー

1
日付は注文されますか?また、日付のペア内で、後の日付が最後になりますか?
無知の

回答:


4

APL(Dyalog Extended)28 25 24バイト

匿名の暗黙の接頭辞関数。引数と結果は、エポック以降の日数の2列の行列で、各行は範囲を表します。

1 ¯1+⍤1∘{⍵⌿⍨1<-⍨/⍵}1⌽⍢,∧

オンラインでお試しください!InIDNの2列の行列への3要素のリスト(ISO順で日付)のペアのリストから、プリプロセッサの機能変換し、国際デー番号(1899年12月31日以来の日)。のOut3要素のリストのマトリックスへのIDNのマトリックスからポストプロセッサ関数変換します。

 行を昇順に並べ替える

1⌽
⍢, ラベリング(平坦化)しながら 日付を1ステップ左に循環的に回転します—その後、元の形状に戻ります

1 ¯1+ 一方と負のいずれかを追加する
⍤1 行ごとにそのリストを使用して、
 結果の
{... } 以下ラムダ:
 引数は
-⍨/ 、右側の日付から左側の日付を減算し、行方向
1< の違いが1つを超えたマスク(すなわち、範囲は隣接していない場合)
⍵⌿⍨ フィルタそのマスクによる行


3

C#(Visual C#Interactive Compiler)、108バイト

n=>{n.Sort();for(int i=0;;)Write(n[i].b.AddDays(1)==n[++i].a?"":n[i-1].b.AddDays(1)+""+n[i].a.AddDays(-1));}

形式での印刷による出力 DD/MM/YYYY 12:00:00 AMDD/MM/YYYY 12:00:00 AM。IndexOutOfRange例外が発生しますが、これはメタコンセンサスごとに問題ありません。

オンラインでお試しください!

UNIXエポック以降の日数の形式で入力を取得する場合、これを取得できます...

83バイト

n=>{n.Sort();for(int i=0;;)Print(n[i].b+1==n[++i].a?"":n[i-1].b+1+" "+(n[i].a-1));}

オンラインでお試しください!

これをさらに下にゴルフできます /u:System.Array旗でます...

78バイト

n=>{Sort(n);for(int i=0;;)Print(++n[i].b==n[++i].a--?"":n[i-1].b+" "+n[i].a);}

オンラインでお試しください!





2

PHP、208 197 190 177バイト

新しいアプローチにはかなりのゴルフの可能性がありましたが...

function($a){sort($a);for($m=$x=$a[0][0];$f=$m<=$x;$f^$g&&print($g=$f)?"$m/":"$n
",$m=date("Y-m-d",strtotime($n=$m)+9e4))foreach($a as$d)$x=max($x,$d[1|$f&=$m<$d[0]|$m>$d[1]]);}

関数は、ISO形式で範囲の配列[開始、終了]を取り、ギャップ間隔を出力します。オンラインでお試しください


壊す

function($a){
    sort($a);                           # sort ranges (for easy access to min date)
    for($m=$x=$a[0][0];$f=$m<=$x;       # loop from min date to max date, 1. set flag
        $f^$g&&print($g=$f)?"$m/":"$n\n",       # 4. flag changed: backup flag, print date
        $m=date("Y-m-d",strtotime($n=$m)+9e4)   # 5. backup and increment date
    )foreach($a as$d)
        $x=max($x,$d[1                          # 2. find max date
            |$f&=$m<$d[0]|$m>$d[1]              # 3. date found in ranges: clear flag
        ]);
}

1

ゼリー、13 バイト

FṢṖḊs2+Ø+>/Ðḟ

Jelly(現在)には組み込みの日付がないため、エポックからの日数を使用します。
範囲(整数のペア)の入力リストは、順序と方向が混在している場合があります。
結果は、昇順の昇順範囲のリストです。

オンラインでお試しください!(空のリストをとして表示するためのフッター形式[]

どうやって?

注:これは、ルールに記載されている「入力に重複する日付がない」という保証に依存しています。

FṢṖḊs2+Ø+>/Ðḟ - Link: list of pairs of integers
F             - flatten
 Ṣ            - sort
  Ṗ           - pop (remove tail)
   Ḋ          - dequeue (remove head)
    s2        - split into twos
       Ø+     - literal [1,-1]
      +       - add (vectorises)
           Ðḟ - filter discard those for which:
          /   -   reduce by:
         >    -     greater than?

興味深いことに、Jellyに日付のサポートがないことは知りませんでした。これは通常のアプローチですか?エポックからの日数を使用しますか?
ダナ

エポックからの日数は、一部のシステムで使用されていると思われます(Excelである可能性があります)。エポックからの秒数がより一般的です(例:Unix)。私は、要件をかなりカバーしているように見えますが、かなりゆるいものでした。
ジョナサンアラン

ブー、日付を手動で計算できます。; Pエポック以降の日数は、日付をサポートしていない言語で実際に頻繁に使用されます。とはいえ、この挑戦​​がもっと簡単になると思います。
ケビンCruijssen

@KevinCruijssenへえ、同意した。
ジョナサンアラン

1

C#(Visual C#Interactive Compiler)、103バイト

x=>{var(a,_)=x[0];foreach(var(b,c)in x.OrderBy(y=>y)){if(a<b)Print((a,b.AddDays(-1)));a=c.AddDays(1);}}

オンラインでお試しください!

入力は、開始/終了日のタプルのリストです。欠落している各範囲をSTDOUTに出力します。

// x: input list of start/end date tuples
x=>{
  // variable definitions...
  // a: 1 day after the end date of the previous range
  // b: start of the current range
  // c: end of the current range

  // start by deconstructing the start date of the first tuple
  // into a. a will then be a DateTime and will contain a value
  // at least a large as the smallest start date.
  var(a,_)=x[0];
  // iterate over sorted ranges
  foreach(var(b,c)in x.OrderBy(y=>y)){
    // if the day after the end of the previous range is less
    // than the start of the current range, then print the
    // missing days.
    if(a<b)
      Print((a,b.AddDays(-1)));
    // save the day after the current range to a for next iteration
    a=c.AddDays(1);
  }
}


ハ-無知の体現のように印刷すると、本当に小さくなります
ダナ

いいね また、後者の2つの入力方法をwtf
ASCIIのみ

まあ、実際に...それは本当に間違ったルックス
ASCIIのみ

1
今も元気に見えるうん
ASCIIのみ

1

R、88バイト

function(a,b=a[order(a$x),],d=c(b$x[-1]-b$y[-nrow(b)],0))data.frame(b$y+1,b$y+d-1)[d>1,]

オンラインでお試しください!

これは、日付範囲のデータフレームを入力として受け取り、欠落している範囲のデータフレームを出力します。これはもっとゴルフができると確信していますがccbindで問題が発生しました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.