Unión de intervalos

15

Dada una lista de intervalos, realice la unión de ellos y reduzca las superposiciones. Eso significa que las partes superpuestas se reducen. ( [a, b] U [c, d] = [a, d]si b > c) Suponiendo todo a <b en todos los intervalos [a, b]. Implementar en función de una lista de intervalos de entrada -> lista de intervalos de salida. El código más corto gana. No puede usar ninguna biblioteca existente.

Aclaraciones:

  • Los intervalos abiertos y cerrados no se distinguen.
  • Intervalos para números reales, no enteros. ( [2, 3], [4, 5] -> [2, 3], [4, 5])
  • No es necesario ordenar los intervalos de salida
  • El orden si las entradas no importan
  • Las entradas ilegales son solo [a, b]donde b >= a, no tiene nada que ver con el orden de los intervalos de entrada y el número de intervalos de entrada.
  • No es necesario que muestre un mensaje de error sobre comportamientos indefinidos

Ejemplos (con líneas numéricas)

 [2, 4], [7, 9] --> [2, 4], [7, 9]
   234
        789
-> 234  789

 [1, 5], [2, 10] --> [1, 10] (overlapping [2, 5] reduced)

   12345
    234567890
-> 1234567890
 [2, 4], [3, 6], [8, 9] -> [2, 6], [8, 9]
   234
    3456
         89
-> 23456 89

 [4, 2], [2, 2] -> (undefined behavior: against the assumption)
Ming-Tang
fuente
3
¿Los intervalos siempre se ordenarán como están en sus ejemplos?
Peter Olson
1
¿Por qué no se superponen [2, 3], [4, 5] o [2, 4], [4, 5]? Ambos rinden 2345.
mellamokb
2
¿Son los intervalos solo en el conjunto de enteros?
Lowjacker
2
Necesitamos alguna aclaración: 1) ¿Es [4,5], [1,2] entrada legal? 2) ¿Debería la salida de [2,3], [4,5] ser [2,5] o [2,3], [4,5]? 3) ¿Debería la salida de [2,3], [3,4] ser [2,4] o [2,3], [3,4]?
MtnViewMark
1
Gracias por las aclaraciones, pero "No es necesario ordenar", ¿qué significa? ¿Que la salida no necesita ser ordenada? ¿O que la entrada ya está ordenada?
MtnViewMark

Respuestas:

2

GolfScript, 32

[{1$1$*-2%~2->{*$[(\)\;]}{}if}*]
  • Agregue 2 caracteres si prefiere un bloque, 4 si prefiere un bloque con nombre.
  • La entrada y la salida son una matriz de pares, por ejemplo [[2 4] [3 5]]
  • Asume que la entrada está ordenada por el primer elemento.
  • Compacta rangos "adyacentes" ([2 4] [5 6] -> [2 6])
  • Primer esfuerzo de GolfScript. Asesoramiento y fruta podrida apreciada.

Programa de prueba completo:

