Sequência de caracteres alfanuméricos em uma lista classificada de intervalos separados por vírgula

12

Dada uma sequência de caracteres alfanuméricos não classificados, por exemplo ,

ABC321STPpJqZZr0

produz uma lista separada por "," de intervalos de caracteres, classificados pelo valor ASCII, ignorando maiúsculas e minúsculas e removendo duplicatas ( ou seja, produzindo apenas caracteres numéricos e maiúsculos), por exemplo

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

Regras

  • A duração do seu programa é sua pontuação base, como de costume.
  • Você deve inicializar (código fixo) o exemplo acima em seu programa, mas pode descontar o comprimento desse exemplo do seu comprimento, por exemplo , para char* s="ABC321STPpJqZZr0";você descontar 16 caracteres, os outros 11 caracteres contando o comprimento do programa.

Bônus (+50 de recompensa)

  • Como esse foi um problema real encontrado por meu colega de trabalho hoje, precisando ser escrito no Tcl 8.0.5 (uma versão antiga, sem muitos dos mais recentes recursos de Tcl), atribuirei 50 pontos a quem escrever o Tcl 8.0 mais curto .5 solução, se houver pelo menos 2 envios válidos no Tcl 8.0.5.
Andrew Cheong
fonte
@FezVrasta - escrevi intencionalmente ", "para incluir o espaço, mas podemos deixar sua edição e deixar esse comentário servir como indicação.
Andrew Cheong
Por que incluir intencionalmente o GolfScript? Por que não permitir outros idiomas, como o Befunge?
Justin
Podemos dizer que tudo é jogo justo. Apenas não poderei verificar a maioria deles com muita facilidade.
Andrew Cheong
Então isso é uma tag Code-Golf?
VisioN
1
@Chron - Boa captura. AB no meu caso, mas como já houve muitos envios, vamos permitir os dois lados.
Andrew Cheong

Respostas:

5

Ruby, 87-16 = 71

EDIT: Foi necessário adicionar alguns caracteres para que os intervalos de dois caracteres sejam exibidos corretamente. Também usando em ?[vez de ?Zpara corrigir um erro com intervalos que terminam em Z.

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

Você pode ver o Ideone sendo executado aqui .

Paul Prestidge
fonte
+1 Para uma linha. Uso muito inteligente de vários métodos; Isso é realmente brilhante.
Daniero
1
Observe que gsub(/[]/i)é menor que tr(''.upcase)2 caracteres. Além disso, scan(/.+/)-> splitsalva 5 e, em $><<vez de putsoutro.
Howard
@ Howard Ótimas sugestões, obrigado!
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"

Não é suportado pelo Ideone.com e provavelmente será esmagado de qualquer maneira.

gggg
fonte
1
Obrigado mesmo assim! A restrição do Ideone.com era apenas para que eu pudesse testá-lo, mas suponho que posso confiar na integridade dos golfistas e remover essa regra. +1 de qualquer maneira.
Andrew Cheong
2

C #, 221 bytes

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));
    }
}
Mão-E-Comida
fonte
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
fonte
Você pode adicionar uma pequena explicação?
1155 Justin justin
Itere sobre a sequência, acumulando uma contagem de instâncias de cada caractere alfanumérico. Em seguida, itere sobre todos os caracteres alfanuméricos em ordem alfabética, escrevendo o início de cada intervalo compacto e, se apropriado, um traço seguido pelo final do intervalo. Se esse não for o primeiro intervalo que foi gravado, adicione o separador de vírgula-espaço. O código deve ser incorporado em uma função main () com os cabeçalhos apropriados (stdio, string, ctypes) incluídos, então eu meio que trapacei lá.
warrenm
2

GolfScript 57 54 52

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

Experimente aqui .

O código coloca em maiúscula tudo:

{.95>32*-}%

Em seguida, obtém caracteres únicos e o salva em uma variável:

.|:x

Em seguida, obtemos os caracteres cujos predecessores diretos não estão na string (para que eles sejam a parte inicial de um intervalo):

..{)}%&-x

Da mesma forma, obtemos os fins dos intervalos com x..{)}%&-.

Agora, na verdade, forme os intervalos concatenando as listas, classificando e dividindo em grupos de 2:

+$2/

O resto é apenas formatação, usando *como junção de string.

Ben Reich
fonte
1
Na saída, os intervalos precisam ser separados por ',' e não apenas ','
Paul Prestidge
1
Também .95>{32-}{}if-> .95>32*-salva 5 caracteres.
1111 Howard
@Howard Great! Eu sabia que essa parte era subótima.
Ben Reich
1
@Chron Corrigido o problema de espaço!
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]}
tmartin
fonte
1

Python 2.x, 304 - 16 = 288

Isso certamente pode ser ainda mais jogado, todos os comentários são bem-vindos!

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
fonte
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

Versão não minificada:

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
fonte
1

q [116 caracteres]

{.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}

Uso

{.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"
Resultado
"0-3,A-C,J,P-T,Z"

Existe um escopo de salvar caracteres, vou tentar outro método e publicá-lo.

Nyi
fonte
0

Tcl 8.0.5, 344 (360 bytes)

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

Mexer com o renamecomando rendeu alguns truques divertidos! Eu os documentei em outro segmento .

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 bytes) [Instável - depende de $ 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

Os nossos agradecimentos a @JohannesKuhn pelo truque interativo .

Andrew Cheong
fonte
1
Às vezes, você pode salvar bytes substituindo whilepor timeconstruções. codegolf.stackexchange.com/a/126236/29325
sergiol #