間隔の連合


15

間隔のリストを指定して、それらの和集合を実行し、重複を減らします。つまり、重なり合う部分が減ります。([a, b] U [c, d] = [a, d]if b > c)すべての間隔ですべてのa <bと仮定します[a, b]。入力間隔のリストの機能として実装->出力間隔のリスト。最短のコードが優先されます。既存のライブラリを使用することはできません。

明確化:

  • 開いている間隔と閉じている間隔は区別されません。
  • 整数ではなく実数の間隔。([2, 3], [4, 5] -> [2, 3], [4, 5]
  • 出力間隔をソートする必要はありません
  • 入力が重要でない場合の順序
  • 不正な入力があるだけで[a, b]どこb >= aそれは、入力間隔の順と入力間隔の数とは関係ありません、。
  • 未定義の動作に関するエラーメッセージを表示する必要はありません。

例(行数あり)

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

3
例にあるように、間隔は常にソートされますか?
ピーターオルソン

1
[2、3]、[4、5]が重ならない、または[2、4]、[4、5]も重ならないのはなぜですか?彼らは両方の歩留まり2345
mellamokb

2
間隔は整数のセットのみですか?
ロージャッカー

2
いくつかの明確化が必要です。1)[4,5]、[1,2]は合法な入力ですか?2)[2,3]、[4,5]の出力は[2,5]または[2,3]、[4,5]ですか?3)[2,3]、[3,4]の出力は[2,4]または[2,3]、[3,4]ですか?
MtnViewMark

1
説明をありがとうございますが、「ソートする必要はありません」とはどういう意味ですか?出力を並べ替える必要はありませんか?または、入力がすでにソートされていることは?
MtnViewMark

回答:


2

GolfScript、32

[{1$1$*-2%~2->{*$[(\)\;]}{}if}*]
  • ブロックを好む場合は2文字、名前付きブロックを好む場合は4文字を追加します。
  • 入力と出力はペアの配列です。例えば [[2 4] [3 5]]
  • 入力が最初の要素によって順序付けられていると仮定します。
  • コンパクトな「隣接」範囲([2 4] [5 6]-> [2 6])
  • GolfScriptの最初の取り組み。アドバイスと腐った果物に感謝します。

完全なテストプログラム:

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

呼び出しの例:

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

4

ハスケル(103)

Haskellにとっては冗長すぎると思います。ソート機能を提供してくれたHoa Long Tamに感謝します。

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

Haskellでは、からaまでの区間bはで示され[a..b]ます。私の表記法は数学的表記法に非常に似ています。次のように使用します。

[a..b] ∪ [c..d] ∪ ... ∪ [y..z]

3

OK、これが私の250文字のクラックです。

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

この関数はint配列を取り、その場で操作します。配列は0で終了し、間隔は任意の順序で指定できます。

サンプル出力:

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) 

サンプルプログラム:

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

perform the union of themにつながる(1,11) (13,18)はずですよね?
ユーザー不明

@ユーザー不明:私は同じことを考えていたでしょうが、命令はそれらが重なる場合にのみ結合すると言うと思います。したがって、(1、4)(5、6)はルールに従って結合されません([a, b] U [c, d] = [a, d] if b > c)。さらに、(1、5)(5、6)でも結合されません。
mellamokb

「間隔のリストを指定し、それらの和集合を実行し、オーバーラップを減らします」andオーバーラップを減らします-ではありませんif they overlap。OK- that means ...反対方向に再び次のポイント。
ユーザー不明

@user unknown:同意します。それが私が質問でそれについてコメントした理由です。OPが応答することを願っています:)
mellamokb

2

Python、100文字

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

生成する

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

間隔のすべてのエンドポイントを取得し、厳密に別の間隔の内側にあるものをすべて削除し、それらを一意化およびソートして、ペアにします。



2

Haskell、55文字

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

入力がソートされていない場合、88文字:

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

テスト実行:

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

「既存のライブラリを使用できない」ためList、インポートと呼び出しができないと想定していますsort。それが合法であれば、ソートされていないバージョンは71文字のみです。


ListパッケージからインポートHaskell98するだけで十分です。
FUZxxl

2

Scala、272文字

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

使用法:

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

配列を作成し、間隔の開始ごとに1を挿入し、間隔の終了ごとに-1を挿入します。次に、配列をステップ実行して、値をカウンターに追加し、カウンターが0から1にステップするたびに開始を出力し、1から0にステップするときに終了を出力します。おそらく不必要に複雑です。

出力:

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

1

Perl (146) (92)(90)

正規表現エンジンを使用して創造的に90文字までゴルフ

sub u {map $ h [$ _] = 1、@ $ _ [0] .. @ $ _ [1] for @_; $ w。= $ _ + 0for @ h; push @ r、$-[0 ]、$ + [0] -1while $ w =〜/ 1 + / g; @r}

使用例:

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

このコードについて少し説明しましょう。

このサブルーチンはarrayrefの配列を受け取ります。各arefは、間隔の開始と終了の2つの要素を含む配列を指します。 ([2, 4], [3, 6], [8, 9])

すべてのarefについて、firstからlastまでの要素の配列を生成し($_->[0] .. $_->[1])ます。次に、mapを使用して、@ hのそのようなインデックスの要素を1に設定します。

にとって (@_) {
    map {$ h [$ _] = 1}($ _-> [0] .. $ _-> [1]);
}

この後、@h1つ(間隔用)またはundefが含まれます。明確にするために、以下にハイフンとして示します。

インデックス:0 1 2 3 4 5 6 7 8 9
@h:--1 1 1 1 1-1 1

次に、@ hから文字列を作成し、0を追加してundefをより有用なもの(undef + 0 = 0)に置き換えます。

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

$ wには011111011現在含まれています。

正規表現エンジンを少し悪用する時が来ました。

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

一致が成功した後、@-および@ +配列には、各一致の開始位置と終了位置がそれぞれ含まれます。0番目の要素は一致全体に使用され、最初は$ 1、2番目は$ 2などになります。

$+[0] 実際には最初に一致しないcharの位置が含まれるため、1を減算する必要があります。

@r(2, 6, 8, 9)今含まれています。

@r

サブリターンをする@r


実数の[2,3],[4,5]利回りでは機能しません2 5
-Xcali

1

呼び出しなしのScala 305 279文字:

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

呼び出し:

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

1

Brachylog、12バイト

⟦₂ᵐcod~c~⟦₂ᵐ

オンラインでお試しください!

入力変数を介してリストのリストとして入力を取得し、出力変数を介してリストのリストを出力する、宣言型ソリューション。

        ~⟦₂ᵐ    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.

1

Clojure、138バイト

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

入力がより柔軟な場合、つまり間隔の開始点のリストと間隔の終了点のリストの場合、これは119バイトに短縮されます

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

より良い方法が必要です。



弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.