[~](;2/[{1$1$*-2%~2->{*$[(\)\;]}{}if}*]`

Ejemplo de invocación:

ruby golfscript.rb intervals.gs <<EOF
3
2 4
3 6
8 9
EOF
# Expected output: [[2 6] [8 9]]
Jesse Millikan
fuente
4

Haskell (103)

Creo que es demasiado detallado para Haskell. Gracias a Hoa Long Tam por su función de clasificación.

m%(x:y)|x>m=m:x:y|2>1=x:m%y;m%_=[m]
(x:y)?l|x`elem`l=y?l|0<1=x:y?(x:l);a?_=a
a∪b=foldr(%)[](a++b)?[]

En Haskell, un intervalo de aa bse denota por [a..b]. Mi notación es muy similar a la notación matemática. Úselo así:

[a..b] ∪ [c..d] ∪ ... ∪ [y..z]
FUZxxl
fuente
3

Ok, aquí está mi crack de 250 caracteres.

void n(int a[]){if(!a[2])return;if(a[2]<=a[1]){if(a[1]<a[3])a[1]=a[3];
int *b=a+2;while(*b=*(b+2))++b;n(a);}n(a+2);}
void m(int a[]){if(!a[2])return;if(a[0]>a[2]){int s=a[0],t=a[1];
a[0]=a[2];a[2]=s;a[1]=a[3];a[3]=t;m(a+2);m(a);n(a);}m(a+2);n(a+2);}

La función toma una matriz int y opera en ella in situ. La matriz termina en un 0, y los intervalos pueden darse en cualquier orden.

Salida de muestra:

input list: (7,9) (5,6) (1,4) (15,18) (13,16) (2,3) (8,11) 
output list: (1,4) (5,6) (7,11) (13,18) 

Programa de muestra:

#include <stdio.h>

void n(int a[]){if(!a[2])return;if(a[2]<=a[1]){if(a[1]<a[3])a[1]=a[3];
int *b=a+2;while(*b=*(b+2))++b;n(a);}n(a+2);}
void m(int a[]){if(!a[2])return;if(a[0]>a[2]){int s=a[0],t=a[1];
a[0]=a[2];a[2]=s;a[1]=a[3];a[3]=t;m(a+2);m(a);n(a);}m(a+2);n(a+2);}


/*
void n(int a[])
{
    if(!a[2])return;
    if(a[2]<=a[1]) {
        if(a[1]<a[3])
            a[1]=a[3];
        int *b=a+2;
        while(*b=*(b+2))++b;
        n(a);
    }
    n(a+2);
}

void m(int a[])
{
    if(!a[2])return;
    if(a[0]>a[2]) {
        int s=a[0],t=a[1];
        a[0]=a[2];a[2]=s;
        a[1]=a[3];a[3]=t;
        m(a+2);m(a);n(a);
    }
    m(a+2);n(a+2);
}
*/

void p(int a[]) 
{
    if(!*a) {
        printf("\n");
        return;
    }
    printf("(%d,%d) ",a[0],a[1]);
    p(a+2);
}

int main (int argc, const char * argv[]) 
{
    // Code golf entry
    // Interval Merging

    int a[] = {7,9,5,6,1,4,15,18,13,16,2,3,8,11,0};
    printf( "input list: " ); p(a);
    m(a);
    printf( "output list: " ); p(a);

    return 0;
}
Jonathan Watmough
fuente
perform the union of themdebería conducir a (1,11) (13,18), ¿no?
Usuario desconocido
@user unknown: habría pensado lo mismo, pero creo que las instrucciones dicen que solo se combinan si se superponen. Entonces (1, 4) (5, 6) no se combinan de acuerdo con la regla ([a, b] U [c, d] = [a, d] if b > c). Y para el caso, incluso (1, 5) (5, 6) no se combinarían.
mellamokb
"Dada una lista de intervalos, realice la unión de ellos y reduzca las superposiciones", andreduzca las superposiciones, no if they overlap. OK: los siguientes that means ...puntos nuevamente en la dirección opuesta.
usuario desconocido el
@usuario desconocido: estoy de acuerdo. Por eso he comentado al respecto sobre la pregunta. Esperemos que el OP responda :)
mellamokb
2

Python, 100 caracteres

def f(L):R=sorted(set(p for p in sum(L,[])if 1-any(x<p<y for x,y in L)));return zip(R[::2],R[1::2])
print f([[2, 4], [7, 9]])
print f([[1, 5], [2, 10]])
print f([[3, 6], [2, 4], [8, 9]])
print f([[1, 5], [3, 5], [4, 5]])

genera

[(2, 4), (7, 9)]
[(1, 10)]
[(2, 6), (8, 9)]
[(1, 5)]

Toma todos los puntos finales de los intervalos, elimina los que están estrictamente dentro de otro intervalo, los unifica y los ordena, y los empareja.

Keith Randall
fuente
98 bytes
movatica
2

Haskell, 55 caracteres

v(q@(a,b):p@(c,d):r)|c>b=q:v(p:r)|1<3=v((a,d):r);v x=x

Si la entrada no está ordenada, entonces 88 caracteres:

p@(a,b)§(q@(c,d):r)|b<c=p:q§r|a>d=q:p§r|1<3=(min a c,max b d)§r;p§_=[p]
u i=foldr(§)[]i

Pruebas de funcionamiento:

ghci> testAll v
pass: [(2,4),(7,9)] --> [(2,4),(7,9)]
pass: [(1,5),(2,10)] --> [(1,10)]
pass: [(2,4),(3,6),(8,9)] --> [(2,6),(8,9)]
ghci> testAll u
pass: [(2,4),(7,9)] --> [(2,4),(7,9)]
pass: [(1,5),(2,10)] --> [(1,10)]
pass: [(2,4),(3,6),(8,9)] --> [(2,6),(8,9)]

Supongo que "no se puede usar ninguna biblioteca existente" impide importar Listy llamar sort. Si eso fuera legal, la versión sin clasificar tendría solo 71 caracteres.

MtnViewMark
fuente
Importar Listdesde el paquete Haskell98sería suficiente en mi humilde opinión.
FUZxxl
2

Scala, 272 caracteres

type p=List[(Int,Int)];def f(l:p):p={var(a,s,c,o)=(new Array[Int]((l map(x=>x._2)max)+1),0,0,List[Int]());l map(x=>(a(x._1)+=1,a(x._2)-=1));while(c<a.size){s+=a(c);if(a(c)==1&&s==1)o=o:+c;if(a(c)== -1&&s==0)o=o:+c;c+=1};return(o.grouped(2).map(x=>(x.head,x.last)).toList)}

Uso:

object Intervals2 extends Application
{
    type p=List[(Int,Int)];def f(l:p):p={var(a,s,c,o)=(new Array[Int]((l map(x=>x._2)max)+1),0,0,List[Int]());l map(x=>(a(x._1)+=1,a(x._2)-=1));while(c<a.size){s+=a(c);if(a(c)==1&&s==1)o=o:+c;if(a(c)== -1&&s==0)o=o:+c;c+=1};return(o.grouped(2).map(x=>(x.head,x.last)).toList)}

    print(f(List((1,2),(3,7),(4,10))))
}

Crea una matriz e inserta un 1 para cada inicio de intervalo y un -1 para cada final de intervalo. Luego, recorre la matriz agregando los valores a un contador que genera un inicio cada vez que el contador pasa de 0 a 1 y un final cuando pasa de 1 a 0. Probablemente sea innecesariamente complicado.

Salida:

List((1,2), (3,10))
Gareth
fuente
1

Perl (146) (92) (90)

Golfé hasta 90 caracteres, usando creativamente el motor regex

sub u {mapa $ h [$ _] = 1, @ $ _ [0] .. @ $ _ [1] para @_; $ w. = $ _ + 0 para @ h; presione @ r, $ - [0 ], $ + [0] -1 mientras $ w = ~ / 1 + / g; @r}

ejemplo de uso:

my @ out1 = u ([1, 5], [2, 10]); # (1,10)
my @ out2 = u ([2, 4], [3, 6], [8, 9]); # (2, 6, 8, 9)

Vamos a explicar un poco este código.

Esta subrutina recibe una matriz de arrayrefs, cada una de las cuales apunta a una matriz que contiene dos elementos, inicio y final del intervalo: ([2, 4], [3, 6], [8, 9])

Para cada aref, generamos una matriz de elementos del primero al último ($_->[0] .. $_->[1]). luego usamos map para establecer elementos de dichos índices en @h a 1.

para (@_) {
    mapa {$ h [$ _] = 1} ($ _-> [0] .. $ _-> [1]);
}

después de esto, @hcontendrá unos (para intervalos) o undefs, representados a continuación como guiones para mayor claridad.

índice: 0 1 2 3 4 5 6 7 8 9
@h: - - 1 1 1 1 1 - 1 1

luego construimos una cadena de @h, agregando 0 para reemplazar undefs con algo más útil (undef + 0 = 0).

$w .= $_+0 for @h;

$ w contiene 011111011ahora.

Es hora de abusar un poco del motor regex.

push @r, ($-[0], $+[0]-1) while $w=~/1+/g;

después de coincidencias exitosas, las matrices @ - y @ + contienen respectivamente la posición de inicio y finalización de cada coincidencia; El elemento 0 se usa para toda la partida, primero por $ 1, segundo por $ 2 y así sucesivamente.

$+[0] en realidad contiene la posición del primer carácter no coincidente, por lo que tenemos que restar uno.

@rcontiene (2, 6, 8, 9)ahora.

@r

para hacer que el sub regrese @r.

perl chino goth
fuente
No funciona para [2,3],[4,5]rendimientos de números reales2 5
Xcali
1

Scala 305 279 caracteres sin invocación:

type I=(Int,Int)
def l(p:I,q:I)=if(p._1<q._1)true else if(p._1>q._1)false else p._2<q._2
def r(l:List[I]):List[I]=l match{case x::y::z=>{if(y._1<=x._2&&y._2>x._2)(x._1,y._2)::r(z)else
if(y._1<=x._2&&y._2<=x._2)x::r(z)else  
x::r(y::z)}case _=>l}
def c(v:List[I])=r(v.sortWith(l))

invocación:

val i=List((7,9),(5,6),(1,4),(15,18),(13,16),(2,3),(8,11))
c(i)
res0: List[(Int, Int)] = List((1,4), (5,6), (7,11), (13,18))
usuario desconocido
fuente
1

Brachylog , 12 bytes

⟦₂ᵐcod~c~⟦₂ᵐ

Pruébalo en línea!

Una solución deliciosamente declarativa, que toma la entrada como una lista de listas a través de la variable de entrada y genera una lista de listas a través de la variable de salida.

        ~⟦₂ᵐ    The output is a list of intervals, where each interval is a range in
      ~c        the smallest partition of
  ᵐ             each element of the input
⟦₂              converted to an inclusive range,
   c            concatenated,
    o           sorted,
     d          and deduplicated
        ~⟦₂ᵐ    for which each element of the partition is a range.
Cadena no relacionada
fuente
1

Clojure, 138 bytes

#(let[S(set(apply mapcat range(apply map list %)))Q(sort S)](map list(for[s Q :when(not(S(dec s)))]s)(for[s(map inc Q):when(not(S s))]s)))

Esto se acorta a 119 bytes si la entrada es más flexible, es decir, una lista de puntos de inicio de intervalos Y una lista de puntos finales de intervalos:

#(let[S(set(mapcat range % %2))Q(sort S)](map list(for[s Q :when(not(S(dec s)))]s)(for[s(map inc Q):when(not(S s))]s)))

Tiene que haber una mejor manera.

NikoNyrh
fuente
1

Japt , 18 bytes

Esto se siente demasiado tiempo. E / S ordenada, matriz 2D de intervalos.

c_ròÃòÈaY Éîg[TJ]

Intentalo

Lanudo
fuente
0

Perl 5 -MList::Util=max -n , 89 bytes

@r=/\S+/g;map{/ /;$`<=$r[1]?$r[1]=max@r,$'*1:(say"@r")|(@r=($`,$'))}sort{$a-$b}<>;say"@r"

Pruébalo en línea!

Xcali
fuente