Tentukan rentang dari daftar nilai

18

Diberikan daftar bilangan bulat unik dan positif yang tidak disortir, mengeluarkan daftar terpendek dari kisaran terpanjang yang mungkin dari bilangan bulat berurutan.

MEMASUKKAN

  • Daftar bilangan bulat unik dan positif yang tidak disortir
    • misalnya 9 13 3 11 8 4 10 15
  • Masukan dapat diambil dari salah satu dari berikut ini:
    • stdin
    • argumen baris perintah
    • argumen fungsi

KELUARAN

  • Daftar rentang atau nilai individual yang dicetak pada satu baris untuk stdout atau keluaran serupa bahasa Anda yang terdekat.
    • Jika dua atau lebih bilangan bulat berurutan (berurutan menurut nilai, bukan berdasarkan lokasi dalam daftar) hadir, mereka akan dilambangkan sebagai rentang inklusif menggunakan -, misalnya 8-11
    • Semua bilangan bulat lainnya hanya dicetak tanpa notasi lain
    • Satu ruang akan membatasi output
  • Angka yang tidak ada dalam input tidak boleh dalam output, mis. 3 5 6Tidak dapat disingkat menjadi 3-6karena 4tidak ada

CONTOH

Berhasil:

 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

Salah:

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

Rentang berisi nilai yang tidak ada dalam input

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

Semua nilai sekuensial harus direpresentasikan sebagai rentang

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

Rentang yang dibagi , 8-9dan 10-11harus8-11

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

Output tidak dipesan dengan benar

ATURAN

  • Celah standar tidak diijinkan
  • Jika bahasa Anda memiliki fungsi untuk melakukan ini, itu tidak diperbolehkan
  • Anda dapat menulis program lengkap, atau suatu fungsi
  • trailing whitespace tidak masalah

SKOR

  • Paling tidak byte menang
Corey Ogburn
sumber
1
Kalimat pertama benar-benar membingungkan. Saya akan merekomendasikan mengatakan "keluaran daftar terpendek dari rentang terpanjang yang mungkin dari bilangan bulat berurutan". Kalau tidak, tantangan yang bagus!
Nathan Merrill
2
Saya cukup yakin kami pernah menghadapi tantangan ini sebelumnya, tetapi saya tidak menemukan istilah pencarian yang tepat. Adakah yang ingat?
xnor
4
@CoreyOgburn Ngomong-ngomong, apa yang mendorong Anda untuk memposting di PPCG? Kami mencoba mencari tahu mengapa kami mendapat banyak pengguna baru.
xnor
2
@ xnor Saya sudah mengawasi situs selama berbulan-bulan. Tak satu pun dari bahasa yang saya gunakan biasanya kandidat yang baik untuk jawaban dan saya belum pernah mengajukan pertanyaan sampai hari ini.
Corey Ogburn
1
@ xnor: Mirip dengan daftar pekerjaan rumah Maltysen tapi tidak sama.
Alex A.

Jawaban:

9

Python 2, 123 120 byte

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

Jika input dapat berupa daftar sebagai argumen fungsi, maka (terima kasih mbomb007 dan xnor untuk kondisional)

93 90 81 byte

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

(77 byte jika memimpin spasi dapat diterima - jatuhkan final [1:])

Ruth Franklin
sumber
Anda dapat mengubah str(n)ke `n`untuk menyimpan beberapa byte, jika Anda beralih ke Python 2.
mbomb007
Anda juga dapat membuat fungsi yang mengambil daftar sebagai masukan daripada menggunakan raw_input(), dan Anda dapat mengubah '-'+`n`ke `-n`. Dan karena Anda sekarang menggunakan Python 2, Anda dapat menghapus tanda kurung setelah print.
mbomb007
Menghasilkan bagian demi bagian string itu pintar. Untuk penghematan byte, umumnya lebih pendek untuk melakukan persyaratan dengan pemilihan daftar atau aritmatika, seperti def f(N):print''.join([' '+`n`,`-n`*(n+1 not in N)][n-1 in N]for n in sorted(N))[1:](yang dapat di-golf lebih lanjut).
xnor
Anda mungkin bisa menggunakan set(N)bukannya sorted(N); ini dengan benar akan beralih dari terkecil ke terendah saat menggunakan cPython tetapi tidak dijamin untuk semua implementasi sehingga ada beberapa pertanyaan tentang apakah ini valid atau tidak.
KSab
6

JavaScript (ES6): 171 154 140 137 byte

Terima kasih edc65 dan vihan1086 untuk tipsnya! [...n]sangat bagus tetapi tidak berfungsi dalam kasus ini karena angka multi-digit.

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

Varian ES5, 198 184 183 174 byte

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

rink.attendant.6
sumber
n.split tanpa tanda kurung sama sekali baru bagi saya! Tetapi [...n]lebih baik
edc65
@ edc65 Terima kasih, tidak pernah berpikir untuk membongkar string seperti itu.
rink.attendant.6
... tapi ... apakah itu berhasil dengan salah satu contoh? ada nomor multidigit, jadi Anda perlu split pada "" (ruang kosong) bukan "" (string kosong). Saya mungkin memberi Anda tip yang salah
edc65
@ edc65 Saya pikir ada sesuatu yang tampak berbeda maka saya menyadari bahwa test case gagal. Masih bagus untuk mempelajari sesuatu yang baru
rink.attendant.6
4

