间隔联盟


15

给定间隔列表,对其进行合并,并减少重叠。这意味着减少了重叠部分。([a, b] U [c, d] = [a, d]如果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
间隔仅在整数集上吗?
Lowjacker 2011年

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

Answers:


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

好的,这是我的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),不是吗?
用户未知,

@user未知:我本来会想同样的事情,但是我猜想说的是指令只有在重叠时才会结合在一起。因此(1,4)(5,6)不按照规则进行组合([a, b] U [c, d] = [a, d] if b > c)。因此,即使(1,5)(5,6)也不会合并。
mellamokb 2011年

“给出间隔列表,执行间隔的并集,并减少重叠” and减少重叠-而不是if they overlap。OK-以下that means ...内容再次指向相反的方向。
用户未知,

@user未知:我同意。这就是为什么我对此问题发表评论的原因。希望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 2011年

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}

用法示例:

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

让我们来解释一下这段代码。

该子例程接收一个arrayref数组,每个aref指向一个包含两个元素的数组,该两个元素分别是时间间隔的开始和结束: ([2, 4], [3, 6], [8, 9])

对于每个aref,我们从first到last生成一个元素数组($_->[0] .. $_->[1])。然后我们使用map将@h中此类索引的元素设置为1。

为(@_){
    映射{$ h [$ _] = 1}($ _-> [0] .. $ _-> [1]);
}

之后,@h将包含一个(用于间隔)或undef,为清楚起见,在下面以连字符表示。

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

接下来,我们从@h构建一个字符串,并添加0来用更有用的东西(undef + 0 = 0)替换undefs。

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

$ w 011111011现在包含。

现在该稍微滥用正则表达式引擎了。

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

匹配成功后,@-和@ +数组分别包含每个匹配的开始和结束位置;第0个元素用于整个匹配,第一个元素用于$ 1,第二个元素用于$ 2,依此类推。

$+[0] 实际上包含第一个不匹配字符的位置,因此我们必须减去一个。

@r(2, 6, 8, 9)现在包含。

@r

使子返回@r


不适用于实数[2,3],[4,5]收益率2 5
Xcali '19

1

没有调用的Scala 305279个字符:

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

一定有更好的方法。



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.