Vereinigung von Intervallen

15

Führen Sie die Vereinigung der Intervalle anhand einer Liste von Intervallen durch und reduzieren Sie die Überlappungen. Das heißt, überlappende Teile werden reduziert. ( [a, b] U [c, d] = [a, d]if b > c) Angenommen alle a <b in allen Intervallen [a, b]. Implementieren als Funktion einer Liste von Eingabeintervallen -> Liste von Ausgabeintervallen. Kürzester Code gewinnt. Sie können keine vorhandenen Bibliotheken verwenden.

Klarstellungen:

  • Offene und geschlossene Intervalle werden nicht unterschieden.
  • Intervalle für reelle Zahlen, keine ganzen Zahlen. ( [2, 3], [4, 5] -> [2, 3], [4, 5])
  • Ausgabeintervalle müssen nicht sortiert werden
  • Die Reihenfolge der Eingaben spielt keine Rolle
  • Illegale Eingaben sind nur [a, b]wo b >= a, es hat nichts mit der Reihenfolge der Eingabeintervalle und der Anzahl der Eingabeintervalle zu tun.
  • Bei undefiniertem Verhalten muss keine Fehlermeldung angezeigt werden

Beispiele (mit Zahlenlinien)

 [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
quelle
3
Werden die Intervalle immer so sortiert wie in Ihren Beispielen?
Peter Olson
1
Warum überlappen sich [2, 3], [4, 5] oder [2, 4], [4, 5] nicht? Beide ergeben 2345.
mellamokb
2
Sind die Intervalle nur auf der Menge der ganzen Zahlen?
Lowjacker
2
Wir brauchen eine Klarstellung: 1) Ist [4,5], [1,2] eine rechtliche Eingabe? 2) Sollte die Ausgabe von [2,3], [4,5] [2,5] oder [2,3], [4,5] sein? 3) Sollte die Ausgabe von [2,3], [3,4] [2,4] oder [2,3], [3,4] sein?
MtnViewMark
1
Danke für die Klarstellung, aber "Keine Notwendigkeit zu sortieren" bedeutet was? Dass die Ausgabe nicht sortiert werden muss? Oder dass die Eingabe schon sortiert ist?
MtnViewMark

Antworten:

2

GolfScript, 32

[{1$1$*-2%~2->{*$[(\)\;]}{}if}*]
  • Fügen Sie 2 Zeichen hinzu, wenn Sie einen Block bevorzugen, 4, wenn Sie einen benannten Block bevorzugen.
  • Eingabe und Ausgabe sind ein Array von Paaren, z [[2 4] [3 5]]
  • Nimmt an, dass die Eingabe nach dem ersten Element geordnet ist.
  • Komprimiert "benachbarte" Bereiche ([2 4] [5 6] -> [2 6])
  • Erster GolfScript-Versuch. Beratung & faules Obst geschätzt.

Vollständiges Testprogramm:

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

Beispielaufruf:

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

Haskell

Ich denke, es ist viel zu ausführlich für Haskell. Vielen Dank an Hoa Long Tam für seine Sortierfunktion.

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)?[]

In Haskell wird ein Intervall von abis bmit bezeichnet [a..b]. Meine Notation ist der mathematischen Notation sehr ähnlich. Benutze es so:

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

Ok, hier ist mein 250-Zeichen-Knaller.

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

Die Funktion nimmt ein int-Array und bearbeitet es in situ. Das Array wird mit einer 0 abgeschlossen und die Intervalle können in beliebiger Reihenfolge angegeben werden.

Beispielausgabe:

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) 

Beispielprogramm:

#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
quelle
perform the union of themsollte dazu führen (1,11) (13,18), nicht wahr?
Benutzer unbekannt
@user unbekannt: Ich hätte das gleiche gedacht, aber ich schätze, die Anweisungen sagen nur kombinieren, wenn sie sich überschneiden. (1, 4) (5, 6) werden also nicht nach der Regel kombiniert ([a, b] U [c, d] = [a, d] if b > c). Und auch (1, 5) (5, 6) würde nicht kombiniert werden.
Mellamokb
"Wenn Sie eine Liste von Intervallen haben, führen Sie die Vereinigung dieser Intervalle durch und reduzieren Sie die Überlappungen." andReduzieren Sie die Überlappungen - nicht if they overlap. OK - das Folgende that means ...zeigt wieder in die entgegengesetzte Richtung.
Benutzer unbekannt
@user unbekannt: Ich stimme zu. Deshalb habe ich zu der Frage einen Kommentar abgegeben. Hoffentlich wird das OP antworten :)
mellamokb
2

