Trouver l'intersection de 2 ensembles dans la notation d'intervalle unifié

10

Trouver l'intersection de 2 ensembles dans la notation d'intervalle unifié

Étant donné deux ensembles de nombres réels décrits comme l'union d'intervalles, affichez une description de l'intersection de ces deux ensembles comme une union du même type d'intervalle.

Les ensembles d'entrée seront toujours constitués d'unions d'intervalles de sorte que chaque intervalle commence et se termine à un entier différent (c'est-à-dire qu'aucun intervalle n'a la mesure zéro). Cependant, différents intervalles dans le même ensemble peuvent commencer ou se terminer au même entier ou se chevaucher.

L'ensemble de sortie doit également être une union d'intervalles qui commencent et se terminent à des entiers, mais aucun intervalle dans la sortie ne peut se chevaucher, même à un seul entier.

L'entrée peut prendre n'importe quelle forme adaptée à la langue de votre choix, à condition qu'elle se compose de deux listes de paires d'entiers.

Par exemple, vous pouvez représenter l'ensemble équationcomme:

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

Ou comme:

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

Ou comme:

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

Votre représentation de sortie doit être identique à votre représentation d'entrée (sauf qu'il ne s'agit que d'une liste d'intervalles au lieu de deux).

Exemples / cas de test:

Contribution:

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

Production:

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

En d'autres termes, nous croisons l'ensemble qui contient tous les nombres réels entre -90 et -4 et tous les nombres réels entre 4 et 90 avec l'ensemble qui contient tous les nombres réels entre -50 et 50. L'intersection est l'ensemble contenant tous les nombres réels entre -50 et -4 et tous les nombres réels entre 4 et 50. Une explication plus visuelle:

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

Contribution:

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

Production:

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

Contribution:

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

Production:

[-8,0]

Sortie non valide (même si elle représente le même ensemble):

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

Notation:

C'est le donc la source la plus courte en octets gagne, comme potentiellement modifiée par le bonus suivant.

Prime:

-15% si vous supportez également l'infini positif et négatif comme bornes d'intervalles. Vous pouvez choisir quel (s) jeton (s) représentent ces numéros. (Et oui, l'infini est un nombre dans les hyperréalités; P)

quintopie
la source
Pouvons-nous supposer que les différents ensembles unis dans chaque sommation d'intersection sont écrits dans un ordre croissant? En d'autres termes (mais inversement), l'entrée suivante est-elle valide? [[[4,90],[-90,-4]],[[-50,50]]]
msh210
2
@ msh210 le troisième exemple devrait répondre à cette question. (Non. Triez-les vous-même.)
quintopie
@nimi tu as raison. corrigé
quintopie

Réponses:

3

Mathematica, 41 octets - 15% = 34,85

Mathematica a une fonction intégrée pour l'intersection d'intervalles.

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

Exemple:

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

Out[1]= {{-50, -4}, {4, Infinity}}
alephalpha
la source
2
Wow ... Je viens juste de trouver la même solution sans lire ceci. +1
LegionMammal978
Je dois aimer l'auto-union de Mathematica Interval.
mbomb007
3

Haskell, 145 octets

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

Exemple d'utilisation: [(-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)].

Comment ça fonctionne:

                 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 

Je mets les -values « demi » x.5dans la liste, parce que je dois distinguer (1,2),(3,4)de (1,4). Sans x.5, les deux deviendraient [1,2,3,4], mais avec x.5le 1er devient [1,1.5,2,3,3.5,4](qui manque 2.5) et le second [1,1.5,2,2.5,3,3.5,4].

nimi
la source
La sortie doit être identique à l'entrée. ... alors dites simplement que votre entrée a besoin de .0 après chaque entier également;)
quintopie
@quintopia: oui, merci.
nimi
2

Rubis, 90 octets

Mappe chacun des deux ensembles à un tableau plat, obtient l'intersection de l'ensemble de ces tableaux, puis découpe le résultat en morceaux continus et mappe chaque morceau dans le premier et le dernier élément. Peasy facile.

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

Usage:

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
la source
À quoi sert votre programme s = [[[1,2],[3,4]], [[1,2],[3,4]]]? (Ma version rubis n'a pas slice_when, donc je ne peux pas me tester)
nimi
@mimi ça donne [[1, 4]]. La slice_whenméthode a été ajoutée quelque part autour de Ruby 2.2 je pense.
daniero
... mais ça devrait être [[1,2], [3,4]]
nimi
Les ensembles sont sur des nombres réels, seules les limites d'intervalle sont des entiers, ce 2.2n'est donc pas dans l'entrée s = [[[1,2],[3,4]], [[1,2],[3,4]]], mais dans votre sortie [[1, 4]].
nimi
Hmm, tu as raison. Cela aurait pu être un peu clarifié / empathisé pour les mathématiciens comme moi ..
daniero