Ciąg znaków alfanumerycznych do posortowanej listy zakresów oddzielonych przecinkami

12

Biorąc pod uwagę ciąg nieposortowanych znaków alfanumerycznych, np

ABC321STPpJqZZr0

wypisuje "," oddzieloną listę zakresów znaków, posortowaną według wartości ASCII, ignorując wielkość liter i usuwając duplikaty ( tj. wypisując tylko wielkie i cyfry), np.

0-3, A-C, J, P-T, Z

Zasady

  • Długość twojego programu jest jak zwykle wynikiem podstawowym.
  • Musisz zainicjować (zakodować) powyższy przykład w swoim programie, ale można lekceważyć tego przykładu długość od długości programu, na przykład na char* s="ABC321STPpJqZZr0";można lekceważyć 16 znaków, pozostałe 11 znaków licząc w kierunku swojej długości programu.

Bonus (+50 nagród)

  • Ponieważ był to prawdziwy problem, z którym borykał się dziś mój współpracownik, który musi być napisany w Tcl 8.0.5 (starożytna wersja, pozbawiona wielu najnowszych wbudowanych Tcl), przyznam 50 punktów temu, kto napisze najkrótszą Tcl 8.0 .5 rozwiązanie, jeśli są co najmniej 2 ważne zgłoszenia w Tcl 8.0.5.
Andrew Cheong
źródło
@ FezVrasta - Celowo napisałem, ", "aby uwzględnić spację, ale możemy zostawić Twoją edycję i pozwolić, aby ten komentarz służył jako wskazówka.
Andrew Cheong
Dlaczego celowo dołączasz GolfScript? Dlaczego nie zezwolić na inne języki, takie jak Befunge?
Justin
Można powiedzieć, że wszystko jest uczciwe. Po prostu nie będę w stanie sprawdzić większości z nich bardzo łatwo.
Andrew Cheong,
Więc czy to jest tag Code-Golf?
VisioN
1
@Cron - Dobry połów. AB w moim przypadku, ale ponieważ było już wiele zgłoszeń, pozwólmy na oba sposoby.
Andrew Cheong,

Odpowiedzi:

5

Rubin, 87-16 = 71

EDYCJA: Musiałem dodać kilka znaków, aby zakresy dwóch znaków były wyświetlane poprawnie. Również ?[zamiast ?Znaprawić błąd, którego zakresy kończą się na Z.

$><<[*?0..?[].join.gsub(/[^ABC321STPpJqZZr0]/i,$/).gsub(/\B.+\B/,?-).scan(/.-.|./)*', '

Możesz zobaczyć bieg Ideone tutaj .

Paul Prestidge
źródło
+1 za jedną linijkę. Bardzo sprytne użycie różnych metod; To jest naprawdę genialne.
daniero
1
Pamiętaj, że gsub(/[]/i)jest krótszy niż tr(''.upcase)o 2 znaki. Ponadto, scan(/.+/)-> splitzapisuje 5, a $><<zamiast putsinnego.
Howard
@ Howard Świetne sugestie, dzięki!
Paul Prestidge
2

Julia, 131

julia> l=sort(unique(uppercase("ABC321STPpJqZZr0")))
julia> prod([!(c+1 in l)?"$c"*(c==l[end]?"":", "):!(c-1 in l)?"$c":(c+1 in l)&&!(c+2 in l)?"-":"" for c in l])

"0-3, A-C, J, P-T, Z"

Nieobsługiwany przez Ideone.com i prawdopodobnie zostanie i tak zmiażdżony.

gggg
źródło
1
W każdym razie dzięki! Ograniczenie Ideone.com było tylko po to, abym mógł go przetestować, ale przypuszczam, że mogę zaufać uczciwości golfistów i usunąć tę zasadę. W każdym razie +1.
Andrew Cheong,
2

C #, 221 bajtów

class P{
    static void Main(){
        var s="ABC321STPpJqZZr0";
        var l=new int[257];
        foreach(int c in s.ToUpper())
            l[c]=1;
        var r="";
        for(int i=0;i<255;){
            if(l[i++]-l[i]<0)
                r+=", "+(char)i;
            else if(l[i+1]-l[i]<0)
                r+="-"+(char)i;
        }
        System.Console.Write(r.Substring(2));
    }
}
Hand-E-Food
źródło
2

C 193

char*s="ABC321STPpJqZZr0";
int c[99];memset(c,0,396);while(*s){++c[toupper(*s++)];}for(int i=0,f=1,r=0;
i<=99;++i){if(!r&&c[i])r=i;if(r&&!c[i]){if(!f)printf(", ");putchar(r);
if(i-r>1)printf("-%c",i-1);r=f=0;}}
warrenm
źródło
Czy możesz dodać małe wyjaśnienie?
Justin
Iteruj po ciągu, gromadząc liczbę wystąpień każdego znaku alfanumerycznego. Następnie iteruj wszystkie znaki alfanumeryczne w kolejności alfabetycznej, zapisując początek każdego zwartego zakresu i, w razie potrzeby, myślnik, a następnie koniec zakresu. Jeśli nie jest to pierwszy zapisany zakres, dodaj separator przecinka. Kod musi być osadzony w funkcji main () z dołączonymi odpowiednimi nagłówkami (stdio, string, ctypes), więc trochę oszukiwałem.
warrenm
2

GolfScript 57 54 52

 'ABC321STPpJqZZr0'
 {.95>32*-}%.|:x..{(}%&-x..{)}%&-+$2/{.|'-'*}%', '*

Wypróbuj tutaj .

Kod najpierw wszystko zaczyna od wielkich liter:

{.95>32*-}%

Następnie pobiera unikalne znaki i zapisuje je w zmiennej:

.|:x

Następnie otrzymujemy znaki, których bezpośrednich poprzedników nie ma w ciągu (tak, że są początkową częścią zakresu):

..{)}%&-x

Podobnie otrzymujemy końce zakresów x..{)}%&-.

