กำหนดช่วงจากรายการของค่า


18

รับรายการที่ไม่เรียงลำดับของจำนวนเต็มบวกที่ไม่ซ้ำกันส่งออกรายการที่สั้นที่สุดของช่วงที่เป็นไปได้ที่ยาวที่สุดของจำนวนเต็มตามลำดับ

INPUT

  • รายการที่ไม่เรียงลำดับของจำนวนเต็มบวกที่ไม่ซ้ำกัน
    • เช่น 9 13 3 11 8 4 10 15
  • อินพุตสามารถนำมาจากหนึ่งในสิ่งต่อไปนี้:
    • stdin
    • อาร์กิวเมนต์บรรทัดคำสั่ง
    • อาร์กิวเมนต์ของฟังก์ชัน

เอาท์พุท

  • รายการช่วงที่สั่งซื้อหรือค่าแต่ละค่าที่พิมพ์บนหนึ่งบรรทัดเพื่อ stdout หรือเอาต์พุตที่ใกล้เคียงที่สุดของภาษาของคุณ
    • หากมีจำนวนเต็มต่อเนื่องสองตัวหรือมากกว่า (เรียงตามค่าไม่ใช่ตามตำแหน่งในรายการ) มันจะถูกแสดงว่าเป็นช่วงรวมโดยใช้ -, เช่น 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

เอาต์พุตไม่ถูกสั่งอย่างถูกต้อง

กฎ

SCORING

  • ไบต์ที่น้อยที่สุดชนะ

1
ประโยคแรกนั้นทำให้สับสนจริงๆ ฉันขอแนะนำให้พูดว่า "แสดงรายการที่สั้นที่สุดของช่วงที่เป็นไปได้ที่ยาวที่สุดของจำนวนเต็มตามลำดับ" มิฉะนั้นเป็นความท้าทายที่ดี!
Nathan Merrill

2
ฉันค่อนข้างมั่นใจว่าเราเคยมีความท้าทายนี้มาก่อน แต่ฉันไม่ได้มากับคำค้นหาที่เหมาะสม ใครจำได้บ้าง
xnor

4
@CoreyOgburn โดยวิธีการอะไรแจ้งให้คุณโพสต์บน PPCG? เรากำลังพยายามหาสาเหตุที่ทำให้เรามีผู้ใช้ใหม่เข้ามาทั้งหมด
xnor

2
@xnor ฉันเฝ้าดูไซต์เป็นเวลาหลายเดือนแล้ว ไม่มีภาษาใดที่ฉันใช้มักเป็นคำตอบที่ดีและฉันไม่เคยมีคำถามที่จะโพสต์จนถึงทุกวันนี้
Corey Ogburn

1
@xnor: มันคล้ายกับรายการบ้านของ Maltysen แต่ไม่เหมือนกัน
Alex 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:])


คุณสามารถเปลี่ยนstr(n)เป็น`n`บันทึกได้สองสามไบต์หากคุณเปลี่ยนเป็น Python 2
mbomb007

นอกจากนี้คุณยังสามารถสร้างฟังก์ชั่นที่ใช้รายการเป็น input แทนการใช้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

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.split โดยไม่มีวงเล็บเป็นสิ่งใหม่สำหรับฉัน! แต่[...n]จะดีกว่า
edc65

@ edc65 ขอบคุณอย่าคิดว่าจะเอาสตริงออกมาอย่างนั้น
rink.attendant.6


... แต่ ... มันใช้ได้กับตัวอย่างใด ๆ หรือไม่? มีตัวเลขหลายหลักดังนั้นคุณต้องแยกเป็น "" (ช่องว่าง) ไม่ใช่ "" (สตริงว่าง) ฉันอาจให้ทิปผิดกับคุณ
edc65

@ edc65 ฉันคิดว่าบางอย่างดูแตกต่างออกไปจากนั้นฉันก็รู้ว่ากรณีทดสอบล้มเหลว ยังดีที่จะเรียนรู้สิ่งใหม่แม้ว่า
rink.attendant.6

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 กับความแตกต่างนี้จะระบุช่วงเวลาโดยตรง

ค่าลำดับที่ถูกลบจะต้องเพิ่มกลับมาในระหว่างการส่งออก ฉันไม่พอใจกับวิธีการที่ทำในรหัสของฉันทั้งหมด ฉันสงสัยว่าฉันสามารถบันทึกได้สองสามไบต์ด้วยวิธีการที่สง่างามกว่า

สำหรับการสร้างเอาท์พุทของช่วงเวลานี้ใช้ความคิดของเดนนิสในการสร้างจำนวนลบสำหรับค่าสุดท้ายซึ่งดูแลการสร้าง-และยังลดความซับซ้อนของตรรกะเนื่องจากต้องเพิ่ม / ละเว้นเพียงค่าเดียวเท่านั้นขึ้นอยู่กับขนาดของช่วงเวลา .

คำอธิบาย:

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}/
เดนนิส

เมื่อฉันดูโซลูชันของคุณในตอนแรกฉันก็ประหลาดใจว่าคุณได้รับ-ผลลัพธ์โดยไม่แสดงในโค้ดและไม่มีเงื่อนไข ตอนนี้ฉันเข้าใจแล้ว: มันมาจากการเปลี่ยนค่าสิ้นสุดให้เป็นจำนวนลบ! ฉันไม่เคยคิดเกี่ยวกับสิ่งนี้ดังนั้นฉันจะรู้สึกไม่ดีเกี่ยวกับการคัดลอก ฉันจะพยายามเรียนรู้จากมันในครั้งต่อไป! :)
Reto Koradi

ยุติธรรมพอสมควร วิธีการเกี่ยวกับl~$_,,.-e{~ T + _T +: T; (_ 2 $ + W * Q? S} / `นั่นเป็นอะไรที่คล้ายกับรหัสของคุณและมีน้ำหนักเพียง 33 ไบต์
Dennis

@Dennis Ok ถ้าคุณยืนยัน :) ที่จริงแล้วการนำแนวคิดสำคัญของการสร้างค่าลบสำหรับการสิ้นสุดช่วงเวลาออกมา ขอบคุณ
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 Bytes

ฉันรู้ว่ามันสั้นลงแค่ไม่รู้ว่า .. ต้องป้อนข้อมูลในรูปแบบ[#, #, #, #, ..., #]ใด

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 :) และฉันคิดว่าในสถานการณ์นี้การวนซ้ำอาจมีความยาวเท่ากันแม้จะสั้นกว่า (ยังไม่ได้เล่นรอบพอ)
Kade

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 ส่งคืนเอาต์พุตเป็นรายการ String ที่คั่นด้วยช่องว่าง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.