Trova l'intersezione di 2 set in Notazione intervallo Unioned


10

Trova l'intersezione di 2 set in Notazione intervallo Unioned

Dati due insiemi di numeri reali descritti come l'unione di intervalli, emette una descrizione dell'intersezione di questi due insiemi come unione dello stesso tipo di intervallo.

I set di input saranno sempre costituiti da unioni di intervalli in modo tale che ciascun intervallo inizi e termini con un intero diverso (ovvero nessun intervallo ha misura zero). Tuttavia, intervalli diversi nello stesso set possono iniziare o terminare con lo stesso numero intero o sovrapporsi.

L'insieme di output deve anche essere un unione di intervalli che iniziano e finiscono con numeri interi, ma nessun intervallo nell'output può sovrapporsi a qualsiasi altro anche a un singolo numero intero.

L'input può assumere qualsiasi forma adatta alla tua lingua preferita, purché sia ​​composta da due elenchi di coppie di numeri interi.

Ad esempio, è possibile rappresentare il set equazionecome:

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

O come:

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

O come:

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

La rappresentazione di output deve essere identica alla rappresentazione di input (tranne per il fatto che è solo un elenco di intervalli anziché due).

Esempi / casi di test:

Ingresso:

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

Produzione:

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

In altre parole, stiamo intersecando l'insieme che contiene tutti i numeri reali tra -90 e -4 e tutti i numeri reali tra 4 e 90 con l'insieme che contiene tutti i numeri reali tra -50 e 50. L'intersezione è l'insieme che contiene tutti numeri reali compresi tra -50 e -4 e tutti i numeri reali compresi tra 4 e 50. Una spiegazione più visiva:

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

Ingresso:

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

Produzione:

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

Ingresso:

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

Produzione:

[-8,0]

Output non valido (anche se rappresenta lo stesso set):

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

punteggio:

Questo è il quindi la fonte più corta in byte vince, potenzialmente modificata dal seguente bonus.

Bonus:

-15% se si supporta anche l'infinito positivo e negativo come limiti di intervalli. Puoi scegliere quali token rappresentano questi numeri. (E sì, l'infinito è un numero negli hyperreals; P)


Possiamo supporre che i vari insiemi uniti in ciascun summand di intersezione siano scritti in ordine crescente? In altre parole (ma viceversa), è valido il seguente input? [[[4,90],[-90,-4]],[[-50,50]]]
msh210,

2
@ msh210 il terzo esempio dovrebbe rispondere a questa domanda. (No. Ordinali da soli.)
Quintopia,

@nimi hai ragione. fisso
quintopia

Risposte:


3

Mathematica, 41 byte - 15% = 34,85

Mathematica ha una funzione integrata per l'intersezione degli intervalli.

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

Esempio:

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

Out[1]= {{-50, -4}, {4, Infinity}}

2
Wow ... Ho appena trovato la stessa identica soluzione senza leggere questo. +1
LegionMammal978,

Devo amare l'auto-unione di Mathematica Interval.
mbomb007,

3

Haskell, 145 byte

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=[]

Esempio di utilizzo: [(-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)].

Come funziona:

                 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 

Sto inserendo i "metà" valori x.5nell'elenco, perché devo distinguere (1,2),(3,4)da (1,4). Senza x.5, entrambi diventerebbero [1,2,3,4], ma con x.5il primo diventa [1,1.5,2,3,3.5,4](che manca 2.5) e il secondo [1,1.5,2,2.5,3,3.5,4].


L'output dovrebbe essere identico all'input. ... quindi dì solo che il tuo input ha bisogno di 0 anche dopo ogni numero intero;)
quintopia

@quintopia: si grazie.
nimi,

2

Rubino, 90 byte

Mappa ciascuno dei due set su un array piatto, ottiene l'intersezione di set di tali array, quindi suddivide il risultato in blocchi continui e mappa ogni blocco nel primo e nell'ultimo elemento. Vai tranquillo.

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

A cosa serve il tuo programma s = [[[1,2],[3,4]], [[1,2],[3,4]]]? (La mia versione ruby ​​non ha slice_when, quindi non posso mettermi alla prova)
nimi

@mimi dà [[1, 4]]. Ilslice_when metodo è stato aggiunto da qualche parte intorno Rubino 2.2 credo.
daniero,

... ma dovrebbe essere [[1,2], [3,4]]
nimi

Gli insiemi sono su numeri reali, solo i limiti dell'intervallo sono numeri interi, quindi 2.2non è nell'input s = [[[1,2],[3,4]], [[1,2],[3,4]]], ma nell'output [[1, 4]].
nimi,

Hmm, hai ragione. Ciò avrebbe potuto essere chiarito / enfatizzato un po 'per le persone matematicamente sfidate come me ..
daniero,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.