Xác định phạm vi từ danh sách các giá trị


18

Đưa ra một danh sách chưa sắp xếp các số nguyên dương, duy nhất, đưa ra danh sách ngắn nhất trong phạm vi dài nhất có thể của các số nguyên tuần tự.

ĐẦU VÀO

  • Một danh sách chưa được sắp xếp của các số nguyên duy nhất, tích cực
    • ví dụ 9 13 3 11 8 4 10 15
  • Đầu vào có thể được lấy từ bất kỳ một trong những điều sau đây:
    • stdin
    • đối số dòng lệnh
    • đối số chức năng

ĐẦU RA

  • Một danh sách theo thứ tự các phạm vi hoặc các giá trị riêng lẻ được in trên một dòng tới thiết bị xuất chuẩn hoặc đầu ra tương tự gần nhất với ngôn ngữ của bạn.
    • Nếu có hai hoặc nhiều số nguyên tuần tự (tuần tự theo giá trị, không phải theo vị trí trong danh sách), chúng sẽ được ký hiệu là một phạm vi bao gồm sử dụng -, ví dụ: 8-11
    • Tất cả các số nguyên khác được in đơn giản mà không có ký hiệu nào khác
    • Một không gian duy nhất sẽ phân định đầu ra
  • Các số không có trong đầu vào không nên ở đầu ra, ví dụ 3 5 6không thể rút ngắn 3-64không có mặt

VÍ DỤ

Thành công:

 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

Sai lầm:

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

Phạm vi chứa các giá trị không có trong đầu vào

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

Tất cả các giá trị tuần tự phải được biểu diễn dưới dạng một phạm vi

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

Phạm vi phân chia, 8-910-11nên được8-11

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

Đầu ra không được đặt đúng

QUY TẮC

  • Các sơ hở tiêu chuẩn không được phép
  • Nếu ngôn ngữ của bạn có chức năng để làm điều này thì nó không được phép
  • Bạn có thể viết một chương trình đầy đủ, hoặc một chức năng
  • khoảng trắng dấu vết không quan trọng

KIẾM

  • Ít nhất là chiến thắng

1
Câu đầu tiên thực sự khó hiểu. Tôi khuyên bạn nên nói "xuất ra danh sách ngắn nhất trong phạm vi số nguyên liên tiếp dài nhất có thể". Nếu không, thử thách tốt đẹp!
Nathan Merrill

2
Tôi khá chắc chắn rằng chúng tôi đã có thử thách này trước đây, nhưng tôi không đưa ra các thuật ngữ tìm kiếm phù hợp. Có ai nhớ không?
xnor

4
@CoreyOgburn Nhân tiện, điều gì đã thôi thúc bạn đăng bài trên PPCG? Chúng tôi đang cố gắng tìm hiểu lý do tại sao chúng tôi có cả đống người dùng mới tham gia.
xnor

2
@xnor Tôi đã để mắt đến trang web trong nhiều tháng. Không có ngôn ngữ nào tôi sử dụng thường là ứng cử viên tốt cho câu trả lời và tôi chưa bao giờ có câu hỏi để đăng cho đến ngày hôm nay.
Corey Ogburn

1
@xnor: Nó tương tự như danh sách bài tập về nhà của Maltysen một nhưng không giống nhau.
Alex A.

Câu trả lời:


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

Nếu đầu vào có thể là một danh sách dưới dạng đối số hàm thì (cảm ơn mbomb007 và xnor cho các điều kiện)

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 nếu khoảng trắng hàng đầu có thể chấp nhận được - bỏ phần cuối cùng [1:])


Bạn có thể thay đổi str(n)để `n`lưu một vài byte, nếu bạn chuyển sang Python 2.
mbomb007

Bạn cũng có thể tạo một chức năng lấy danh sách làm đầu vào thay vì sử dụng raw_input()và bạn có thể thay đổi '-'+`n`thành `-n`. Và vì bạn hiện đang sử dụng Python 2, bạn có thể xóa dấu ngoặc đơn sau print.
mbomb007

Tạo chuỗi từng mảnh là thông minh. Để tiết kiệm byte, thường ngắn hơn để thực hiện các điều kiện bằng cách chọn danh sách hoặc số học, như def f(N):print''.join([' '+`n`,`-n`*(n+1 not in N)][n-1 in N]for n in sorted(N))[1:](có thể được đánh gôn thêm).
xnor

Bạn có thể sử dụng set(N)thay vì sorted(N); điều này sẽ lặp lại chính xác từ nhỏ nhất đến thấp nhất khi sử dụng cPython nhưng không được đảm bảo để hoạt động cho tất cả các triển khai vì vậy có một số câu hỏi về việc liệu điều này có hợp lệ hay không.
KSab

6

JavaScript (ES6): 171 154 140 137 byte

Cảm ơn edc65 và vihan1086 cho lời khuyên! [...n]là rất tốt nhưng nó không hoạt động trong những trường hợp này do số nhiều chữ số.

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

Biến thể 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)}


n.split không có dấu ngoặc đơn là hoàn toàn mới đối với tôi! Nhưng [...n]tốt hơn
edc65

@ edc65 Cảm ơn, đừng bao giờ nghĩ đến việc giải nén chuỗi như thế.
rink.attguard.6


