Expandir una cadena codificada

18

Existe la codificación y decodificación de longitud de ejecución clásica.

input   output
a3b2c5  aaabbccccc

Y eso es bastante sencillo y hecho antes.

El desafío es también tener en cuenta un comportamiento no estándar cuando varios caracteres preceden a la longitud de la ejecución (un solo dígito de 0-9). Cada carácter antes del dígito de longitud de ejecución (el último dígito antes de un no dígito o final de la cadena) tiene ese valor aplicado individualmente e impreso en orden.

Algunas pruebas de entrada y salida, incluidos algunos casos extremos:

input   output
ab3c5   aaabbbccccc
a0b3    bbb  
13b1    111b
a13b1   aaa111b
a123b1  aaa111222b
aa2a1b1 aaaaab
  • Una secuencia de caracteres ( [a-zA-Z0-9]+) debe ser seguida por su longitud de ejecución length ( [0-9])
  • Solo se debe considerar la entrada válida ( ([a-zA-Z0-9]+[0-9])*)
    • Sí, la cadena vacía es una entrada válida.
  • La entrada es a través de la entrada estándar, la salida a través de la salida estándar

Este es el código de golf, el número de bytes determina el ganador.


fuente
@AlexA. Correcto. Hay algunos esolangs que disfruto ver de vez en cuando que de otra manera están penalizados por el conteo de bytes. (Ciertamente estoy abierto a sugerencias sobre por qué esto puede ser un error contar de esa manera)
44
@MichaelT La puntuación por caracteres recomienda encarecidamente comprimir el código fuente en UTF32, lo que permite la codificación de hasta 4 bytes por carácter, pero es completamente ilegible.
isaacg
@isaacg feria 'nuff. Lo editaré para cambiar a bytes. Pensaré en una forma de expresar el estilo de sclipting para que sea aceptable para futuros desafíos.
¿Se supone que nuestro envío se complete sin error si la entrada es la cadena vacía? El consenso sobre meta es que la salida a STDERR se puede ignorar, pero como lo mencionaste explícitamente, tengo que preguntar.
Dennis
@Dennis una cadena vacía como la entrada debería, debería detenerse. No debe entrar en un bucle infinito o imprimir otro texto a la salida estándar.

Respuestas:

3

Pip, 22 + 1 = 23 bytes

Usa -rbandera. Tenga en cuenta que esto requiere que 1) ingrese un EOF después de la entrada (Ctrl-D en Linux, Ctrl-Z en Windows) o 2) canalice la entrada desde otro lugar.

(^_@<v)X_@vMa@`\D*\d+`

Explicación:

                        a is first line of stdin (from -r flag) and v is -1 (implicit)
              `\D*\d+`  Pattern (regex) object that matches zero or more non-digits
                        followed by at least one digit
            a@          Find all non-overlapping matches in a, returning a list of strings
           M            To that list, map a lambda function:
  _@<v                    Argument sans last character (equivalent to Python a[:-1])
(^    )                   Split into a list of characters
        _@v               Last character of argument
       X                  Repeat each character of the list that many times
                          (String multiplication X, like most operators, works item-wise
                          on lists)
                        Auto-print (implicit)

El resultado de la operación de mapeo es en realidad una lista de listas, pero por defecto las listas simplemente se concatenan juntas cuando se imprimen, por lo que no es necesaria la conversión manual a cadena.

Ejemplo, con entrada a13b1:

Var a gets        "a13b1"
After regex match  ["a13" "b1"]
After map          [["aaa" "111"] ["b"]]
Final output       aaa111b

Pip tiene soporte básico de expresiones regulares a partir de ... Hace 2 días . Gran momento!

DLosc
fuente
Ese funciona (y también lo hace master) con la -rbandera. (La pregunta especifica que la entrada tiene que venir de STDIN.)
Dennis
@ Dennis Oops, me perdí eso. Se agregó una bandera al conteo de bytes. Debería haber podido usar la variable especial en qlugar de asin banderas adicionales, pero parece haber un error y está pidiendo la entrada dos veces.
DLosc
¡Finalmente un lenguaje de golf con soporte para expresiones regulares!
Dennis
@ Dennis ¡Te veo cambiando a pip ahora!
Optimizador
8

Perl / Bash 54 40 + 1 = 41 bytes

perl -pe's:(\D*\d*)(\d):"\$1=~s/./\$&x$2/egr":ege'

Básicamente es una expresión regular dentro de una expresión regular. Y un poco de magia.

Explicación

