Cadena de caracteres alfanuméricos en una lista ordenada de rangos separados por comas

12

Dada una cadena de caracteres alfanuméricos sin clasificar, p . Ej.

ABC321STPpJqZZr0

genera una lista de rangos de caracteres separados por ",", ordenados por valor ASCII, ignorando mayúsculas y minúsculas ( es decir, generando solo caracteres en mayúscula y numéricos), p . ej.

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

Reglas

  • La duración de su programa es su puntaje base, como de costumbre.
  • Debe inicializar (hardcode) del ejemplo anterior dentro de su programa, pero puede descontar la longitud de ese ejemplo de su duración del programa, por ejemplo, para char* s="ABC321STPpJqZZr0";que pueda descontar 16 caracteres, los otros 11 caracteres contando hacia su duración del programa.

Bonificación (+50 recompensa)

  • Como este fue un problema real encontrado por mi compañero de trabajo hoy, que necesitaba ser escrito en Tcl 8.0.5 (una versión antigua, que carece de muchas de las últimas incorporaciones de Tcl), otorgaré 50 puntos a quien escriba el Tcl 8.0 más corto .5 solución, si hay al menos 2 envíos válidos en Tcl 8.0.5.
Andrew Cheong
fuente
@FezVrasta: escribí intencionalmente ", "para incluir el espacio, pero podemos dejar su edición y dejar que este comentario sirva como indicación.
Andrew Cheong
¿Por qué incluir intencionalmente GolfScript? ¿Por qué no permitir otros idiomas, como Befunge?
Justin
Podemos decir que todo es juego limpio. Simplemente no podré comprobar la mayoría de ellos muy fácilmente.
Andrew Cheong
Entonces, ¿es eso una etiqueta de Code-Golf?
VisioN
1
@Chron - Buena captura. AB en mi caso, pero dado que ya ha habido muchas presentaciones, permitamos ambas formas.
Andrew Cheong

Respuestas:

5

Rubí, 87-16 = 71

EDITAR: Tuve que agregar algunos caracteres para que los rangos de dos caracteres se muestren correctamente. También se usa en ?[lugar de ?Zcorregir un error con rangos que terminan en Z.

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

Puedes ver el Ideone correr aquí .

Paul Prestidge
fuente
+1 Para una línea. Uso muy inteligente de varios métodos; Esto es realmente genial.
daniero
1
Tenga en cuenta que gsub(/[]/i)es más corto que tr(''.upcase)por 2 caracteres. Además, scan(/.+/)-> splitguarda 5, y en $><<lugar de putsotro.
Howard
@Howard ¡Grandes sugerencias, gracias!
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"

No es compatible con Ideone.com, y probablemente será aplastado de todos modos.

gggg
fuente
1
¡Gracias de cualquier manera! La restricción de Ideone.com era solo para poder probarla, pero supongo que puedo confiar en la integridad de los golfistas y eliminar esa regla. +1, de todos modos.
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));
    }
}
Hand-E-Food
fuente
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
fuente
¿Puedes agregar una pequeña explicación?
Justin
Iterar sobre la cadena, acumulando un recuento de instancias de cada carácter alfanumérico. Luego, repita todos los caracteres alfanuméricos en orden alfabético, escribiendo el inicio de cada rango compacto y, si corresponde, un guión seguido del final del rango. Si este no es el primer rango que se ha escrito, agregue el separador de espacio de coma. El código debe estar incrustado en una función main () con encabezados apropiados (stdio, string, ctypes) incluidos, por lo que hice trampa allí.
warrenm
2

GolfScript 57 54 52

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

Pruébalo aquí .

El código primero capitaliza todo:

{.95>32*-}%

Luego obtiene caracteres únicos y los guarda en una variable:

.|:x

Luego, obtenemos los caracteres cuyos predecesores directos no están en la cadena (por lo que son la parte inicial de un rango):

..{)}%&-x

De manera similar, obtenemos los extremos de los rangos con x..{)}%&-.

Ahora, en realidad, forme los rangos concatenando las listas, ordenando y dividiendo en grupos de 2:

+$2/

El resto es solo formatear, usar *como una unión de cadena.

Ben Reich
fuente
1
En la salida, los rangos deben estar separados por ',' y no solo ','
Paul Prestidge
1
Además .95>{32-}{}if-> .95>32*-guarda 5 caracteres.
Howard
@Howard Genial! Sabía que esa parte era subóptima.
Ben Reich
1
@Chron ¡Se corrigió el problema de espacio!
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
fuente
1

Python 2.x, 304 - 16 = 288

Esto seguramente se puede jugar aún más, ¡todos los comentarios son bienvenidos!

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

Versión no 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
fuente
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"
Salida
"0-3,A-C,J,P-T,Z"

Existe la posibilidad de guardar caracteres, probaré algún otro método y lo publicaré.

nyi
fuente
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)

¡Jugar con el renamecomando produjo algunos trucos divertidos! Los he documentado en otro hilo .

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) [Inestable — 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

Gracias a @JohannesKuhn por el truco interactivo .

Andrew Cheong
fuente
1
A veces puede guardar bytes reemplazando whilepor timeconstrucciones. codegolf.stackexchange.com/a/126236/29325
sergiol