... nhưng ... nó có hoạt động với bất kỳ ví dụ nào không? có nhiều số, vì vậy bạn cần phân chia trên "" (khoảng trống) chứ không phải "" (chuỗi trống). Tôi có thể đã cho bạn lời khuyên sai
edc65

@ edc65 Tôi nghĩ có gì đó khác đi thì tôi nhận ra các trường hợp thử nghiệm thất bại. Vẫn còn tốt để học một cái gì đó mới
rink.attguard.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

Đây là một phiên bản hơi bị đánh gôn từ một ví dụ trong tài liệu cho lát_when .


4

CJam, 35 byte

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

Dùng thử trực tuyến trong thông dịch CJam .

Làm thế nào nó hoạt động

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 byte

Các vấn đề như thế này có xu hướng khiến tôi kiểm tra API Ruby để biết các phương pháp phù hợp và hôm nay tôi phát hiện ra một vấn đề mới : Array#slice_when, mới được giới thiệu trong Ruby v2.2 và dường như dành cho tình huống chính xác này :)

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

Sau khi sắp xếp và cắt một cách thích hợp mảng, nó sẽ lấy từng mảng con và tạo một chuỗi ra khỏi phần tử cao nhất và thấp nhất, sau đó nối toàn bộ mảng này thành một chuỗi.

Thí dụ:

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


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

Khá tệ nhưng sau đó một lần nữa Prolog là một ngôn ngữ chơi golf khủng khiếp

Ví dụ: a([9,13,3,11,8,4,10,15,6]).đầu ra3-4 6 8-11 13 15


3

CJam, 38 33 byte

Phiên bản mới, sử dụng các ý tưởng và đoạn mã được đề xuất bởi @Dennis:

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

Dùng thử trực tuyến

Định dạng đầu vào là một mảng CJam trong ngoặc vuông.

Ý tưởng cơ bản ở đây là tôi trừ một chuỗi đơn điệu khỏi chuỗi đầu vào được sắp xếp trước:

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

Trong sự khác biệt này, các giá trị là một phần của cùng một khoảng có cùng giá trị. Áp dụng toán tử CJam RLE cho sự khác biệt này liệt kê trực tiếp các khoảng.

Các giá trị tuần tự được trừ cần được thêm lại trong quá trình đầu ra. Tôi không hoàn toàn hài lòng với cách thực hiện trong mã của mình. Tôi nghi ngờ rằng tôi có thể tiết kiệm một vài byte với cách xử lý thanh lịch hơn.

Để tạo đầu ra của các khoảng, điều này sử dụng ý tưởng của Dennis là tạo số âm cho giá trị cuối, đảm nhiệm việc tạo ra một số - và cũng đơn giản hóa logic vì chỉ cần thêm / bỏ một giá trị tùy thuộc vào kích thước khoảng .

Giải trình:

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.

Đó là cách sử dụng thông minh của RLE! Bằng cách mượn định dạng đầu vào và xử lý phạm vi từ câu trả lời của tôi, bạn có thể nhận được tới 34 byte:l~$_,,.-e`{~T+\_T+:T;,f+(\W>Wf*S}/
Dennis

Khi tôi ban đầu nhìn vào giải pháp của bạn, tôi đã hơi bối rối về cách bạn có được một -đầu ra mà không hiển thị trong mã và không có điều kiện. Bây giờ tôi hiểu rồi: Nó xuất phát từ việc biến giá trị cuối thành số âm! Tôi sẽ không bao giờ nghĩ ra điều này, vì vậy tôi sẽ cảm thấy tồi tệ khi sao chép nó. Tôi sẽ cố gắng học hỏi từ lần sau! :)
Reto Koradi

Đủ công bằng. Mặc dù thế nào về l~$_,,.-e{~ T + _T +: T; (_ 2 $ + W * Q? S} / `? Điều đó rất giống với mã của riêng bạn và chỉ nặng 33 byte.
Dennis

@Dennis Ok, nếu bạn khăng khăng. :) Trên thực tế, lấy ý tưởng chính là tạo ra giá trị âm cho khoảng thời gian kết thúc, đây có vẻ là một cách đơn giản để thực hiện nó. Cảm ơn.
Reto Koradi

2

CoffeeScript, 178 161 byte

Giống như câu trả lời JavaScript của tôi. Tôi cần phải tìm ra nếu sử dụng hiểu sẽ dẫn đến mã ngắn hơn.

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

Nguyên:

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 byte

Tôi biết điều này có thể ngắn hơn, chỉ không biết ở đâu .. Yêu cầu đầu vào dưới dạng [#, #, #, #, ..., #].

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

Bạn dường như tìm thấy giải pháp với execkhá thường xuyên.
mbomb007

@ mbomb007 Bạn có thể nghĩ về xnor :) Và tôi nghĩ trong tình huống này, vòng lặp có thể có cùng độ dài, thậm chí ngắn hơn (chưa chơi đủ với nó).
Kade

1
Bạn sẽ có thể thay thế while x<len(l)bằng while l[x:]để lưu một vài 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];}}}

Kiểm tra phạm vi và in chúng cho phù hợp. Thật không may, tôi đã phải tạo một trường hợp đặc biệt cho phần tử cuối cùng trong mảng vì chương trình sẽ chấm dứt mà không in số hoặc phạm vi cuối cùng.


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

Lấy đầu vào dưới dạng một mảng int, trả về đầu ra dưới dạng danh sách Chuỗi được phân tách bằng dấu cách

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.