La expresión regular externa /(\D*\d*)(\d)/gextrae cada grupo codificado de longitud de ejecución. Capturamos las cosas para repetir $1y la cantidad de repeticiones $2. Ahora sustituimos cada grupo con la expansión de ese grupo. Para eso, evaluamos el código "\$1=~s/./\$&x$2/egr" dos veces (como por la /eebandera en la sustitución externa).

La primera evaluación solo interpolará el número de repeticiones en la cadena; las otras variables están protegidas por una barra diagonal inversa. Asumiendo la entrada a14, ahora tendríamos el código$1=~s/./$&x4/egr , que será evaluado nuevamente.

Esto aplicará la sustitución al contenido de $1(las cosas para repetir a1). La sustitución coincide con cada personaje .. La $&variable contiene toda la coincidencia, que repetimos x4veces. Hacemos esto /globalmente para cada coincidencia y /rgrabamos la cadena sustituida en lugar de modificar la $1variable (que es de solo lectura). Entonces el resultado de la sustitución interna es aaaa1111.

El -pindicador aplica la sustitución a cada línea de entrada e imprime el resultado.

amon
fuente
3
Es habitual calificar esto como una solución Perl, donde solo agrega 1 byte para el -pmodificador. Cuento 45 bytes. Además, debería poder usar en \Dlugar de [a-z], lo que también eliminó la necesidad de hacerlo i.
Dennis
7

CJam, 33 31 27 bytes

Ughh, la falta de expresiones regulares hace que esto sea bastante largo ...

qN+{:XA,s&L\:L>{])~e*[}&X}%

Cómo funciona

Recorremos todos los caracteres de la cadena de entrada y, en cada iteración, hacemos un seguimiento del último carácter encontrado (comenzando con un carácter vacío por primera vez). Luego verificamos si el carácter actual no es numérico y el último carácter es numérico. Si es así, repetimos cada carácter anterior (que no se ha repetido ya), el número veces.

(Expansión de código un poco desactualizada)

q{                       }%        e# Read the input (q) and loop through each character
  L                                e# Put variable L (initially empty character) on stack
   A,                              e# Put variable A (equals 10) and create an array 0..9
     s                             e# Convert the array to string "0123456789"
      &                            e# Do a set intersect b/w previous char and 0-9 string
                                   e# If numeric, it gives 1 char string, otherwise 0
       \:LA,s&                     e# Swap to bring current character on top. Store it in L
                                   e# and do the same set intersect with it
              >                    e# Means we are checking that current char is non-numeric
                                   e# and previous numeric
               {      }&           e# Run this block if above is true
                ])~                e# Wrap everything not already repeated in an array and
                                   e# take out the last character and convert it to integer.
                                   e# This is the run length of the preceding string
                   e*              e# Repeat each character in the string, run length times
                     [             e# Start a new array to help when next run length is found
                        L          e# Restore the current character back on stack to be used
                                   e# in next iteration
                           )~e*    e# The last string-run-length pair is not decoded..
                                   e# So we do that now

Pruébalo en línea aquí

Optimizador
fuente
Agradezco la demostración del problema que causa el calificador de bytes. Gracias. Estoy pensando un poco en cómo formular la calificación de tal manera que los idiomas en los que una sola instrucción es un carácter de varios bytes no sean penalizados por ese estilo de lenguaje sin permitir que la codificación UTF que mostraste ingrese a través de lagunas. PD: Realmente me gusta ver el desglose algorítmico que proporcionas.
6

rs , 43 71 caracteres

Bueno, esto se volvió largo rápidamente. Estúpidos números ...

(\d)(\D)/\1 \2
+(\w)(\w+?)(\d)(?= |$)/\1\3 \2\3
(\w)(\d)/(\1)^^(\2)
 /

Pruébalo aquí!

Versión original (no funcionó con entrada como 123):

+(\D)(\D+)(\d)/\1\3\2\3
(\D)(\d)/(\1)^^(\2)

Explicación

La primera línea coloca espacios entre carreras que contienen números, por ejemplo, convirtiéndose a313ena3 13 .

La segunda línea se expande continuamente las codificaciones comprimidas como aa5paraa5a5 .

La tercera línea convierte cada instancia de a5en aaaaael uso de la operador de repetición .

La última línea elimina los espacios.

kirbyfan64sos
fuente
¿Cómo se maneja a123b1?
Optimizador
@Optimizer No está bien. Tengo que ajustar un poco ...
kirbyfan64sos
@Optimizer Fixed.
kirbyfan64sos
5

Javascript ( ES6 ), 86 83 bytes

alert(prompt().replace(/(.+?)(\d)(?!\d)/g,(a,b,c)=>b.replace(/./g,y=>y.repeat(c))))

