Calcule el superconjunto

18

Su tarea aquí es simple:

Dada una lista de conjuntos enteros, encuentre la unión de conjuntos. En otras palabras, encuentre la lista más corta de conjuntos enteros que contenga todos los elementos en la lista original de conjuntos (pero no otros elementos). Por ejemplo:

[1,5] and [3,9] becomes [1,9] as it contains all of the elements in both [1,5] and [3,9]
[1,3] and [5,9] stays as [1,3] and [5,9], because you don't want to include 4

Los conjuntos se anotan usando notación de rango: [1,4]significa los enteros 1,2,3,4. Los conjuntos también pueden ser ilimitados: [3,]significa todos los enteros >= 3y [,-1]significa todos los enteros <= -1. Se garantiza que el primer elemento del rango no será mayor que el segundo.

Puede optar por tomar conjuntos en notación de cadena, o puede usar tuplas de 2 elementos, usando un constante no entero como el valor "infinito". Puede usar dos constantes distintas para representar el límite superior infinito y el límite inferior infinito. Por ejemplo, en Javascript, puede usar [3,{}]para anotar todos los enteros >= 3, siempre y cuando lo haya usado {}en todos los casos de prueba.

Casos de prueba:

[1,3]                     => [1,3]
[1,]                      => [1,]
[,9]                      => [,9]
[,]                       => [,]
[1,3],[4,9]               => [1,9]
[1,5],[8,9]               => [1,5],[8,9]
[1,5],[1,5]               => [1,5]
[1,5],[3,7]               => [1,7]
[-10,7],[1,5]             => [-10,7]
[1,1],[2,2],[3,3]         => [1,3]
[3,7],[1,5]               => [1,7]
[1,4],[8,]                => [1,4],[8,]
[1,4],[-1,]               => [-1,]
[1,4],[,5]                => [,5]
[1,4],[,-10]              => [1,4],[,-10]
[1,4],[,]                 => [,]
[1,4],[3,7],[8,9],[11,20] => [1,9],[11,20]

Este es el , ¡así que haga su respuesta lo más breve posible!

Nathan Merrill
fuente
Relacionado
Nathan Merrill
1
¿Puedo usar Infinityen su lugar {}?
Luis felipe De jesus Munoz
¿Podemos tomar la entrada como valores flotantes, por ejemplo, en [1.0, 3.0]lugar de [1, 3]?
AdmBorkBork
Mientras los trates como enteros, sí. En otras palabras [1.0, 3.0], [4.0, 5.0], todavía debería convertirse en[1.0, 5.0]
Nathan Merrill
Si su idioma no puede tomar Infinityy -Infinitycomo entrada, ¿está permitido tomar -999999y 999999(o incluso más grande / más pequeño) en su lugar?
Kevin Cruijssen

Respuestas:

7

R + intervals, 90 87 81 bytes

function(...)t(reduce(Intervals(rbind(...),type="Z")))+c(1,-1)
library(intervals)

Pruébalo en línea!

La entrada es una lista de intervalos. -Infy Infson R incorporados para menos / más infinito. La salida es una matriz de columnas de intervalos.

Por lo general, no soy fanático del uso de bibliotecas no estándar, pero esta fue divertida. TIO no tiene intervalsinstalado. Puede probarlo en su propia instalación o en https://rdrr.io/snippets/

El intervalspaquete admite type = "Z"intervalos reales y enteros ( ) y la reducefunción está integrada para lo que el desafío quiere, pero la salida parece tener intervalos predeterminados para abrirse, por lo que es necesaria para obtener el resultado deseado.close_intervals +c(1,-1)

La versión anterior tenía ejemplos en la lista de listas que podrían ser convenientes, así que he dejado el enlace aquí.

ngm
fuente
Creo que se puede ahorrar unos pocos bytes: function(...)close_intervals(reduce(Intervals(rbind(...),type="Z"))). O incluso mejor, puede verificar con op si permiten una matriz como entrada.
JayCe
1
Estaba anoche literalmente despierto en la cama pensando "debe haber habido una mejor manera de hacer una matriz con los vectores de entrada". Creo que el desafío es mejor dejar la entrada como está. Pero fue divertido tener reducey Reduceallí.
ngm
¡Me encanta la cosa de "doble reducción"! simplemente no es lo suficientemente golfístico;) ¿Qué hay de modificar los intervalos abiertos de esta manera f=function(...)t(reduce(Intervals(rbind(...),type="Z")))+c(1,-1):?
JayCe
6

