从值列表确定范围


18

给定一个未排序的唯一正整数列表,请输出序列整数的最长可能范围中的最短列表。

输入

  • 未排序的唯一正整数列表
    • 例如 9 13 3 11 8 4 10 15
  • 输入可以来自以下任意一项:
    • stdin
    • 命令行参数
    • 函数参数

输出值

  • 在标准输出或您的语言最接近的相似输出的一行上打印的范围或单个值的有序列表。
    • 如果存在两个或多个顺序整数(按值顺序,而不是列表中的位置),则将使用-将它们表示为包含范围。例如 8-11
    • 所有其他整数仅打印而没有其他符号
    • 单个空格将分隔输出
  • 输入中不存在的数字不应出现在输出中,例如3 5 63-6由于4不存在而不能缩短为

例子

成功:

 IN> 9 13 3 11 8 4 10 15 6
OUT> 3-4 6 8-11 13 15

 IN> 11 10 6 9 13 8 3 4 15
OUT> 3-4 6 8-11 13 15

 IN> 5 8 3 2 6 4 7 1
OUT> 1-8

 IN> 5 3 7 1 9
OUT> 1 3 5 7 9

错误:

 IN> 9 13 3 11 8 4 10 15
OUT> 3-15

范围包含不在输入中的值

 IN> 9 13 3 11 8 4 10 15
OUT> 3 4 8 9 10 11 13 15

所有顺序值都应表示为范围

 IN> 9 13 3 11 8 4 10 15
OUT> 3-4 8-9 10-11 13 15

划分范围,8-910-118-11

 IN> 9 13 3 11 8 4 10 15
OUT> 8-9 13 10-11 3-4 15

输出顺序不正确

规则

  • 不允许出现标准漏洞
  • 如果您的语言具有执行此功能的功能,则不允许
  • 您可以编写完整的程序或函数
  • 尾随空格并不重要

计分

  • 最少字节获胜

1
第一句话确实令人困惑。我建议您说“输出连续整数可能的最长范围的最短列表”。否则,很好的挑战!
弥敦道·美林

2
我很确定我们之前曾经遇到过这个挑战,但是我没有提出正确的搜索字词。有人记得吗?
xnor

4
@CoreyOgburn顺便说一句,是什么促使您在PPCG上发帖?我们试图弄清楚为什么我们有一大堆的新用户进来。
同或

2
@xnor我几个月来一直在关注该站点。我使用的任何一种语言通常都不是答案的最佳候选者,直到今天我再也没有发布过任何问题。
Corey Ogburn 2015年

1
@xnor:它与Maltysen的作业清单类似,但不完全相同。
Alex A.

Answers:


9

Python 2,123120字节

N=sorted(map(int,raw_input().split(' ')));print(''.join((''if n+1in N else'-'+`n`)if n-1in N else' '+`n`for n in N)[1:])

如果输入可以作为函数参数列表,则(感谢mbomb007和xnor作为条件变量)

93 90 81字节

def f(N):print''.join((' '+`n`,`-n`*-~-(n+1in N))[n-1in N]for n in sorted(N))[1:]