Comentado:

alert( // output final result
    prompt(). // take input
    replace(/(.+?)(\d)(?!\d)/g, // replace ungreedy capture group of any characters 
                                // followed by a digit (captured)
                                // and not followed by a digit (negative lookahead)
        (a, b, c)=> // replace with a function
            b.replace(/./g, // replace all characters in b
                y=>y.repeat(c) // with that character repeated c times
            )
    )
)
nderscore
fuente
¿No alert(prompt().replace(/(.+?)(\d)(?!\d)/g,(a,b,c)=>Array(c+1).join(b)))harás lo mismo? Tiene solo 71 bytes de longitud.
Ismael Miguel
@IsmaelMiguel que solo funcionaría si hubiera un solo carácter antes del dígito. La comprensión de la matriz maneja la repetición de cada carácter individualmente.
nderscore
Intenta Array(6).join('12')y volverá '1212121212'.
Ismael Miguel
Éste funciona: alert(prompt().replace(/(.+?)(\d)(?!\d)/g,(a,b,c)=>Array(-~c).join(b)))(el mismo de 71 bytes de longitud, probado en es6fiddle.net/ia7gocwg )
Ismael Miguel
1
Sin embargo, encontré una forma diferente (obvia) de decir 3 bytes: D
nderscore
4

CJam, 27 25 bytes

r_'A+1>.{64&1$>{])~f*o}&}

Pruébelo en línea en el intérprete de CJam .

Cómo funciona

r_                        e# Read a token from STDIN and push a copy.
  'A+                     e# Append the character A to the copy.
     1>                   e# Discard the first character of the copy.
       .{               } e# For each character C of the input string and the
                          e# corresponding character D of the copy:
         64&              e#   Take the bitwise and of D and 64. This pushes @
                          e#   if D is a letter and NUL if it is a digit.
            1$>           e#   Compare the result to a copy of C. This pushes 1
                          e#   if and only if D is a letter and C is a digit.
               {      }&  e#   If the result was 1, do the following:
                ]         e#     Wrap the stack in an array.
                 )~       e#     Pop and evaluate the last character.
                   f*     e#     Repeat each char in the array that many times.
                     o    e#     Print all characters.
Dennis
fuente
3

Pyth, 33 32 28 bytes

ssmm*vedkPdPcz-hMJf<@zT\=UzJ

Pruébelo en línea: demostración o prueba de arnés

Explicación

Explicaré el código usando la entrada de ejemplo aa1a23b2. Esperemos que esto sea un poco más fácil de seguir que sin él.

                               implicit: z = input string = 'aa1a23b2'
                         Uz    the indices of z: [0, 1, 2, 4, 5, 6, 7]
                  f            filter for indices T, which satisfy:
                   <@zT\=        z[T] < "="
                               this gives us the list of indices [2, 4, 5, 7], 
                               which correspond to digits in z. 
                 J             assignment, J = [2, 4, 5, 7]
               hMJ             increment all element in J: [3, 5, 6, 8]
              -            J   and remove the elements of J:
                                 [3, 5, 6, 8] - [2, 4, 5, 7] = [3, 6, 8]
            cz                 split z at these indices: ['aa1', 'a23', 'b2', '']
           P                   remove last element: ['aa1', 'a23', 'b2']
  m                            map each string d to:
   m     Pd                      map each string k of d-without-last-char to:
     ved                           int(last element of d)
    *   k                          * k
                               this creates [['a', 'a'], ['aaa', '222'], ['bb']]
 s                             sum the lists: ['a', 'a', 'aaa', '222', 'bb']
s                              sum the strings: 'aaaaa222bb'
Jakube
fuente
2

JavaScript 112

alert(prompt().replace(/.*?\d+/g,function(m){for(i=n=m.length-1,o="";i--;){j=m[n];while(j--)o=m[i]+o}return o}))

martillo de lobo
fuente
2

Python 2.7, 98 bytes

import re
print"".join(c*int(m[-1])for m in 
re.findall(r".+?\d(?!\d)",raw_input())for c in m[:-1])

Esto solo hace una simple búsqueda de expresiones regulares para los dígitos que no son seguidos por un dígito, y luego realiza la aritmética de cadenas en cada grupo y los une nuevamente.

recursivo
fuente
Puede guardar 2 bytes cambiando de Python 2 a 3. se raw_inputconvierte en paréntesis inputpero printnecesita.
Alex A.
Es cierto, pero prefiero jugar al golf en Python 2.7.
recursivo
1

Julia, 105 99 95 87 bytes