JavaScript (ES6), 103 bytes

Guardado 1 byte gracias a @Shaggy
Guardado 1 byte gracias a @KevinCruijssen

Espera +/-Infinityvalores infinitos.

a=>(a.sort(([p],[P])=>p-P).map(m=M=([p,q])=>p<M+2?M=q>M?q:M:(b.push([m,M]),m=p,M=q),b=[]),b[0]=[m,M],b)

Pruébalo en línea!

¿Cómo?

Primero clasificamos los intervalos por su límite inferior, de menor a mayor. Los límites superiores se ignoran.

Luego iteramos sobre los intervalos ordenados [pn,qn] , mientras hacemos un seguimiento de los límites inferior y superior actuales m y M , inicializados en p1 y q1 respectivamente.

Para cada intervalo [pn,qn] :

  • Si pnM+1 : este intervalo se puede combinar con los anteriores. Pero podemos tener un nuevo límite superior, por lo que actualizamosM almax(M,qn) .
  • De lo contrario: hay una brecha entre los intervalos anteriores y este. Creamos un nuevo intervalo [m,M] y actualizamosm yM apn yqn respectivamente.

Al final del proceso, creamos un último intervalo con los límites actuales [m,M] .

Comentado

a => (                  // a[] = input array
  a.sort(([p], [P]) =>  // sort the intervals by their lower bound; we do not care about
    p - P)              // the upper bounds for now
  .map(m = M =          // initialize m and M to non-numeric values
    ([p, q]) =>         // for each interval [p, q] in a[]:
    p < M + 2 ?         //   if M is a number and p is less than or equal to M + 1:
      M = q > M ? q : M //     update the maximum M to max(M, q)
    : (                 //   else (we've found a gap, or this is the 1st iteration):
      b.push([m, M]),   //     push the interval [m, M] in b[]
      m = p,            //     update the minimum m to p
      M = q             //     update the maximum M to q
    ),                  //
    b = []              //   start with b[] = empty array
  ),                    // end of map()
  b[0] = [m, M], b      // overwrite the 1st entry of b[] with the last interval [m, M]
)                       // and return the final result
Arnauld
fuente
p<=M+1puede ser p<M+2?
Kevin Cruijssen
@KevinCruijssen La perdí por completo ... ¡Gracias!
Arnauld
4

Pitón 2 , 118 113 112 111 106 105 104 101 bytes

x=input()
x.sort();a=[];b,c=x[0]
for l,r in x:
 if l>c+1:a+=(b,c),;b,c=l,r
 c=max(c,r)
print[(b,c)]+a

Ahorré un byte gracias a Mr.Xcoder, uno gracias a Jonathan Frech y tres gracias a Dead Possum.
Pruébalo en línea!


fuente
(b,c),Guarda un byte.
Sr. Xcoder
Huh, pensé que ya lo había intentado.
¿No gsignifica que su función fno es reutilizable y, por lo tanto, no es válida?
Neil
@Neil Probablemente, pero eso fue solo un remanente de un intento anterior.
1
También podría hacer los returncambiosprint para otro byte.
Jonathan Frech
2

Rubí , 89 76 bytes

->a{[*a.sort.reduce{|s,y|s+=y;y[0]-s[-3]<2&&s[-3,3]=s.max;s}.each_slice(2)]}

Pruébalo en línea!

Ordene la matriz, luego aplánela agregando todos los rangos al primero: si un rango se superpone al anterior, descarte 2 elementos de los últimos 3 (manteniendo solo el máximo).

Despliega todo al final.

GB
fuente
1

Pascal (FPC) , 367 362 357 bytes

uses math;type r=record a,b:real end;procedure d(a:array of r);var i,j:word;t:r;begin for i:=0to length(a)-1do for j:=0to i do if a[i].a<a[j].a then begin t:=a[i];a[i]:=a[j];a[j]:=t;end;j:=0;for i:=1to length(a)-1do if a[j].b>=a[i].a-1then begin a[j].a:=min(a[i].a,a[j].a);a[j].b:=max(a[i].b,a[j].b)end else j:=j+1;for i:=0to j do writeln(a[i].a,a[i].b)end;

Pruébalo en línea!

Un procedimiento que toma una matriz dinámica de registros que consta de 2 límites de rango, modifica la matriz en su lugar y luego la escribe en la salida estándar, un rango por línea. (Perdón por esa frase retorcida).1/0 para arriba y -1/0abajo sin límite.

