Określ zakresy na podstawie listy wartości


18

Biorąc pod uwagę nieposortowaną listę unikatowych, dodatnich liczb całkowitych, wypisz najkrótszą listę z najdłuższych możliwych zakresów liczb całkowitych sekwencyjnych.

WEJŚCIE

  • Nieposortowana lista unikalnych, dodatnich liczb całkowitych
    • na przykład 9 13 3 11 8 4 10 15
  • Dane wejściowe można pobrać z jednego z poniższych:
    • stdin
    • argumenty wiersza poleceń
    • argumenty funkcji

WYNIK

  • Uporządkowana lista zakresów lub poszczególnych wartości drukowana w jednym wierszu na standardowe wyjście lub najbliższy podobny wynik w twoim języku.
    • Jeśli obecne są dwie lub więcej kolejnych liczb całkowitych (sekwencyjnych według wartości, a nie według lokalizacji na liście), zostaną one oznaczone jako zakres obejmujący za pomocą -, np. 8-11
    • Wszystkie inne liczby całkowite są po prostu drukowane bez żadnej innej notacji
    • Pojedyncza spacja ograniczy wynik
  • Liczby nieobecne na wejściu nie powinny znajdować się na wyjściu, np. 3 5 6Nie można ich skrócić, 3-6ponieważ 4nie jest obecny

PRZYKŁADY

Odnoszący sukcesy:

 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

Źle:

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

Zakres zawiera wartości, których nie ma na wejściu

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

Wszystkie kolejne wartości powinny być reprezentowane jako zakres

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

Podzielony zakres 8-9i 10-11powinien być8-11

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

Wyjście nie zostało poprawnie zamówione

ZASADY

  • Standardowe luki są niedozwolone
  • Jeśli Twój język ma taką funkcję, jest to niedozwolone
  • Możesz napisać pełny program lub funkcję
  • końcowe białe znaki nie mają znaczenia

PUNKTACJA

  • Najmniej bajtów wygrywa

1
Pierwsze zdanie jest bardzo mylące. Polecam powiedzenie „wypisz najkrótszą listę najdłuższych możliwych zakresów liczb całkowitych sekwencyjnych”. W przeciwnym razie miłe wyzwanie!
— Nathan Merrill

2
Jestem prawie pewien, że mieliśmy już takie wyzwanie, ale nie mam odpowiednich kryteriów wyszukiwania. Czy ktoś pamięta?
— xnor

4
@CoreyOgburn Przy okazji, co skłoniło cię do opublikowania postu na PPCG? Próbujemy dowiedzieć się, dlaczego przybywa cała masa nowych użytkowników.
— xnor

2
@xnor Od miesięcy mam oko na stronę. Żaden z używanych przeze mnie języków nie jest zwykle dobrym kandydatem na odpowiedź i do dziś nie miałem pytania.
— Corey Ogburn,

1
@xnor: Jest podobny do pierwszej listy zadań domowych Maltysena, ale nie jest identyczny.
— Alex A.

Odpowiedzi:


9

Python 2, 123 120 bajtów

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

Jeśli dane wejściowe mogą być listą jako argumentem funkcji, to (dzięki mbomb007 i xnor za instrukcje warunkowe)

93 90 81 bajtów

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

(77 bajtów, jeśli dopuszczalne są wiodące białe znaki - upuść końcowy [1:])


Możesz zmienić, str(n)aby `n`zapisać kilka bajtów, jeśli przełączysz się na Python 2.
— mbomb007

Możesz także utworzyć funkcję, która zamiast danych pobiera listę jako dane wejściowe raw_input(), i możesz zmienić '-'+`n`na `-n`. A ponieważ używasz teraz języka Python 2, możesz usunąć nawiasy po print.
— mbomb007

Generowanie struny kawałek po kawałku jest sprytne. Aby zaoszczędzić bajty, generalnie krótsze jest robienie warunkowe przez wybór listy lub arytmetykę, np. def f(N):print''.join([' '+`n`,`-n`*(n+1 not in N)][n-1 in N]for n in sorted(N))[1:](Które można dalej grać w golfa).
— xnor

Możesz być w stanie użyć set(N)zamiast sorted(N); spowoduje to poprawną iterację od najmniejszej do najniższej przy użyciu cPython, ale nie gwarantuje się, że będzie działać dla wszystkich implementacji, więc jest pewne pytanie, czy jest to poprawne.
— KSab

6

JavaScript (ES6): 171 154 140 137 bajtów

Dzięki edc65 i vihan1086 za wskazówki! [...n]jest bardzo fajny, ale nie działa w takich przypadkach ze względu na liczby wielocyfrowe.

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

Wariant ES5, 198 184 183 174 bajtów

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 bez nawiasów jest dla mnie zupełnie nowy! Ale [...n]jest lepiej
— edc65

@ edc65 Dzięki, nigdy nie myślałem o rozpakowaniu takiego łańcucha.
— rink.attendant. 6


... ale ... czy to działa z dowolnym przykładem? istnieją liczby wielocyfrowe, więc potrzebujesz podziału na „” (spację), a nie „” (pusty ciąg). Prawdopodobnie dałem ci złą wskazówkę
— edc65,