s->join([join([string(b)^(int(p[end])-48)for b=chop(p)])for p=matchall(r"\D*\d*\d",s)])

Esto crea una función sin nombre que toma una cadena como entrada y devuelve una cadena. Para llamarlo, dale un nombre, por ejemplo f=s->....

Aquí se utilizan dos comprensiones de matrices, una anidada dentro de la otra. La comprensión externa actúa sobre cada coincidencia de la cadena de entrada contra la expresión regular.\D*\d*\d . La comprensión interna repite cada carácter del partido de acuerdo con el dígito final. Los elementos de la matriz interna se unen en una cadena, por lo que la matriz externa es una matriz de cadenas. Estos se unen y se devuelven.

En Julia, las cadenas se pueden tratar como matrices de caracteres. Sin embargo, tenga en cuenta que los tipos Chary Stringen Julia no tienen los mismos métodos definidos; en particular, no existe un método para repetir utilizando ^caracteres. Esto utiliza una solución complicada:

  • Pase sobre la cadena omitiendo el último carácter, que se elimina con chop() .
  • Convierte el carácter actual en una cadena usando string() .
  • Convierta el dígito final, que también es un carácter, en un entero. Sin embargo, tenga en cuenta que, por ejemplo, int('4')no devuelve 4. Más bien, devuelve el punto de código, que en este caso es 52. Por lo tanto, podemos restar 48 para recuperar el entero real.
  • Repita de string(b)acuerdo a int(p[end]) - 48.

Ejemplos:

julia> f("ab3c5")
"aaabbbccccc"

julia> f("a0b3")
"bbb"

julia> f("13b1")
"111b"
Alex A.
fuente
1

Pitón 3, 148 144 136 135 Bytes

w,o,r,d=''.join,'',[],[]
for c in input()+' ':
 if'/'<c<':':d+=[c]
 elif d:o+=w(x*int(w(d))for x in r);r=[c];d=[]
 else:r+=[c]
print(o)

Gracias a Pietu1998 y mbomb007 por las sugerencias.

Python 2, 161 151 147 139 138 Bytes

Tal vez hoy haya sido un largo día en el trabajo, pero no puedo por mi vida descubrir cómo jugar golf ...

w,o,r,d=''.join,'',[],[]
for c in raw_input()+' ':
 if'/'<c<':':d+=[c]
 elif d:o+=w(x*int(w(d))for x in r);r=[c];d=[]
 else:r+=[c]
print o
Kade
fuente
3
Cambiar a Python 3 guarda un par de bytes ( raw_fuera, paréntesis en print). len(d)>0puede ser reemplazado por dya que una lista vacía es falsa y una lista no vacía es verdadera. list(...)puede ir directamente a la for. Los corchetes no w([...])son necesarios ya que es el único argumento. Puedes eliminar el espacio en ) for. Esas son todas las cosas menores que se me ocurrieron hasta ahora.
PurkkaKoodari
@ Pietu1998 Gracias por la ayuda!
Kade
Sin cambiar demasiado su enfoque, puede deshacerse de él list()ya que las cadenas son iterables. Puedes usar w=r=''. Si estás dispuesto a cambiarlo mucho, mira mi solución. :)
recursivo
if c.isdigit()puede llegar a ser if'/'<c<':', si no me equivoco.
DLosc
@DLosc gracias, eso parece funcionar.
Kade
0

Java 7, 175 bytes

String c(String s){String r="",a[];for(String x:s.split("(?<=(\\d)(?!\\d))")){a=x.split("");for(int i=0,j,l=a.length-1;i<l;i++)for(j=0;j++<new Short(a[l]);r+=a[i]);}return r;}

El desafío es más difícil de lo que parece, en verdad ...

Ungolfed y código de prueba:

Pruébalo aquí

class M{
  static String c(String s){
    String r = "",
           a[];
    for(String x : s.split("(?<=(\\d)(?!\\d))")){
      a = x.split("");
      for(int i = 0, j, l = a.length-1; i < l; i++){
        for(j = 0; j++ < new Short(a[l]); r += a[i]);
      }
    }
    return r;
  }

  public static void main(String[] a){
    System.out.println(c("ab3c5"));
    System.out.println(c("a0b3"));
    System.out.println(c("13b1"));
    System.out.println(c("a13b1"));
    System.out.println(c("a123b1"));
    System.out.println(c("aa2a1b1"));
    System.out.println(c("123"));
  }
}

Salida:

aaabbbccccc
bbb
111b
aaa111b
aaa111222b
aaaaab
111222
Kevin Cruijssen
fuente