Versión legible

Sería bueno simplemente devolver la matriz con el número corregido de elementos, pero la matriz dinámica pasada a la función / procedimiento ya no es una matriz dinámica ... Primero encontré esto , luego está esto excelente explicación alucinante .

Esta es la mejor estructura de datos que pude encontrar para acortar el código. Si tiene mejores opciones, no dude en hacer una sugerencia.

AlexRacer
fuente
1

Wolfram Language (Mathematica) , 57 bytes

List@@(#-{0,1}&/@IntervalUnion@@(Interval[#+{0,1}]&/@#))&

Pruébalo en línea!

Toma la entrada como una lista de listas que {a,b}representan el intervalo [a,b], donde apuede -Infinityy bpuede estar Infinity.

Utiliza el incorporado IntervalUnion, pero, por supuesto, primero tenemos que masajear los intervalos para darle forma. Para pretender que los intervalos son enteros, agregamos 1 al límite superior (asegurándonos de que la unión de [1,3]y [4,9]sea[1,9] ). Al final, deshacemos esta operación y volvemos el resultado a una lista de listas.

También hay un enfoque completamente diferente, que registra 73 bytes :

NumericalSort@#//.{x___,{a_,b_},{c_,d_},y___}/;b+1>=c:>{x,{a,b~Max~d},y}&

Aquí, después de ordenar los intervalos, simplemente reemplazamos dos intervalos consecutivos por su unión siempre que sea un intervalo único, y repetimos hasta que no quede tal operación por hacer.

Misha Lavrov
fuente
1

05AB1E (heredado) , 88 79 78 bytes

g≠i˜AKïDW<UZ>VIøεAXY‚Nè:}ïø{©˜¦2ôíÆ1›.œʒíεćsO_*}P}н€g®£εø©θàDYQiA}V®нßDXQiA}Y‚

El infinito se ingresa como el alfabeto en minúsculas ( 'abcdefghijklmnopqrstuvwxyz').

Pruébelo en línea o verifique todos los casos de prueba .

Nota importante: si hubiera un real Infinityy -Infinity, en su lugar, habría sido 43 42 bytes . Tan poco más del 50%, alrededor del 30%, es una solución temporal por la falta de Infinity...

{©Dg≠i˜¦2ôíÆ1›.œʒíεćsO_*}P}н€g®£εø©θàV®нßY‚

Pruébelo en línea (con Infinityreemplazado por 9999999999y -Infinityreemplazado por-9999999999 ).

Definitivamente se puede jugar al golf sustancialmente. Al final resultó muy, muy feo, lleno de soluciones. Pero por ahora me alegra que esté funcionando.

Explicación:

Dgi          # If the length of the implicit input is NOT 1:
              #   i.e. [[1,3]] → length 1 → 0 (falsey)
              #   i.e. [[1,4],["a..z",-5],[3,7],[38,40],[8,9],[11,20],[25,"a..z"],[15,23]]
              #    → length 8 → 1 (truthy)
    ˜         #  Take the input implicit again, and flatten it
              #   i.e. [[1,4],["a..z",-5],[3,7],[38,40],[8,9],[11,20],[25,"a..z"],[15,23]]
              #    → [1,4,"a..z",-5,3,7,38,40,8,9,11,20,25,"a..z",15,23]
     AK       #  Remove the alphabet
              #   i.e. [1,4,"a..z",-5,3,7,38,40,8,9,11,20,25,"a..z",15,23]
              #    → ['1','4','-5','3','7','38','40','8','9','11','20','25','15','23']
       ï      #  Cast everything to an integer, because `K` turns them into strings..
              #   i.e. ['1','4','-5','3','7','38','40','8','9','11','20','25','15','23']
              #    → [1,4,-5,3,7,38,40,8,9,11,20,25,15,23]
        D     #  Duplicate it
         W<   #  Determine the min - 1
              #   i.e. [1,4,-5,3,7,38,40,8,9,11,20,25,15,23] → -5
           U  #  Pop and store it in variable `X`
         Z>   #  Determine the max + 1
              #   i.e. [1,4,-5,3,7,38,40,8,9,11,20,25,15,23] → 40
           V  #  Pop and store it in variable `Y`
