Encontrar brechas en rangos de fechas

15

Dada una lista de rangos de fechas rcomo entrada, salida o devolución de cualquier rango que no se encuentre r.

Por el bien de este ejemplo, la entrada estará en YYYY-MM-DDformato.

Digamos que tiene tres rangos de fechas:

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

Puedes ver que hay una brecha entre 2019-04-05y 2019-06-01.

El resultado será esa brecha: [2019-04-06, 2019-05-31]

Reglas

  • La entrada y la salida pueden estar en cualquier fecha razonable o formato de recopilación, siempre que sea coherente.
  • Suponga que la entrada no está ordenada.
  • Su rango de fechas no tiene que ser [latest, earliest], pero sí tiene que seguir la regla 2.
  • Suponga que no hay fechas superpuestas en la entrada

Casos de prueba:

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

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


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

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


Entrada: [[2019-01-01, 2019-02-01],[2019-02-02, 2019-03-02],[2019-03-03, 2019-07-01]]

Salida: []


Entrada: [[2019-01-01, 2019-02-01], [2019-11-02, 2019-11-20]]

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


Entrada: [[2019-01-01, 2019-02-01],[2019-02-03, 2019-04-05]]

Salida: [[2019-02-02, 2019-02-02]]o[[2019-02-02]]

Oliver
fuente
55
Sugiero reelaborar todas las fechas de ejemplo en formato ISO, YYYY-MM-DDya que el formato actual es extraño para muchas personas y se hizo aún más difícil de analizar debido al uso de pequeños días del mes≤12.
Adám
@ Adám Buena idea, actualizada.
Oliver
¿Podemos tomar datos como fechas de automatización OLE de .NET?
Adám
@ Adám Sí. Cualquier formato de fecha razonable es aceptable.
Oliver
1
¿Se ordenarán las fechas? Además, dentro de un par de fechas, ¿será la última la última?
Encarnación de la ignorancia

Respuestas:

4

APL (Dyalog Extended) , 28 25 24 bytes

Función de prefijo tácito anónimo. El argumento y el resultado son matrices de 2 columnas de números de días desde una época, y cada fila representa un rango.

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

Pruébalo en línea! La función de Inpreprocesador se convierte de una lista de pares de listas de 3 elementos (fechas en orden ISO) a una matriz de 2 columnas de IDN, números de días internacionales (días desde 1899-12-31). La Outfunción de posprocesador se convierte de una matriz de IDN a una matriz de listas de 3 elementos.

 ordenar filas ascendentes

1⌽ gire cíclicamente las fechas un paso hacia la izquierda
⍢, mientras está desarmado (aplanado); luego, vuelva a dar forma a la forma original

1 ¯1+ agregue uno y uno negativo
⍤1 usando esa lista para cada fila
 del resultado de
{... } la siguiente lambda:
 el argumento
-⍨/ resta la fecha de la izquierda de la fecha de la derecha, la
1< máscara de fila donde las diferencias exceden un
⍵⌿⍨ filtro (es decir, donde los rangos no son adyacentes) las filas por esa máscara

Adán
fuente
3

C # (compilador interactivo de Visual C #) , 108 bytes

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

Salidas imprimiendo en el formato DD/MM/YYYY 12:00:00 AMDD/MM/YYYY 12:00:00 AM. Causará una excepción IndexOutOfRange, que está bien por meta consenso.

Pruébalo en línea!

Si tomamos datos en forma de días desde la época de Unix, podemos reducir esto a ...

83 bytes

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

Pruébalo en línea!

Podemos jugar golf aún más con la /u:System.Arraybandera, por ...

78 bytes

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

Pruébalo en línea!

Encarnación de la ignorancia
fuente
2

Perl 5, 130 bytes

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

Bash, 125 bytes

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
fuente
2

PHP, 208 197 190 177 bytes

Hunky Chunky se sentó en una pared ... aunque el nuevo enfoque tenía bastante potencial de golf.

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

La función toma una variedad de rangos [inicio, fin] en formato ISO, imprime intervalos de intervalo. Pruébalo en línea .


Descompostura

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
fuente
1

Jalea , 13 bytes

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

Jelly (actualmente) no tiene fechas incorporadas, por lo que utiliza días desde la época.
La lista de entrada de rangos (pares de enteros) puede estar en orden mixto y en direcciones mixtas.
El resultado es una lista de rangos ascendentes en orden ascendente.

Pruébalo en línea! (formatos de pie de página para mostrar una lista vacía como[])

¿Cómo?

Nota: Esto se basa en la garantía de que "no hay fechas superpuestas en la entrada" como se indica en las reglas.

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
fuente
Interesante, no sabía que Jelly no tenía soporte para citas. ¿Es este el enfoque habitual? ¿Usar días desde época?
dana
Días desde la época es, creo, utilizado por algunos sistemas (tal vez Excel). Segundos desde la época es más común (por ejemplo, Unix). Acabo de ir con algo que parece cubrir los requisitos, aunque de manera bastante laxa.
Jonathan Allan
Boo, podrías calcular las fechas manualmente . ; P Días ya que epoch se usa con mayor frecuencia para idiomas que no admiten fechas. Sin embargo, siento que hace que este desafío sea MUCHO más fácil.
Kevin Cruijssen
@KevinCruijssen je, de acuerdo.
Jonathan Allan
1

C # (compilador interactivo de Visual C #) , 103 bytes

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

Pruébalo en línea!

La entrada es una lista de tuplas de fecha de inicio / finalización. Emite cada rango faltante a 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
fuente
128
ASCII solo
Ja, si imprimes como Encarnación de la ignorancia, puedes ser realmente pequeño. ¡ Pruébalo en línea!
dana
Agradable. También wtf su método de entrada para los dos últimos
solo ASCII
Bueno, en realidad ... eso parece realmente incorrecto
solo ASCII
1
Sí, eso se ve bien ahora
solo ASCII
1

R , 88 bytes

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

Pruébalo en línea!

Esto toma un marco de datos de rangos de fechas como entrada y genera un marco de datos con los rangos que faltan. Estoy bastante seguro de que esto se podría jugar más, pero tuve problemas con c,cbind entre otros pelar la clase fecha.

Nick Kennedy
fuente