Python, 100 Zeichen

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

erzeugt

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

Übernimmt alle Endpunkte der Intervalle, entfernt alle, die sich ausschließlich innerhalb eines anderen Intervalls befinden, vereinheitlicht und sortiert sie und verbindet sie.

Keith Randall
quelle
98 Bytes
Movatica
2

Haskell, 55 Zeichen

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

Wenn die Eingabe unsortiert ist, dann 88 Zeichen:

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

Testläufe:

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

Ich gehe davon aus, dass "keine vorhandenen Bibliotheken verwenden können" das Importieren Listund Aufrufen ausschließt sort. Wenn das legal wäre, wäre die unsortierte Version nur 71 Zeichen.

MtnViewMark
quelle
ein import Listaus paket Haskell98wäre meiner meinung nach ausreichend.
FUZxxl
2

Scala, 272 Zeichen

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

Verwendung:

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

Erstellt ein Array und fügt für jeden Intervallstart eine 1 und für jedes Intervallende eine -1 ein. Führen Sie dann die Schritte durch, indem Sie die Werte zu einem Zähler hinzufügen und jedes Mal einen Start ausgeben, wenn der Zähler von 0 auf 1 wechselt, und ein Ende, wenn er von 1 auf 0 wechselt. Wahrscheinlich unnötig kompliziert.

Ausgabe:

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

Perl (146) (92) (90)

Golf bis zu 90 Zeichen, kreativ mit der Regex-Engine

sub u {map $ h [$ _] = 1, @ $ _ [0] .. @ $ _ [1] für @_; $ w. = $ _ + 0für @ h; push @ r, $ - [0 ], $ + [0] -1während $ w = ~ / 1 + / g; @r}

Anwendungsbeispiel:

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

Lassen Sie uns diesen Code ein wenig erklären.

Diese Subroutine empfängt ein Array von Arrayrefs, von denen jedes auf ein Array verweist, das zwei Elemente enthält, nämlich Anfang und Ende des Intervalls: ([2, 4], [3, 6], [8, 9])

für jedes aref generieren wir eine reihe von elementen vom ersten bis zum letzten ($_->[0] .. $_->[1]). Dann verwenden wir map, um Elemente solcher Indizes in @h auf 1 zu setzen.

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

nach diesem, @hwird entweder diejenigen enthalten (Intervalle) oder undefs, dargestellt unten als Bindestriche für Klarheit.

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

Als Nächstes erstellen wir einen String aus @h und fügen 0 hinzu, um Undefs durch etwas Nützlicheres zu ersetzen (Undef + 0 = 0).

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

$ w enthält 011111011jetzt.

Es ist Zeit, die Regex-Engine ein wenig zu missbrauchen.

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

Nach erfolgreichen Übereinstimmungen enthalten die Arrays @ - und @ + jeweils die Position von Anfang und Ende jeder Übereinstimmung. Das 0te Element wird für das gesamte Match verwendet, erstens für 1 $, zweitens für 2 $ und so weiter.

$+[0] enthält tatsächlich die Position des ersten nicht passenden Zeichens, also müssen wir eines subtrahieren.

@renthält (2, 6, 8, 9)jetzt.

@r

um das U-Boot zurückzubringen @r.

chinesischer Perl Goth
quelle
Funktioniert nicht für reelle Zahlen [2,3],[4,5]Erträge2 5
Xcali
1

Scala 305 279 Zeichen ohne Aufruf:

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

Aufruf:

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))
Benutzer unbekannt
quelle
1

Brachylog , 12 Bytes

⟦₂ᵐcod~c~⟦₂ᵐ

Probieren Sie es online!

Eine erfreulich deklarative Lösung, bei der die Eingabe als Liste von Listen über die Eingabevariable und die Ausgabe einer Liste von Listen über die Ausgabevariable erfolgt.

        ~⟦₂ᵐ    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.
Nicht verwandte Zeichenfolge
quelle
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)))

Dies verkürzt sich auf 119 Bytes, wenn die Eingabe flexibler ist, nämlich eine Liste von Intervallstartpunkten UND eine Liste von Intervallendpunkten:

#(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)))

Es muss einen besseren Weg geben.

NikoNyrh
quelle
1

Japt , 18 Bytes

Das fühlt sich viel zu lang an. E / A als sortierte, 2D-Anordnung von Intervallen.

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

Versuch es

Zottelig
quelle
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"

Probieren Sie es online!

Xcali
quelle