Iø            #  Take the input again, and transpose/zip it (swapping rows and columns)
              #   i.e. [[1,4],["a..z",-5],[3,7],[38,40],[8,9],[11,20],[25,"a..z"],[15,23]]
              #    → [[1,'a..z',3,38,8,11,25,15],[4,-5,7,40,9,20,'a..z',23]]
  ε       }   #  Map both to:
   A          #   Push the lowercase alphabet
    XY       #   Push variables `X` and `Y`, and pair them into a list
       Nè     #   Index into this list, based on the index of the mapping
         :    #   Replace every alphabet with this min-1 or max+1
              #   i.e. [[1,'a..z',3,38,8,11,25,15],[4,-5,7,40,9,20,'a..z',23]]
              #    → [['1','-6','3','38','8','11','25','15'],['4','-5','7','40','9','20','41','23']]
ï             #  Cast everything to integers again, because `:` turns them into strings..
              #   i.e. [['1','-6','3','38','8','11','25','15'],['4','-5','7','40','9','20','41','23']]
              #    → [[1,-6,3,38,8,11,25,15],[4,-5,7,40,9,20,41,23]]
 ø            #  Now zip/transpose back again
              #   i.e. [[1,-6,3,38,8,11,25,15],[4,-5,7,40,9,20,41,23]]
              #    → [[1,4],[-6,-5],[3,7],[38,40],[8,9],[11,20],[25,41],[15,23]]
  {           #  Sort the pairs based on their lower range (the first number)
              #   i.e. [[1,4],[-6,-5],[3,7],[38,40],[8,9],[11,20],[25,41],[15,23]]
              #    → [[-6,-5],[1,4],[3,7],[8,9],[11,20],[15,23],[25,41],[38,40]]
   ©          #  Store it in the register (without popping)
˜             #  Flatten the list
              #   i.e. [[-6,-5],[1,4],[3,7],[8,9],[11,20],[15,23],[25,41],[38,40]]
              #    → [-6,-5,1,4,3,7,8,9,11,20,15,23,25,41,38,40]
 ¦            #  And remove the first item
              #   i.e. [-6,-5,1,4,3,7,8,9,11,20,15,23,25,41,38,40]
              #    → [-5,1,4,3,7,8,9,11,20,15,23,25,41,38,40]
  2ô          #  Then pair every two elements together
              #   i.e. [-5,1,4,3,7,8,9,11,20,15,23,25,41,38,40]
              #    → [[-5,1],[4,3],[7,8],[9,11],[20,15],[23,25],[41,38],[40]]
    í         #  Reverse each pair
              #   i.e. [[-5,1],[4,3],[7,8],[9,11],[20,15],[23,25],[41,38],[40]]
              #    → [[1,-5],[3,4],[8,7],[11,9],[15,20],[25,23],[38,41],[40]]
     Æ        #  Take the difference of each pair (by subtracting)
              #   i.e. [[1,-5],[3,4],[8,7],[11,9],[15,20],[25,23],[38,41],[40]]
              #    → [6,-1,1,2,-5,2,-3,40]
      1      #  Determine for each if they're larger than 1
              #   i.e. [6,-1,1,2,-5,2,-3,40] → [1,0,0,1,0,1,0,1]
            #  Create every possible partition of these values
              #   i.e. [1,0,0,1,0,1,0,1] → [[[1],[0],[0],[1],[0],[1],[0],[1]],
              #                             [[1],[0],[0],[1],[0],[1],[0,1]],
              #                             ...,
              #                             [[1,0,0,1,0,1,0],[1]],
              #                             [[1,0,0,1,0,1,0,1]]]
  ʒ         } #  Filter the partitions by:
   í          #   Reverse each inner partition
              #    i.e. [[1],[0,0,1],[0,1],[0,1]] → [[1],[1,0,0],[1,0],[1,0]]
    ε     }   #   Map each partition to:
     ć        #    Head extracted
              #     i.e. [1,0,0] → [0,0] and 1
              #     i.e. [1] → [] and 1
              #     i.e. [1,0,1] → [1,0] and 1
      s       #    Swap so the rest of the list is at the top of the stack again
       O      #    Take its sum
              #     i.e. [0,0] → 0
              #     i.e. [] → 0
              #     i.e. [1,0] → 1
        _     #    And check if it's exactly 0
              #     i.e. 0 → 1 (truthy)
              #     i.e. 1 → 0 (falsey)
         *    #    And multiply it with the extracted head
              #    (is only 1 when the partition has a single trailing 1 and everything else a 0)
              #     i.e. 1 and 1 → 1 (truthy)
              #     i.e. 1 and 0 → 0 (falsey)
           P  #   And check if all mapped partitions are 1
