Encuentre la intersección de 2 conjuntos en notación de intervalo unido

10

Encuentre la intersección de 2 conjuntos en notación de intervalo unido

Dados dos conjuntos de números reales descritos como la unión de intervalos, genera una descripción de la intersección de estos dos conjuntos como una unión del mismo tipo de intervalo.

Los conjuntos de entrada siempre consistirán en uniones de intervalos de modo que cada intervalo comience y termine en un número entero diferente (es decir, ningún intervalo tiene medida cero). Sin embargo, diferentes intervalos en el mismo conjunto pueden comenzar o terminar en el mismo entero o superponerse.

El conjunto de salida también debe ser una unión de intervalos que comienzan y terminan en enteros, pero ningún intervalo en la salida puede solaparse con ningún otro, incluso en un solo entero.

La entrada puede tomar cualquier forma que sea adecuada para su idioma de elección, siempre que consista en dos listas de pares de enteros.

Por ejemplo, puede representar el conjunto ecuacióncomo:

[-10,-4]u[1,5]u[19,20]

O como:

[[-10,-4],[1,5],[19,20]]

O como:

[-10,-4;1,5;19,20]

Su representación de salida debe ser idéntica a su representación de entrada (excepto que es solo una lista de intervalos en lugar de dos).

Ejemplos / Casos de prueba:

Entrada:

[[[-90,-4],[4,90]],[[-50,50]]]

Salida:

[[-50,-4],[4,50]]

En otras palabras, estamos intersectando el conjunto que contiene todos los números reales entre -90 y -4 y todos los números reales entre 4 y 90 con el conjunto que contiene todos los números reales entre -50 y 50. La intersección es el conjunto que contiene todos números reales entre -50 y -4 y todos los números reales entre 4 y 50. Una explicación más visual:

-90~~~~~-4  4~~~~~90   intersected with
    -50~~~~~~~~50        yields:
    -50~-4  4~~50

Entrada:

"[-2,0]u[2,4]u[6,8]
[-1,1]u[3,5]u[5,9]"

Salida:

"[-1,0]u[3,4]u[6,8]"

Entrada:

[-9,-8;-8,0;-7,-6;-5,-4]
[-7,-5;-1,0;-8,-1]

Salida:

[-8,0]

Salida no válida (aunque represente el mismo conjunto):

[-8,0;-7,-5;-5,0]

Puntuación:

Este es el por lo que la fuente más corta en bytes gana, tal como se modifica potencialmente con el siguiente bono.

Prima:

-15% si también admite infinito positivo y negativo como límites de intervalos. Puede elegir qué token (s) representan estos números. (Y sí, el infinito es un número en los hiperreales; P)

