値のリストから範囲を決定する


18

一意の正の整数のソートされていないリストが与えられた場合、連続する整数の可能な限り長い範囲の最短リストを出力します。

入力

  • 一意の正の整数のソートされていないリスト
    • 例えば 9 13 3 11 8 4 10 15
  • 入力は、次のいずれかから取得できます。
    • stdin
    • コマンドライン引数
    • 関数の引数

出力

  • 範囲の順序付きリストまたは個々の値が1行でstdoutまたは使用言語の最も類似した出力に出力されます。
    • 2つ以上の連続した整数(リスト内の位置ではなく、値で連続)が存在する場合、それらは-を使用して包括的範囲として示されます。 8-11
    • 他のすべての整数は、他の表記法なしで単に印刷されます
    • 単一のスペースで出力を区切ります
  • 入力に存在しない数値は出力に含ま3 5 6れてはなりません。たとえば、存在しない3-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-9そして10-11あるべき8-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私は何ヶ月もサイトに目を光らせていました。私が使用している言語はどれも通常、回答の良い候補ではなく、今日まで投稿する質問はありませんでした。
コーリーオグバーン

1
@xnor:Maltysenの宿題リストに似ていますが、同一ではありません。
アレックスA.

回答:


9

Python 2、123 120バイト

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


Python 2に切り替えると、数バイトを保存するstr(n)よう`n`に変更できます。
mbomb00715年

また、代わりに使用しての入力としてリストを取る関数を作成することができraw_input()、あなたが変更することができます'-'+`n``-n`。また、現在Python 2を使用しているため、の後の括弧を削除できますprint
mbomb007

文字列を1つずつ生成するのは賢い方法です。バイトを節約するために、一般的にリスト選択または算術による条件付けを行う方が短くなります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

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.6


...しかし...それはどの例でも動作しますか?複数桁の数字があるため、 ""(空の文字列)ではなく ""(空白)で分割する必要があります。私はおそらくあなたに間違ったヒントを与えた
-edc65

@ edc65何かが違って見えると思い、テストケースが失敗したことに気づきました。まだ新しいことを学ぶのにまだ良い
-rink.attendant.6

4

ルビー、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

ルビー、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]).

かなり悪いが、プロローグはひどいゴルフ言語です

例: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演算子を適用すると、間隔が直接列挙されます。

減算されたシーケンシャル値は、出力中に再度加算する必要があります。私のコードでそれがどのように行われるかについて、私は完全に満足していません。私はそれをよりエレガントな方法で数バイト節約できると思います。

間隔の出力を生成するために、これは終了値に負の数を生成するデニスのアイデアを使用します。 -します。 。

説明:

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}/
デニス

私が最初にあなたのソリューションを見たとき、私はあなたが-コードに現れず、条件なしでどのように出力になったのか不思議に思っていました。今、私はそれを得る:それは、終了値を負の数に変えることから来る!私はこれを思い付かなかったので、それをコピーするのは気分が悪いでしょう。次回からそれを学ぼうと思います!:)
レトコラディ

けっこうだ。どの程度l~$_,,.-e{〜T + _T +?:T;(_ 2 $ + W * Q S}?。/ `しかし、独自のコードに多くの類似のだとわずか33バイトの重さ
デニス・

@Dennis OK、あなたが主張するなら。:)実際には、間隔の終わりに負の値を生成するという重要な考えを取り入れると、これは合理的に簡単に実装する方法のように見えます。ありがとう。
レトコラディ

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バイト

私はこれが短くなる可能性があることを知っていますが、どこにあるのか分からないだけです。formの入力が必要です[#, #, #, #, ..., #]

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

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、171 162バイト

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配列として受け取り、出力をスペースで区切られた文字列リストとして返します

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