Replicador de cadenas

15

En Vim, puede repetir un comando precediéndolo con un número, como 3ddes equivalente a dd dd dd. Bueno, este patrón repetitivo no está restringido a los comandos de Vim. La cadena también se puede replicar de esta manera.

Especificación:

Dada una cadena, que consta de solo dígitos, caracteres alfabéticos (mayúsculas y minúsculas) y espacios, con una nueva línea final opcional, como entrada, escriba un programa que haga el siguiente trabajo:

  • Cada "palabra" consta de dígitos y alfabetos. Si una letra va precedida de un número (puede haber más de un dígito en un número o el número es cero), repita esa letra para los tiempos dados. Por ejemplo:

    a2bc -> abbc
    3xx1yz -> xxxxyz
    10ab0c0d0e -> aaaaaaaaaab # No 'cde' because there's a zero
    2A2a2A2a -> AAaaAAaa
    
  • Las palabras están separadas por espacios. Hay un máximo de un espacio entre cada dos palabras adyacentes.

Fácil, verdad? Aquí están las cosas adicionales:

  • Si hay un número antes del espacio, repita la siguiente palabra para los tiempos dados. El número siempre se adjuntará al final de la palabra anterior o al comienzo de la cadena. Ejemplo:

    a2bc3 2d -> abbc dd dd dd
    3 3a -> aaa aaa aaa
    33a -> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    0 abcd0 efgh3 2x -> xx xx xx
    a3 0xc b -> a c c c b
    
  • Si se debe repetir una palabra vacía, no genere múltiples espacios seguidos. Aplastarlos:

    a3 0x2 b -> a b b   # NOT 'a    b b'
    

    En otras palabras, su programa nunca debería generar dos espacios juntos.

  • La entrada nunca está vacía, pero no es necesario que la salida no esté vacía:

    0 3x -> (empty)
    
  • La entrada y la salida se pueden tomar de cualquier manera preferida. También es aceptable una función que toma datos de argumentos y proporciona resultados a través de valores de retorno.

    Si es un programa, no debe salir con error (es decir, el valor de retorno es cero).

  • Los números siempre son decimales y nunca comienzan con un cero, a menos que el número en sí sea cero, en cuyo caso solo hay un cero. Es decir, no necesita considerar 077ao 000adar como entrada.

  • Todos los números son menores a 2 ^ 31 (2,147,483,648). La longitud máxima de salida es inferior a 2 ^ 32 (4,294,967,296) bytes.

  • El programa puede opcionalmente generar un espacio final y / o una nueva línea final. Esos espacios y líneas nuevas no afectan la validez de la salida. Incluso si la salida correcta debe estar vacía, se calificará una salida de un espacio seguido de una nueva línea.

En resumen, una entrada válida coincide con esta expresión regular:

([0-9]+ )?([0-9A-Za-z]*[A-Za-z])([0-9]* [0-9A-Za-z]*[A-Za-z])*( ?\n?)

Y para una salida válida:

([A-Za-z]+)( [A-Za-z]+)*( ?\n?)

Ejemplos de casos de prueba:

abcdefg -> abcdefg
a3bcd -> abbbcd
a3bbbc -> abbbbbc
3a0b -> aaa
abc 3d -> abc ddd
abc3 d -> abc d d d
5 1x5 1y0 z -> x x x x x y y y y y
a999 0x b -> a b
999 0s -> (empty)
0 999s -> (empty)
0 999s4 t -> t t t t
a3 0xc b -> a c c c b
ABC3 abc -> ABC abc abc abc

Este es un , por lo que gana el programa más corto en bytes en cada idioma.

iBug
fuente
3
.... "el programa no debe salir con error" "la entrada no debe darse como una lista de caracteres ..." ¿alguna razón en particular? (como ya sabías) generalmente permitimos un formato de E / S flexible.
user202729
@ user202729 Estoy considerando eliminar este último. Para el resultado de salida del programa, quiero conservarlo. Editar : Listo.
iBug
1
Similares .
cole
1
También similar
danieltakeshi
Creo que se debe agregar una prueba como a3 0xc b-> a c c c b, ya que originalmente tenía un código que funcionó para todos los casos de prueba anteriores, pero no funcionó correctamente para eso.
Brad Gilbert b2gills

Respuestas:

3

JavaScript (Node.js) , 102 129 110 106 bytes