(如果可以接受前导空白,则为77个字节-删除最后一个[1:]


你可以改变str(n),以`n`节省几个字节,如果切换到Python的2
mbomb007

您还可以创建一个将列表作为输入而不是使用的函数raw_input(),并且可以更改'-'+`n``-n`。并且由于您现在使用的是Python 2,因此可以在后面删除括号print
mbomb007

逐段生成字符串很聪明。对于字节保存,通常通过列表选择或算术(例如def f(N):print''.join([' '+`n`,`-n`*(n+1 not in N)][n-1 in N]for n in sorted(N))[1:],可以进行进一步的查找)进行条件运算的时间较短。
xnor

您也许可以使用set(N)代替sorted(N); 使用cPython时,这将正确地从最小迭代到最低,但是不能保证在所有实现中都有效,因此存在一些关于是否有效的问题。
KSab 2015年

6

的JavaScript(ES6):171个 154 140 137 字节

感谢edc65和vihan1086的提示![...n]非常好,但是由于多位数,在这种情况下不起作用。

f=n=>{s=e=o='';n.split` `.map(Number).sort((a,b)=>a-b).map(v=>{s=s||v;if(e&&v>e+1){o+=`${s<e?s+'-'+e:s} `;s=v}e=v});return o+(s<e?s+'-'+e:e)}

ES5变型中,198个 184 183 174字节

f=function(n){s=e=o='';n.split(' ').map(Number).sort(function(a,b){return a-b}).map(function(v){s=s||v;if(e&&v>e+1){o+=(s<e?s+'-'+e:s)+' ';s=v}e=v});return o+(s<e?s+'-'+e:e)}


n。没有括号的分割对我来说是全新的!但是[...n]更好
edc65

@ edc65谢谢,从未想过要像这样解包字符串。
rink.attendant.15年


...但是...可以用于任何示例吗?有多位数字,因此您需要在“”(空白)而不是“”(空字符串)上进行分割。我可能给了您错误的提示
edc65

@ edc65我以为看起来有些不同,然后我意识到测试用例失败了。不过,还是很高兴学到新的东西
rink.attendant.15年

4

Ruby,86 84字节

s=->*a{puts a.sort.slice_when{|i,j|i+1!=j}.map{|e|e.size<2?e:[e[0],e[-1]]*"-"}*" "}

# demo
s[9, 13, 3, 11, 8, 4, 10, 15, 6]
# => 3-4 6 8-11 13 15

这是来自slice_when文档中一个示例的略微修改版本。


4

CJam,35个字节

l~${__0=f-ee::=0+0#/((oW>Wf*S+oe_}h

CJam解释器中在线尝试。

怎么运行的

l~$     e# Read a line from STDIN, evaluate it and sort the result.
{       e# Do:
  _     e#   Push a copy of the array.
  _0=f- e#   Subtract the first element from all array elements.
  ee    e#   Enumerate the differences: [0 1 4] -> [[0 0] [1 1] [2 4]]
  ::=   e#   Vectorized quality: [i j] -> (i == j)
  0+    e#   Append a zero.
  0#    e#   Push the first index of 0.
  /     e#   Split the array into chunks of that size.
  (     e#   Shift out the first chunk.
  (o    e#   Print its first element.
  W>    e#   Discard all remaining elements (if any) except the last.
  Wf*   e#   Multiply all elements of the remainder by -1.
  S+o   e#   Append a space and print.
  e_    e#   Flatten the rest of the array.
}h      e# Repeat while the array is non-empty.

4

Ruby,70个字节

诸如此类的问题使我不得不检查Ruby API的合适方法,今天我发现了一个新的:Array#slice_when,它是Ruby v2.2中新引入的,似乎是针对这种情况的:)

f=->a{puts a.sort.slice_when{|i,j|j-i>1}.map{|x|x.minmax.uniq*?-}*' '}

在对数组进行排序和适当切片之后,它将获取每个子数组并从最高和最低元素中创建一个字符串,然后将整个数组连接成一个字符串。

例:

f.call [9,13,3,11,8,4,10,15,6] 版画 3-4 6 8-11 13 15


4

SWI-Prolog的,165个 162 159字节

b(Z,C,[D|E]):-Z=[A|B],(A=:=D+1,(B=[],put(45),print(A);b(B,C,[A,D|E]));(E=[],tab(1),print(A);writef('-%t %t',[D,A])),b(B,A,[A]));!.
a(A):-sort(A,B),b(B,_,[-1]).

相当糟糕,但是Prolog又是一种糟糕的高尔夫语言

示例:a([9,13,3,11,8,4,10,15,6]).输出3-4 6 8-11 13 15


3

CJam,38 33字节

新版本,使用@Dennis建议的想法和代码片段:

l~$_,,.-e`{~T+\_T+:T;(_2$+W*Q?S}/

在线尝试

输入格式是方括号内的CJam数组。

这里的基本思想是,我首先从排序后的输入序列中减去一个单调序列:

3  4  8  9 10 11 13 15
0  1  2  3  4  5  6  7  (-)
----------------------
3  3  6  6  6  6  7  8

在这种差异中,属于相同间隔的值具有相同的值。将CJam RLE运算符应用于此差异将直接枚举间隔。

减去的顺序值需要在输出期间加回去。我对自己的代码完成方式并不完全满意。我怀疑我可以用更优雅的方式节省一些字节。

为了生成间隔的输出,这使用了Dennis为最终值生成一个负数的想法,该想法要产生一个-,并且还简化了逻辑,因为仅需要根据间隔大小添加/省略一个值。 。

说明:

l~    Get input.
$     Sort it.
_,,   Create monotonic sequence of same length.
.-    Calculate vector difference between the two.
e`    Calculate RLE of difference vector.
{     Loop over entries in RLE.
  ~     Unpack the RLE entry, now have length/value on stack.
  T+    Add position to get original value for start of interval.
  \     Bring length of interval to top of stack.
  _T+:T;  Add length of interval to variable T, which tracks position.
  (     Decrement interval length.
  _     Copy it, we need it once for calculating end value, once for ternary if condition.
  2$    Copy interval start value to top...
  +     ... and add interval length - 1 to get end value.
  W*    Negate end value.
  Q?    Output end value if interval length was > 1, empty string otherwise.
  S     Add a space.
}%    End loop.

这是RLE的巧妙用法!通过从我的答案中借用范围处理和输入格式,您可以减少到34个字节:l~$_,,.-e`{~T+\_T+:T;,f+(\W>Wf*S}/
Dennis

当我最初查看您的解决方案时,我有点迷惑,您是如何-进入输出的,而没有在代码中显示它,并且没有条件。现在我明白了:这是将最终值变成负数!我永远不会想出这个,所以我对复制它感到很难过。我将在下一次尝试中学习!:)
Reto Koradi

很公平。如何l~$_,,.-e{〜T + _T +:T;(2 _ $ + W * Q S'} /`虽然这是一个很多自己的代码更相似,重量只有33字节?
丹尼斯

@丹尼斯好吧,如果您坚持的话。:)实际上,采用为时间间隔结束生成负值的关键思想,这似乎是实现它的一种相当简单的方法。谢谢。
Reto Koradi

2

CoffeeScript,178 161字节

就像我的JavaScript答案一样。我需要弄清楚使用理解是否会缩短代码。

f=(n)->s=e=o='';n.split(' ').map(Number).sort((a,b)->a-b).map((v)->s=s||v;(o+=s+(if s<e then'-'+e else'')+' ';s=v)if(e&&v>e+1);e=v);o+(if s<e then s+'-'else'')+e

原版的:

f=(n)->o='';s=e=0;n.split(' ').map(Number).sort((a,b)->a-b).forEach((v,i)->if!i then s=v else(o+=s+(if s<e then'-'+e else'')+' ';s=v)if(v!=e+1);e=v);o+(if s<e then s+'-'else'')+e

1

Python 2中,126 122个 121字节

我知道这会变得更短,只是不知道在哪里。需要以表格形式输入[#, #, #, #, ..., #]

l=sorted(input());s=`l[0]`;c=0;x=1
while x<len(l):y,z=l[x],l[x-1];s+=(('-'+`z`)*c+' '+`y`)*(y-z>1);c=(y-z<2);x+=1
print s

您似乎exec经常会找到解决方案。
mbomb007

@ mbomb007您可能正在考虑xnor :)而且我认为在这种情况下,循环的长度可能相同,甚至更短(还没有玩完)。
卡德

1
您应该可以替换while x<len(l)while l[x:]以节省一些字节。
mathmandan 2015年

1

Java,191个字节

void f(int[]a){java.util.Arrays.sort(a);for(int b=a.length,c=b-1,i=0,j=a[0],l=j;++i<b;){if(a[i]!=++j||i==c){System.out.print((l+1==j?l+(i==c?" "+a[c]:""):l+"-"+(i==c?j:j-1))+" ");l=j=a[i];}}}

检查范围并相应地打印它们。不幸的是,我不得不对数组中的最后一个元素进行特殊处理,因为程序将在不打印最后一个数字或范围的情况下终止。


1

Java,171162字节

String s(int[] n){Arrays.sort(n);int p=0,b=0;String r="",d="";for(int c:n){if(c==++p)b=1;else{if(b==1){r+="-"+--p+d+c;p=c;b=0;}else{r+=d+c;p=c;}d=" ";}}return r;}

将输入作为一个int数组,将输出作为一个以空格分隔的String列表返回

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.