н             #  Take the head (there should only be one valid partition left)
              #   i.e. [[[1],[0,0,1],[0,1],[0,1]]] → [[1],[0,0,1],[0,1],[0,1]]
 g           #  Take the length of each inner list
              #   i.e. [[1],[0,0,1],[0,1],[0,1]] → [1,3,2,2]
   ®          #  Push the sorted pairs we've saved in the register earlier
    £         #  Split the pairs into sizes equal to the partition-lengths
              #   i.e. [1,3,2,2] and [[-6,-5],[1,4],[3,7],[8,9],[11,20],[15,23],[25,41],[38,40]]
              #    → [[[-6,-5]],[[1,4],[3,7],[8,9]],[[11,20],[15,23]],[[25,41],[38,40]]]
ε             #  Map each list of pairs to:
 ø            #   Zip/transpose (swapping rows and columns)
              #    i.e. [[1,4],[3,7],[8,9]] → [[1,3,8],[4,7,9]]
              #    i.e. [[25,41],[38,40]] → [[25,38],[41,40]]
  ©           #   Store it in the register
   θ          #   Take the last list (the ending ranges)
              #    i.e. [[25,38],[41,40]] → [41,40]
    à         #   And determine the max
              #    i.e. [41,40] → 41
     DYQi }   #   If this max is equal to variable `Y`
              #     i.e. 41 (`Y` = 41) → 1 (truthy)
         A    #    Replace it back to the lowercase alphabet
           V  #   Store this max in variable `Y`
  ®           #   Take the zipped list from the register again
   н          #   This time take the first list (the starting ranges)
              #    i.e. [[25,38],[41,40]] → [25,38]
    ß         #   And determine the min
              #    i.e. [25,38] → 25
     DXQi }   #   If this min is equal to variable `X`
              #     i.e. 25 (`X` = -6) → 0 (falsey)
         A    #    Replace it back to the lowercase alphabet
           Y #   And pair it up with variable `Y` (the max) to complete the mapping
              #    i.e. 25 and 'a..z' → [25,'a..z']
              #  Implicitly close the mapping (and output the result)
              #   i.e. [[[-6,-5]],[[1,4],[3,7],[8,9]],[[11,20],[15,23]],[[25,41],[38,40]]]
              #    → [['a..z',-5],[1,9],[11,23],[25,'a..z']]
              # Implicit else (only one pair in the input):
              #  Output the (implicit) input as is
              #   i.e. [[1,3]]
Kevin Cruijssen
fuente
1

C (sonido metálico) , 346 342 bytes

Opciones del compilador -DP=printf("(%d,%d)\n", -DB=a[i+1]y-DA=a[i]

typedef struct{int a,b;}t;s(t**x,t**y){if((*x)->a>(*y)->a)return 1;else if((*x)->a<(*y)->a)return -1;}i;f(t**a){for(i=0;A;)i++;qsort(a,i,sizeof(t*),s);for(i=0;B;i++){if(B->a<=A->b+1){A->b=B->b;if(B->a<A->a)A->a=B->a;else B->a=A->a;}}for(i=0;A;i++){if(!B)break;if(A->a!=B->a)P,A->a,A->b);}P,A->a,A->b);}

Pruébalo en línea!

Logern
fuente
Creo que confía en iel valor global de.
Jonathan Frech
Lo que @JonathanFrech significa es que while(A)i++;debe for(i=0;A;)i++;establecerse explícitamente i=0antes de usarlo en el ciclo while, en lugar de usar su 0valor predeterminado a nivel global. Ya no estoy seguro de por qué, pero se requiere de acuerdo con las meta reglas. Principalmente porque los métodos deben ser autocontenidos / reutilizables, sin tener que restablecer los valores globales entre llamadas a métodos, IIRC.
Kevin Cruijssen
Confianza fija en el ivalor global
Confianza
1
@KevinCruijssen Consulte ¿Las presentaciones de funciones tienen que ser reutilizables? .
Jonathan Frech
246 bytes
ceilingcat
1

Stax , 46 39 bytes

ÿδ7│ⁿ╚╪║»ÿ1Wç♥├óπ◙+╣╝[á╬p£ß₧ΓÑ°♥ºië«4T╗

Ejecutar y depurarlo

Este programa toma la entrada en la notación de cadena especificada originalmente.

recursivo
fuente