Ruby, 86 84 byte

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

Ini adalah versi yang sedikit golf dari contoh dalam dokumen untuk slice_when .

steenslag
sumber
4

CJam, 35 byte

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

Cobalah online di juru bahasa CJam .

Bagaimana itu bekerja

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.
Dennis
sumber
4

Ruby, 70 byte

Masalah seperti ini cenderung membuat saya memeriksa API Ruby untuk metode yang sesuai, dan hari ini saya menemukan metode baru Array#slice_when:, baru diperkenalkan di Ruby v2.2 dan sepertinya ditujukan untuk situasi yang tepat ini :)

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

Setelah mengurutkan dan mengiris array dengan tepat, dibutuhkan setiap sub-array dan membuat string dari elemen tertinggi dan terendah, dan kemudian menggabungkan seluruh array ini ke dalam sebuah string.

Contoh:

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

daniero
sumber
4

SWI-Prolog, 165 162 159 byte

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

Cukup buruk tapi sekali lagi Prolog adalah bahasa golf yang mengerikan

Contoh: a([9,13,3,11,8,4,10,15,6]).keluaran3-4 6 8-11 13 15

Fatalisasi
sumber
3

CJam, 38 33 byte

Versi baru, menggunakan ide dan fragmen kode yang disarankan oleh @Dennis:

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

Cobalah online

Format input adalah array CJam dalam tanda kurung siku.

Ide dasar di sini adalah bahwa saya mengurangi urutan monoton dari urutan input yang diurutkan terlebih dahulu:

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

Dalam perbedaan ini, nilai yang merupakan bagian dari interval yang sama memiliki nilai yang sama. Menerapkan operator CJam RLE ke perbedaan ini secara langsung menyebutkan interval.

Nilai sekuensial yang dikurangi perlu ditambahkan kembali selama output. Saya tidak sepenuhnya senang dengan bagaimana hal itu dilakukan dalam kode saya. Saya menduga bahwa saya dapat menyimpan beberapa byte dengan cara yang lebih elegan untuk menyerahkannya.

Untuk menghasilkan output dari interval, ini menggunakan ide Dennis 'menghasilkan angka negatif untuk nilai akhir, yang mengurus memproduksi -, dan juga menyederhanakan logika karena hanya satu nilai yang perlu ditambahkan / dihilangkan tergantung pada ukuran interval .

Penjelasan:

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.
Reto Koradi
sumber
Itu adalah penggunaan RLE yang cerdas! Dengan meminjam rentang penanganan dan format input dari jawaban saya, Anda bisa turun ke 34 byte:l~$_,,.-e`{~T+\_T+:T;,f+(\W>Wf*S}/
Dennis
Ketika saya awalnya melihat solusi Anda, saya agak bingung bagaimana Anda mendapatkan -output tanpa muncul di kode, dan tanpa syarat. Sekarang saya mengerti: Itu berasal dari mengubah nilai akhir menjadi angka negatif! Saya tidak akan pernah menghasilkan ini, jadi saya akan merasa buruk karena menyalinnya. Saya akan mencoba belajar darinya untuk waktu berikutnya! :)
Reto Koradi
Cukup adil. Bagaimana dengan l~$_,,.-e{~ T + _T +: T; (_ 2 $ + W * Q? S} / `? Namun, itu jauh lebih mirip dengan kode Anda sendiri dan beratnya hanya 33 byte.
Dennis
@ Dennis Ok, jika Anda bersikeras. :) Sebenarnya, mengambil ide kunci untuk menghasilkan nilai negatif untuk akhir interval, ini terlihat seperti cara yang cukup mudah untuk mengimplementasikannya. Terima kasih.
Reto Koradi
2

CoffeeScript, 178 161 byte

Sama seperti jawaban JavaScript saya. Saya perlu mencari tahu apakah menggunakan pemahaman akan menghasilkan kode yang lebih pendek.

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

Asli:

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
rink.attendant.6
sumber
1

Python 2, 126 122 121 byte

Saya tahu ini bisa menjadi lebih pendek, hanya saja tidak tahu di mana .. Membutuhkan input dalam bentuk [#, #, #, #, ..., #].

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
Kade
sumber
Anda sepertinya menemukan solusi dengan execcukup sering.
mbomb007
@ mbomb007 Anda mungkin berpikir tentang xnor :) Dan saya pikir dalam situasi ini, perulangan mungkin sama, bahkan lebih pendek (belum bermain-main dengannya).
Kade
1
Anda harus dapat mengganti while x<len(l)dengan while l[x:]untuk menyimpan beberapa byte.
mathmandan
1

Java, 191 byte

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

Memeriksa rentang dan mencetaknya sesuai. Sayangnya saya harus membuat kasus khusus untuk elemen terakhir dalam array karena program akan berakhir tanpa mencetak angka atau rentang terakhir.

TNT
sumber
1

Java, 171 162 byte

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

Mengambil input sebagai array int, mengembalikan output sebagai daftar String yang dipisahkan oleh ruang

vijrox
sumber