Поиск пробелов в диапазонах дат

15

Дан список диапазонов дат в rкачестве входных, выходных или возвращаемых диапазонов, не найденных в r.

Ради этого примера ввод будет в YYYY-MM-DDформате.

Допустим, у вас есть три диапазона дат:

[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
Я предлагаю переделать все даты в качестве примера в формат ISO, так YYYY-MM-DDкак текущий формат является чужим для многих, и его еще труднее разобрать из-за использования маленьких дней месяца≤12.
Адам
@ Adám Хорошая идея, обновлено.
Оливер
Можем ли мы принять входные данные в качестве дат .NET OLE Automation?
Адам
@ Адам Да. Любой разумный формат даты приемлем.
Оливер
1
Будут ли даты заказаны? Кроме того, в течение пары дат последний будет последним?
Воплощение Невежества

Ответы:

4

APL (Dyalog Extended) , 28 25 24 байта

Функция анонимного молчаливого префикса. Аргумент и результат - это матрицы из 2-х дневных чисел, начиная с эпохи, каждая строка представляет диапазон.

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

Попробуйте онлайн! Функция Inпрепроцессора преобразует из списка пар трехэлементных списков (даты в порядке ISO) в 2-колоночную матрицу ИДИ, номеров международных дней (дни с 1899-12-31). В Outфункции преобразует постпроцессор от матрицы IDNs к матрице из списков 3-элемента.

 сортировать строки по возрастанию

1⌽ циклически поворачивайте даты на один шаг влево,
⍢, пока выровняйтесь (выровняйте) - потом вернитесь к исходной форме

1 ¯1+ добавьте один и отрицательный,
⍤1 используя этот список для каждой строки
 результата
{} следующей лямбды:
 аргумент
-⍨/ вычитает левую дату из правой даты,
1< маску строки, где различия превышают один (т. е. где диапазоны не являются смежными)
⍵⌿⍨ фильтр строки этой маской

Адам
источник
3

C # (интерактивный компилятор Visual C #) , 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

Perl 5, 130 байт

/-(\d+)-/,$_=strftime"%Y-%m-%d",0,0,0,$'+($|--||-1),$1-1,$`-1900 for@F=sort@F;$,lt$;&&say"$, $;"while($,,$;)=@F[++$i,$i+1],++$i<@F

TIO

Науэль Фуйе
источник
2

Баш, 125 байт

set `sort<<<$1`;shift;for a;{ s=$[x++%2?-1:1]day;c=`date -d$a\ $s +%Y-%m-%d`;[ $p ]&&{ [[ $p < $c ]]&&echo $p $c;p=;}||p=$c;}

TIO

Науэль Фуйе
источник
2

PHP, 208 197 190 177 байт

Hunky Chunky сидел на стене ... хотя новый подход имел некоторый потенциал для игры в гольф.

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]]);}

Функция принимает массив диапазонов [start, end] в формате 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
        ]);
}
Titus
источник
1

Желе , 13 байт

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

У желе (в настоящее время) нет встроенных дат, поэтому используются дни с тех пор.
Входной список диапазонов (пары целых чисел) может быть в смешанном порядке и в смешанных направлениях.
Результатом является список возрастающих диапазонов в порядке возрастания.

Попробуйте онлайн! (форматы нижнего колонтитула, чтобы показать пустой список как[])

Как?

Примечание. Это зависит от гарантии того, что «во входных данных нет перекрывающихся дат», как указано в правилах.

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?
Джонатан Аллан
источник
Интересно, я не знал, что у Желе не было поддержки свиданий. Это обычный подход? Использовать дни с эпохи?
Dana
Дни с тех пор, как я полагаю, используются некоторыми системами (возможно, Excel). Секунды с начала эпохи (например, Unix). Я просто пошел с чем-то, что, кажется, покрывает требования, хотя и довольно слабо.
Джонатан Аллан
Бу, вы можете рассчитать даты вручную . ; P Дни, начиная с эпохи, действительно чаще используются для языков, которые не поддерживают даты. Я чувствую, что это облегчает эту задачу, однако.
Кевин Круйссен
@KevinCruijssen хех, согласился.
Джонатан Аллан
1

C # (интерактивный компилятор Visual C #) , 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);
  }
}
Dana
источник
128
только для ASCII
Ха-ха - если вы печатаете как Embodiment of Ignorance, вы можете стать очень маленьким - попробуйте онлайн!
Dana
Ницца. Также их метод ввода для последних двух
только 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,]

Попробуйте онлайн!

В качестве входных данных используется фрейм данных диапазонов дат, а фрейм данных выводится с пропущенными диапазонами. Я вполне уверен, что это может быть больше в гольфе, но я столкнулся с проблемами c, cbindи другие раздеваются на свидании.

Ник Кеннеди
источник