Znajdowanie luk w zakresach dat

15

Podano listę zakresów dat rjako dane wejściowe, wyjściowe lub zwracające wszelkie zakresy, których nie znaleziono w r.

Na potrzeby tego przykładu dane wejściowe będą miały YYYY-MM-DDformat.

Załóżmy, że masz trzy zakresy dat:

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

Widać, że istnieje przerwa między 2019-04-05i 2019-06-01.

Wynik będzie taki: [2019-04-06, 2019-05-31]

Zasady

  • Dane wejściowe i wyjściowe mogą mieć dowolny rozsądny format daty lub kolekcji, o ile są spójne.
  • Załóż, że dane wejściowe nie są uporządkowane.
  • Twój zakres dat nie musi być [latest, earliest], ale musi być zgodny z regułą 2.
  • Załóżmy, że dane wejściowe nie pokrywają się

Przypadki testowe:

Wejście: [[2019-01-01, 2019-02-01],[2019-02-02, 2019-04-05],[2019-06-01, 2019-07-01]]

Wynik: [[2019-04-06, 2019-05-31]]


Wejście: [[2019-01-01, 2019-02-01],[2018-02-02, 2018-04-05],[2019-06-01, 2019-07-01]]

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


Wejście: [[2019-01-01, 2019-02-01],[2019-02-02, 2019-03-02],[2019-03-03, 2019-07-01]]

Wynik: []


Wejście: [[2019-01-01, 2019-02-01], [2019-11-02, 2019-11-20]]

Wynik: [[2019-02-02, 2019-11-01]]


Wejście: [[2019-01-01, 2019-02-01],[2019-02-03, 2019-04-05]]

Wyjście: [[2019-02-02, 2019-02-02]]lub[[2019-02-02]]

Oliver
źródło
5
Proponuję przerobić wszystkie przykładowe daty do formatu ISO, YYYY-MM-DDponieważ obecny format jest obcy dla wielu osób, a jeszcze trudniejszy do przeanalizowania ze względu na użycie małych dni miesiąca ≤12.
Adám
@ Adám Dobry pomysł, zaktualizowany.
Oliver
Czy możemy przyjąć dane jako daty automatyzacji OLE .NET?
Adám
@ Adám Tak. Dowolny rozsądny format daty jest dopuszczalny.
Oliver
1
Czy terminy zostaną zamówione? Czy w ciągu kilku dat późniejsza będzie ostatnia?
Embodiment of Ignorance

Odpowiedzi:

4

APL (Dyalog Extended) , 28 25 24 bajtów

Anonimowa ukryta funkcja prefiksu. Argument i wynik to 2-kolumnowe macierze liczb dni od epoki, każdy wiersz reprezentuje zakres.

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

Wypróbuj online! Funkcja Inpreprocesora konwertuje z listy par list 3-elementowych (daty w kolejności ISO) na 2-kolumnową macierz IDN, międzynarodowe numery dni (dni od 1899-12-31). Funkcja Outpostprocesora konwertuje z macierzy IDN na macierz list 3-elementowych.

 sortuj rzędy rosnąco

1⌽ cyklicznie obracaj daty o jeden krok w lewo,
⍢, gdy jesteś zniszczony (spłaszczony) - następnie przekształć z powrotem do pierwotnego kształtu

1 ¯1+ dodaj jeden i jeden ujemny,
⍤1 używając tej listy dla każdego wiersza
 wyniku
{} następującej lambdy:
 argument
-⍨/ odejmij datę po lewej stronie od daty po prawej stronie,
1< maskę w wierszach, gdzie różnice przekraczają jeden (tzn. gdy zakresy nie sąsiadują)
⍵⌿⍨ filtr rzędy przy tej masce

Adám
źródło
3

C # (interaktywny kompilator Visual C #) , 108 bajtów

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

Wysyła przez wydruk w formacie DD/MM/YYYY 12:00:00 AMDD/MM/YYYY 12:00:00 AM. Powoduje wyjątek IndexOutOfRange, który jest w porządku zgodnie z meta konsensusem.

Wypróbuj online!

Jeśli weźmiemy wkład w postaci dni od epoki unixu, możemy sprowadzić to do ...

83 bajty

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

Wypróbuj online!

Możemy zagrać w golfa jeszcze bardziej z /u:System.Arrayflagą, ponieważ ...

78 bajtów

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

Wypróbuj online!

Wcielenie ignorancji
źródło
2

Perl 5, 130 bajtów

/-(\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

Nahuel Fouilleul
źródło
2

Bash, 125 bajtów

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

Nahuel Fouilleul
źródło
2

PHP, 208 197 190 177 bajtów

gruby, gruby siedział na ścianie ... choć nowe podejście miało całkiem spory potencjał golfowy.

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

funkcja przyjmuje tablicę zakresów [początek, koniec] w formacie ISO, drukuje interwały odstępów. Wypróbuj online .


awaria

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
        ]);
}
Tytus
źródło
1

Galaretka , 13 bajtów

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

Galaretka (obecnie) nie ma wbudowanych dat, więc korzysta z dni od epoki.
Lista wejściowa zakresów (par liczb całkowitych) może być w kolejności mieszanej i kierunkach mieszanych.
Wynikiem jest lista rosnących zakresów w kolejności rosnącej.

Wypróbuj online!(formaty stopek, aby wyświetlić pustą listę jako [])

W jaki sposób?

Uwaga: Opiera się to na zapewnieniu, że „dane wejściowe nie nakładają się”, zgodnie z zasadami.

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?
Jonathan Allan
źródło
Co ciekawe, nie wiedziałem, że Jelly nie ma wsparcia daty. Czy to jest zwykłe podejście? Używać dni od epoki?
dana
Wierzę, że dni od epoki są używane przez niektóre systemy (być może Excel). Sekundy od epoki są bardziej powszechne (np. Unix). Po prostu poszedłem z czymś, co wydaje się pokrywać wymagania, choć dość luźne.
Jonathan Allan
Boo, możesz ręcznie obliczyć daty . ; P Dni od epoki są rzeczywiście częściej używane dla języków, które nie obsługują dat. Wydaje mi się, że dzięki temu to wyzwanie jest DUŻO łatwiejsze.
Kevin Cruijssen
@KevinCruijssen heh, zgodził się.
Jonathan Allan
1

C # (interaktywny kompilator Visual C #) , 103 bajty

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

Wypróbuj online!

Dane wejściowe to lista krotek daty początkowej / końcowej. Wysyła każdy brakujący zakres do 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
źródło
128
Tylko ASCII,
Hah - jeśli drukujesz jak Embodiment of Ignorance, możesz stać się naprawdę mały - wypróbuj online!
dana
Ładny. Również wtf ich metoda wprowadzania dla dwóch ostatnich
tylko ASCII
Cóż, właściwie ... to wygląda naprawdę niepoprawnie
tylko ASCII
1
Tak, teraz wygląda dobrze
tylko ASCII
1

R , 88 bajtów

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,]

Wypróbuj online!

Pobiera to ramkę danych zakresów dat jako dane wejściowe i wysyła ramkę danych z brakującymi zakresami. Jestem dość pewien, że to może być grałem więcej, ale wpadłem na problemy z c, cbindi innych odpędzania klasy Date.

Nick Kennedy
źródło