@ edc65 Myślałem, że coś wygląda inaczej, ale zdałem sobie sprawę, że testy zakończyły się niepowodzeniem. Nadal dobrze jest nauczyć się czegoś nowego
— rink.attendant. 6

4

Rubin, 86 84 bajtów

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

Jest to lekko golfowa wersja z przykładu w dokumentacji dla slice_when .


4

CJam, 35 bajtów

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

Wypróbuj online w interpretatorze CJam .

Jak to działa

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

Rubinowy, 70 bajtów

Problemy takie jak te powodują, że sprawdzam API Ruby pod kątem odpowiednich metod, a dziś odkryłem nowy: Array#slice_whennowo wprowadzony w Ruby v2.2 i najwyraźniej przeznaczony do tej dokładnej sytuacji :)

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

Po posortowaniu i odpowiednim pocięciu tablicy, pobiera ona każdą pod-tablicę i tworzy ciąg z najwyższego i najniższego elementu, a następnie łączy całą tablicę w ciąg.

Przykład:

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


4

SWI-Prolog, 165 162 159 bajtów

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

Całkiem źle, ale z drugiej strony Prolog to straszny język golfa

Przykład: a([9,13,3,11,8,4,10,15,6]).wyjścia3-4 6 8-11 13 15


3

CJam, 38 lat 33 bajtów

Nowa wersja, wykorzystująca pomysły i fragmenty kodu sugerowane przez @Dennis:

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

Wypróbuj online

Format wejściowy to tablica CJam w nawiasach kwadratowych.

Podstawową ideą jest to, że najpierw odejmuję sekwencję monotoniczną od posortowanej sekwencji wejściowej:

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

W tej różnicy wartości, które są częścią tego samego przedziału, mają tę samą wartość. Zastosowanie operatora RLE CJam do tej różnicy bezpośrednio wylicza interwały.

Odejmowane wartości sekwencyjne należy dodać z powrotem podczas generowania. Nie jestem do końca zadowolony z tego, jak to się dzieje w moim kodzie. Podejrzewam, że mógłbym zaoszczędzić kilka bajtów w bardziej elegancki sposób.

Do generowania danych wyjściowych przedziałów wykorzystuje pomysł Dennisa, aby wygenerować liczbę ujemną dla wartości końcowej, która zajmuje się wytworzeniem - , a także upraszcza logikę, ponieważ tylko jedna wartość musi być dodana / pominięta w zależności od wielkości przedziału .

Wyjaśnienie:

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.

To sprytne zastosowanie RLE! Pożyczając obsługę zakresu i format wejściowy z mojej odpowiedzi, możesz dostać się do 34 bajtów:l~$_,,.-e`{~T+\_T+:T;,f+(\W>Wf*S}/
— Dennis

Kiedy początkowo patrzyłem na twoje rozwiązanie, byłem trochę zdziwiony, w jaki sposób dostałeś się -do wyjścia bez pokazania go w kodzie i bez warunku. Teraz rozumiem: Pochodzi z zamiany wartości końcowej na liczbę ujemną! Nigdy bym tego nie wymyślił, więc źle byłoby mi go skopiować. Spróbuję się od tego uczyć następnym razem! :)
— Reto Koradi

Słusznie. Co powiesz na l~$_,,.-e{~ T + _T +: T; (_ 2 $ + W * Q? S} / `chociaż? Jest to o wiele bardziej podobne do twojego kodu i waży tylko 33 bajty.
— Dennis

@Dennis Ok, jeśli nalegasz. :) Właściwie, biorąc pod uwagę kluczowy pomysł generowania wartości ujemnej dla końca interwału, wygląda to na dość prosty sposób na jej wdrożenie. Dzięki.
— Reto Koradi

2

CoffeeScript, 178 161 bajtów

Tak jak moja odpowiedź JavaScript. Muszę dowiedzieć się, czy użycie wyrażeń spowoduje skrócenie kodu.

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

Oryginalny:

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 bajtów

Wiem, że to może być krótsze, po prostu nie wiem, gdzie .. Wymaga wprowadzenia formularza [#, #, #, #, ..., #].

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

Wygląda na to, execże często znajdziesz rozwiązania .
— mbomb007

@ mbomb007 Być może myślisz o xnor :) I myślę, że w tej sytuacji zapętlenie może być tej samej długości, nawet krótszej (nie bawiłem się już wystarczająco długo).
— Kade

1
Powinieneś być w stanie wymienić while x<len(l)z while l[x:]zaoszczędzić kilka bajtów.
— matmandan

1

Java, 191 bajtów

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

Sprawdza zakresy i odpowiednio je drukuje. Niestety musiałem zrobić specjalny przypadek dla ostatniego elementu w tablicy, ponieważ program zakończyłby się bez drukowania ostatniej liczby lub zakresu.


1

Java, 171 162 bajtów

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

Pobiera dane wejściowe jako tablicę int, zwraca dane wyjściowe jako rozdzieloną spacjami listę ciągów

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.