s=>s[p="replace"](/(\d+)( \w*[A-Z])/gi,g=(_,a,b)=>b.repeat(a))[p](/(\d+)(.)/g,g)[p](/ +/g,(_,i)=>i?" ":"")

Pruébalo en línea!

Gracias por @Arnauld por -4 bytes.

Shieru Asakoto
fuente
2

Perl 6, 88 bytes

{$_=$^a;s:g/(\d+):(\w)/{$1 x$0||'_'}/;s:g/(\d+)\s([\w& \D]+)/ {$1 xx$0}/;~S:g/_//.words}

Pruébalo

Expandido:

{ # bare block lambda with placeholder parameter 「$a」

  # store a copy of the argument in 「$_」
  # (shorter than 「-> $_ is copy {…}」)
  $_ = $^a;
  # note that 「$_」 is the default scalar,
  # and many things operate on it by default (like 「s///」)


  # do the character repeats
  s :global
  /

    (\d+)           # repeat count
    :               # don't backtrack (prevents it from matching word repeats)
    (\w)            # character to repeat

  /{

    $1 x $0         # do the repeat

    || '_'          # replace with 「_」 if the repeat was 0 (matched by [\w & \D])
                    # this is so “words” don't get removed yet

  }/;


  # do the word repeats
  s :global
  /

    (\d+)           # repeat count

    \s              # shortest way to match a space

    ([
      \w & \D       # word character and not a digit (doesn't match next repeat)
    ]+)             # match that at least once

  / {               # add a space (as we removed it by matching it)

    $1 xx $0        # list repeat (adds a space between values when stringified)

  }/;


  # the following is the result
  ~                 # stringify (adds spaces between values in a list) # (3)
    S :global /_//  # remove all _ not in-place                        # (1)
    .words          # get a list of words                              # (2)
}

La ~(…).wordscombinación elimina espacios extraños, lo cual es útil si se elimina una "palabra".

Brad Gilbert b2gills
fuente
1

Python 2, 286 275 260 257 238 bytes

-19 bytes gracias a los ovs

def f(s,j=' '.join):exec"s=s.split(%s[-1]):s[i]=s[i][:-1];s[i-1]=j([s[i-1]]*int(w[-1]))\ns=list(j(s[::-1])%s):s[i]='';s[i-1]*=int(w)\nprint j(''.join(s[::-1]).strip().split())"%((')[::-1]\nfor i,w in enumerate(s):\n if str.isdigit(w',)*2)

f toma una cadena como argumento e imprime la cadena formateada.

Aquí hay una respuesta con los casos de prueba.

Código sin golf:

def f(s, j=' '.join):
    s = s.split()[::-1]
    for i, w in enumerate(s):
        if str.isdigit(w[-1]):
            s[i] = s[i][:-1]
            s[i - 1] = j([s[i - 1]] * int(w[-1]))
    s = list(j(s[::-1]))[::-1]
    for i, w in enumerate(s):
        if str.isdigit(w):
            s[i] = ''
            s[i - 1] *= int(w)
    print j(''.join(s[::-1]).strip().split())

Todavía estoy trabajando en mejoras.

nog642
fuente
238 bytes
ovs
@ovs Gracias. No puedo creer que no haya pensado en deshacerme de la nueva línea y la sangría de la exec, ya que es la única línea en la función.
nog642
0

Limpio , 443 ... 306 bytes

import StdEnv,StdLib
^ =last
$n|n>"9"=1=toInt n
?v c| ^v<c=init v=v
q=groupBy
f[a:t]|a<"a"=repeatn($a)(hd t)++f(tl t)|t>[]=[a:f t]=[a," "]
f e=e
@l#[h:t]=[[toString[c:if(c<'1')[]k]\\[c:k]<-q(\a b=max a b<'a')s]\\s<-q(\a b=min a b>' ')l|s>[' ']]
=flatten(map f[?h"a":[?u":"\\u<-t&v<-map^[h:t],_<-[1.. $v]]])

Pruébalo en línea!

Οurous
fuente
0

Lua , 113 bytes

a="(%d+)(%a)"g=a.gsub function r(c,s)return s:rep(c)end g(g(g(g(...,a,r),"(%d+)( %a*)",r)," +"," "),"%a.*",print)

Pruébalo en línea!

Jonathan S.
fuente