Teraz faktycznie tworzą zakresy, łącząc listy, sortując i dzieląc na grupy po 2:

+$2/

Reszta to po prostu formatowanie, używając *jako łączenia ciągów.

Ben Reich
źródło
1
Na wyjściu zakresy muszą być oddzielone „,” a nie tylko „,”
Paul Prestidge
1
Również .95>{32-}{}if-> .95>32*-zapisuje 5 znaków.
Howard
@ Howard Great! Wiedziałem, że ta część była nieoptymalna.
Ben Reich,
1
@Chron Naprawiono problem z przestrzenią!
Ben Reich,
2

Q, 94

{","sv(,/){{"-"sv(?) -1 1#\:x}'[cut[;a]0,1_(&)1<(-':)"i"$'a:asc upper[x]inter y]}[x]'[.Q`n`A]}
tartin
źródło
1

Python 2.x, 304-16 = 288

Z pewnością można to jeszcze pograć w golfa, wszystkie komentarze mile widziane!

e=[""]*11;f=[""]*27
for c in"ABC321STPpJqZZr0".lower():e["0123456789".find(c)]=f["abcdefghijklmnopqrstuvwxyz".find(c)]=c
e[-1]=f[-1]=""
def h(j):
 g=[];k=l=i=0
 for e in j:
  if e:
   if not l:k=i;l=1
  elif l:l=g.append((k,i-1))
  i+=1
 print", ".join([j[m],j[m]+"-"+j[n]][n-m>1]for m,n in g)
h(e);h(f)
ChristopheD
źródło
1

Rebol (218 - 16 = 202)

m: s: sort uppercase unique"ABC321STPpJqZZr0"i: :to-integer f: does[either 1 = length? x: copy/part m s[x][rejoin[x/1"-"last x]]]while[not tail? s: next s][if(1 + i pick back s 1)!=(i s/1)[prin join f", "m: s]]print f

Wersja niezminimalizowana:

m: s: sort uppercase unique "ABC321STPpJqZZr0"
i: :to-integer

f: does [
    either 1 = length? x: copy/part m s [x] [rejoin [x/1 "-" last x]]
]

while [not tail? s: next s][
    if (1 + i pick back s 1) != (i s/1) [
        prin join f ", "
        m: s
    ]
]

print f
draegtun
źródło
1

q [116 znaków]

{.a:();{m:6h$x;.a:.a,$[m[1]=1+m[0];45;m[0],44,m 1];1_x}/[x:asc distinct upper x];p where differ 6h$p:-3_10h$x[0],.a}

Stosowanie

{.a:();{m:6h$x;.a:.a,$[m[1]=1+m[0];45;m[0],44,m 1];1_x}/[x:asc distinct upper x];p where differ 6h$p:-3_10h$x[0],.a}"ABC321STPpJqZZr0"
Wynik
"0-3,A-C,J,P-T,Z"

Istnieje możliwość zapisywania znaków, wypróbuję inną metodę i opublikuję ją.

nyi
źródło
0

Tcl 8.0.5, 344 (360 bajtów)

set a ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
set s string
set x [join [lsort [split [$s toupper ABC321STPpJqZZr0] ""]] ""]
regsub -all (.)\\1+ $x \\1 x
set i 36
while {[incr i -1]} {set j -1
while {$i+[incr j]<36} {set y [$s range $a $j [expr $i+$j]]
regsub $y $x [$s index $y 0]-[$s index $y end],\  x}}
while {[regsub -all {(\w)(\w)} $x {\1, \2} x]} {}
puts $x

Tcl 8.0.5, 340 (356 bajtów)

Majstrowanie przy renamepoleceniu przyniosło zabawne sztuczki! Udokumentowałem je w innym wątku .

rename rename &
& set =
& regsub R
& string S
& while W
= a ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
= x [lsort [split [S toupper ABC321STPpJqZZr0] ""]]
R -all {(.) \1+| } $x \\1 x
= i 36
W {[incr i -1]} {= j -1
W {$i+[incr j]<36} {= y [S range $a $j [expr $i+$j]]
R $y $x [S index $y 0]-[S index $y end],\  x}}
W {[R -all {(\w)(\w)} $x {\1, \2} x]} {}
puts $x

Tcl 8.0.5, 332 (348 bajtów) [Niestabilny - zależy od $ PATH]

info script ""
set tcl_interactive 1
set a ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
set x [lso [sp [st toupper ABC321STPpJqZZr0] ""]]
regs -all {(.) \1+| } $x \\1 x
set i 36
wh {[inc i -1]} {set j -1
wh {$i+[inc j]<36} {set y [st range $a $j [exp $i+$j]]
regs $y $x [st index $y 0]-[st index $y end],\  x}}
wh {[regs {(\w)(\w)} $x {\1, \2} x]} {}
pu $x

Kredyt dla @JohannesKuhn dla interaktywnego podstęp .

Andrew Cheong
źródło
1
Czasami można zapisać bajtów zastąpienie whileprzez timekonstruktów. codegolf.stackexchange.com/a/126236/29325
sergiol