quintapia
fuente
¿Podemos suponer que los diversos conjuntos unidos en cada intersección sumando están escritos en orden creciente? En otras palabras (pero a la inversa), ¿es válida la siguiente entrada? [[[4,90],[-90,-4]],[[-50,50]]]
msh210
2
@ msh210 el tercer ejemplo debería responder a esta pregunta. (No.
Ordénelos
@nimi tienes razón. arreglado
quintopia

Respuestas:

3

Mathematica, 41 bytes - 15% = 34.85

Mathematica tiene una función incorporada para la intersección de intervalos.

List@@IntervalIntersection@@Interval@@@#&

Ejemplo:

In[1]:= List@@IntervalIntersection@@Interval@@@#&[{{{-90, -4}, {4, Infinity}}, {{-50,Infinity}}}]

Out[1]= {{-50, -4}, {4, Infinity}}
alephalpha
fuente
2
Wow ... se me ocurrió exactamente la misma solución sin leer esto. +1
LegionMammal978
Tengo que amar la auto-unión de Mathematica Interval.
mbomb007
3

Haskell, 145 bytes

import Data.List
q(a,b)=[a,a+0.5..b]
p@(a,b)%(h:t)|h==b+0.5=(a,h)%t|1<2=p:(h,h)%t
p%_=[p]
a#b|h:t<-nub$sort$intersect(q=<<a)$q=<<b=(h,h)%t|1<2=[]

Ejemplo de uso: [(-2.0,0.0),(2.0,4.0),(5.0,6.0),(6.0,8.0)] # [(-1.0,1.0),(3.0,5.0),(5.0,9.0)]-> [(-1.0,0.0),(3.0,4.0),(5.0,8.0)].

Cómo funciona:

                 q=<<a            -- turn each pair in the 1st input list into
                                  -- lists with halves in between (e.g. (1,4) ->
                                  -- [1,1.5,2,2.5,3,3.5,4]) and concatenate them
                                  -- to a single list
                      q=<<b       -- same for the second input list
    nub$sort$intersect            -- sort the intersection of those lists
                                  -- and remove duplicates
h:t<-                             -- call the first element h and the rest t
                       (h,h)%t    -- start rebuilding the intervals
                          |1<2=[] -- if there's no first element h, one of the
                                  -- input lists is empty, so the output is also
                                  -- empty


p@(a,b)%(h:t)                     -- an interval p = (a,b), build from a list (h:t)
             =(a,h)%t             -- becomes (a,h)
      |h==b+1                     --   if h equals b+0.5
                    p:(h,h)%t     -- or is put in the output list, followed by
                                  --       a new interval starting with (h,h)
      |1<2                        --   otherwise
p%_=[p]                           -- base case of the interval rebuilding function 

Estoy poniendo los-valores "medio" x.5en la lista, porque necesito distinguir (1,2),(3,4)entre (1,4). Sin x.5, ambos se convertirían [1,2,3,4], pero con x.5el primero se convierte [1,1.5,2,3,3.5,4](que falta 2.5) y el segundo [1,1.5,2,2.5,3,3.5,4].

nimi
fuente
La salida debe ser idéntica a la entrada. ... así que solo di que tu entrada necesita .0 después de cada número entero también;)
quintopia
@quintopia: sí, gracias.
nimi
2

Rubí, 90 bytes.

Asigna cada uno de los dos conjuntos a una matriz plana, obtiene la intersección establecida de esas matrices, luego divide el resultado en fragmentos continuos y asigna cada fragmento al primer y último elemento. Pan comido.

->s{a,b=s.map{|y|y.flat_map{|f,l|[*f..l]}.sort}
(a&b).slice_when{|a,b|b-a>1}.map &:minmax}

Uso:

f=->s{a,b=s.map{|y|y.flat_map{|f,l|[*f..l]}.sort}
(a&b).slice_when{|a,b|b-a>1}.map &:minmax}

s = [[[-90,-4],[4,90]], [[-50,50]]]
p f[s] # => [[-50, -4], [4, 50]]

s = [[[-2,0],[2,4],[6,8]], [[-1,1],[3,5],[5,9]]]
p f[s] # => [[-1, 0], [3, 4], [6, 8]]

s = [[[-9,-8],[-8,0],[-7,-6],[-5,-4]],[[-7,-5],[-1,0],[-8,-1]]]
p f[s] # => [[-8, 0]]
daniero
fuente
¿Para qué sale el programa s = [[[1,2],[3,4]], [[1,2],[3,4]]]? (Mi versión ruby ​​no tiene slice_when, así que no puedo
probarme
@mimi da [[1, 4]]. El slice_whenmétodo fue agregado en algún lugar alrededor de Ruby 2.2, creo.
daniero
... pero debería ser [[1,2], [3,4]]
nimi
Los conjuntos están sobre números reales, solo los límites de intervalo son enteros, por 2.2lo que no está en la entrada s = [[[1,2],[3,4]], [[1,2],[3,4]]], sino en su salida [[1, 4]].
nimi
Hmm, tienes razón. Eso podría haber sido aclarado / enfatizado un poco para los matemáticamente desafiados como yo ..
daniero