Acortar texto con codificación de longitud de ejecución

8

Acortar (o no) el texto utilizando la codificación de longitud de ejecución

Entrada:

heeeello
woooorld

Salida:

1h4e2l1o
1w4o1r1l1d
  • Leer líneas de stdin.
  • Imprimir en stdout.
  • Stderr es, por supuesto, descartado.
  • Suponga que hay casos de prueba ocultos (sin incrustación de la salida)
  • Entrada / Salida como ASCII
  • Cualquier idioma es aceptado
mroman
fuente
3
Puede (normalmente) ahorrar un poco si ignora todos, por ejemplo, en w4orldlugar de 1w4o1r1l1d(necesitaría escapar de los números, por ejemplo, `f111 -> f3 \ 1´). Pero entonces sería casi un duplicado de esto: codegolf.stackexchange.com/questions/6774
primo
1
Ya que está lo suficientemente cerca de la codificación de longitud de ejecución que voto para cerrar como engañado. No va a proporcionar ningún nuevo desafío o puntos de interés.
Peter Taylor
Puntos de bonificación para quien logre encontrar un punto de fijación.
FUZxxl
44
@FUZxxl, 22es un punto de referencia trivial.
Peter Taylor
2
@PeterTaylor Y el único no vacío. Sabemos que debe comenzar con un dígito. 11es imposible. 22debe terminar allí o ser seguido por otro punto fijo que no comience por 2. 333nnnes un patrón imposible, ya que nunca encontrarás el mismo personaje en índices impares consecutivos. 4444y hasta fallan por la misma razón.
Khuldraeseth na'Barya

Respuestas:

2

Perl: 46 → 36 o 27 caracteres

perl -pe's|((.)\2*)|@x=split//,$1;@x.$x[0]|eg'

Todos saludan a @ardnew por tener la idea de usar el tr///coperador para contar el número de caracteres en la cadena coincidente en lugar de dividir:

perl -pe's|((.)\2*)|$1=~y///c.$2|eg'

Degolfed:

while(defined($_ = <>)) {
  $_ =~ s{((.)\2*)}           # match 1 or more consecutive identical non-newlines
         {
           ($1 =~ y///c )     # count the number of characters in $1
           .                  # and concatenate it
           $2                 # with the first matched character
         }eg;                 # execute substitution, match "global"
  print $_;                   # print the modified line
}

Uso:

$ perl -pe's|((.)\2*)|$1=~y///c.$2|eg' infile

o vía STDIN

$ perl -pe's|((.)\2*)|$1=~y///c.$2|eg'
heeeello

huellas dactilares

1h4e2l1o
amon
fuente
Te estás quedando corto en tu recuento de personajes: cuento 37 caracteres, incluido 1 para la popción.
Gareth
Puede guardar 10 caracteres mediante el uso s|((.)\2*)|$1=~y///c.$2|eg, que suma a 27 caracteres en total (utilizando las mismas reglas de recuento de caracteres como @Gareth)
ardnew
1
Puede acortar aún más a 25 bytes (incluidos -p) al eliminar los elementos externos: ¡ Pruébelo en línea!
Xcali
2

Stax , 7 bytes

ûèB☼å°╤

Ejecutar y depurarlo st staxlang.xyz!

Desempaquetado (8 bytes) y explicación:

m|RFNppz
m           For each line of input:
 |R           Run-length encode: "heeeello" -> [[104,1],[101,4],[108,2],[111,1]]
   F          For each pair:
    N           Uncons-left: [104,1] -> push [104]; push 1
     ppz        Pop and print. Pop and print. Push "".
              Implicit print (always an empty string) with a newline

5 bytes, funciona solo en una sola línea:

∩l↨me
|RmEp]    Unpacked
|R        Run-length encode: "heeeello" -> [[104,1],[101,4],[108,2],[111,1]]
  m       Map block over input:
   E        Explode array: [104,1] -> push 104, push 1
    p       Pop and print with no newline
     ]      Make a one-element list: 104 -> [104] (which is "h")
            Implicit print with newline

¡Ejecútelo y depúrelo en staxlang.xyz!

Quizás no sea legal. Este programa imprime cada par en una línea propia. Un poco vago.

Si ese formato de salida es ilegal, le doy 6 bytes :

╡δôZ→╬
|RFEp]p    Unpacked
  F        For each item in array, execute block:
      p      Pop and print with no newline
             No implicit print in for-each block, so no extra newlines

¡Ejecútelo y depúrelo en staxlang.xyz!

El creador recursivo del lenguaje señala que uncons-right ( N) puede acortar esto a seis bytes sin empaquetar, ya que maneja el Ey el ]solo. Sin embargo, los programas tan cortos a menudo no se acortan cuando se empaquetan, y este es un ejemplo. Todavía seis bytes: |RFNppEditar: Tuve que actualizar mi respuesta principal; este formulario es lo que usé.

Khuldraeseth na'Barya
fuente
1
Bien hecho. |RFNpppuede proporcionar la salida especificada en 6 bytes sin empaquetar, pero desafortunadamente no empaca.
recursivo el
1
@KevinCruijssen Sí. Whoops
Khuldraeseth na'Barya
1

J, 35 31 caracteres

,(](":@#,{.);.1~1,2~:/\])1!:1[1

Uso:

   ,(](":@#,{.);.1~1,2~:/\])1!:1[1
heeeello
1h4e2l1o
   ,(](":@#,{.);.1~1,2~:/\])1!:1[1
woooorld
1w4o1r1l1d
Gareth
fuente
Usando reglas modernas del sitio y una función, [:,(#,&":{.)/.~por 15: ¡ Pruébelo en línea!
Jonás
1

Brachylog , 11 bytes

ḅ⟨{lṫ}ch⟩ᵐc

Pruébalo en línea!

(Si la salida realmente tiene que estar en stdout, agregue un byte wal final).

          c    The output is the concatenation of
 ⟨    c ⟩ᵐ     the concatenated pairs of
  {lṫ}         length converted to a string
       h       and first element
ḅ        ᵐ     for every run in the input.
Cadena no relacionada
fuente
1

Python 3 iterativo, 115 99 97 bytes

while 1:
 a=b='';k=0
 for c in input():e=a!=c;b+=(str(k)+a)*e;k+=1-k*e;a=c
 print(b[1:]+str(k)+a)

Pruébalo en línea!

Python 3 recursivo, 136 130 129 bytes

f=lambda r,c,s,k=1:s and(c==s[0]and f(r,c,s[1:],k+1)or f(r+str(k)+c,s[0],s[1:]))or r[1:]+str(k)+c
while 1:print(f('','',input()))

Pruébalo en línea!

El enfoque iterativo parece bastante exitoso, mientras que la versión recursiva tiene mucho margen de mejora.

movatica
fuente
Buen enfoque! Parece que el whilebucle en su código solo está allí para demostrar la entrada. Sin él, su código sigue siendo válido. En ese caso, el bucle no necesita ser parte del código y puede reducir el primer ejemplo a 85 bytes de esta manera: ¡ Pruébelo en línea!
Jitse
Su segundo ejemplo se puede reducir a 121 bytes de esta manera: ¡ Pruébelo en línea!
Jitse
Sí, el ciclo while es solo para entrada en línea. Pero la pregunta requiere leer todas las líneas, no solo una, por lo que externalizar el ciclo sería contrario a las reglas.
movatica
1

05AB1E , 9 bytes

|εÅγs.ιJ,

Pruébalo en línea.

O alternativamente:

|εÅγøí˜J,

Pruébalo en línea.

Explicación:

|          # Read all lines of input as list
 ε         # For-each over the lines:
  Åγ       #  Run-length encode, pushing the list of characters and lengths separately
    s      #  Swap so the characters at at the top and lengths below it
         #  Interleave the two lists
       J   #  Join the list of characters and lengths together to a single string
        ,  #  And output it with trailing newline

|εÅγ       # Same as above
    ø      #  Zip/transpose; creating pairs of [character, length]
     í     #  Reverse each pair to [length, character]
      ˜    #  Deep flatten the pairs to a single list
       J,  #  Join them together to a single string, and output it with trailing newline
Kevin Cruijssen
fuente
0

Bash: 104 caracteres

while read s;do e=;while [[ $s ]];do c=${s:0:1};n=${s##+($c)};e+=$[${#s}-${#n}]$c;s=$n;done;echo $e;done

Ejecución de muestra:

bash-4.2$ while read s;do e=;while [[ $s ]];do c=${s:0:1};n=${s##+($c)};e+=$[${#s}-${#n}]$c;s=$n;done;echo $e;done <<END
heeeello
woooorld
END
1h4e2l1o
1w4o1r1l1d
hombre trabajando
fuente
0

Zsh, 117

while read s;do n=1;for i in {1..$#s};do if [[ $s[i] != $s[i+1] ]];then echo -n $n$s[i];n=0;fi;((n++));done;echo;done

Ejecútelo así:

zsh script.zsh < infile

De golf

while read s; do                      # while stdin has more
  n=1                                 # repeat counter
  for i in {1..$#s}; do               # for each character
    if [[ $s[i] != $s[i+1] ]]; then   # same as next one?
      echo -n $n$s[i]                 # print if no
      n=0
    fi
    ((n++))
  done
  echo                                # newline between words
done
Thor
fuente
¿Son necesarios esos espacios en blanco o puede acortar 'if [' a 'if [' etc.?
mroman
La [[construcción es un comando en sí mismo (como [) y debe separarse de otros comandos. En cuanto a usar [over [[, requiere que se citen los argumentos, por lo "que deben agregarse cuatro .
Thor
0

APL (24)

,↑{(⍕⍴⍵),⊃⍵}¨B⊂⍨B≠¯1⌽B←⍞
marinus
fuente
0

Burlesco (17B)

{=[{J[-jL[Q}\m}WL

{=[{^^[~\/L[Sh}\m}WL

Versiones anteriores / alternativas y más largas:

{= [{^^ L [Sh \ / -] Sh. +} M [\ [} WL
{= [{^^ L [Sh \ / -] [-. +} M [\ [} WL
{= [{^^ L [Sh \ / - ~. +} M [\ [} WL
{= [{^^ L [Sh \ / -]. +} \ M} WL
{= [{^^ L [Sh \ / [~. +} \ M} WL
{= [{^^ L [Sh \ / [~ _ +} \ m} WL
{= [{^^ L [Sh \ / fc. +} \ M} WL
{= [{^^ L [Sh \ / - ~. +} \ M} WL
{= [{^^ L [Sh \ / -] \ /} \ m} WL
mroman
fuente
0

Retina , 12 bytes

(.)\1*
$.0$1

Pruébalo en línea.

Explicación:

Obtenga una parte de 1 o más del mismo personaje, capturando al personaje en el grupo de captura 1.

(.)\1*

Reemplácelo con la longitud de la coincidencia total, concatenada con el personaje del grupo de captura 1:

$.0$1
Kevin Cruijssen
fuente
0

Python 3 , 84 bytes

def f(s,c=1):i,*j=s;b=j[:1]==[i];print(end='%s%s'%(c,i)*(b^1));f(j,1+b*c)
f(input())

Pruébalo en línea!

Explicación

Comprueba si el primer y el segundo carácter de la cadena son iguales. Si lo están, aumente el contador en 1. Si no lo están, imprima el contador y el primer elemento y restablezca el contador a 1. En ambos casos, la función se llama de forma recursiva con el primer carácter eliminado.

Provoca un error cuando se alcanza el final de la cadena.


Sin restricciones de E / S, pero con un recuento mínimo de bytes:

Python 3.8 (prelanzamiento) , 70 bytes

f=lambda s:'%s%s'%(len(s)-len(t:=s.lstrip(p:=s[0])),p)+f(t)if s else''

Pruébalo en línea!

Python 3 equivalente (77 bytes)

Explicación

Elimina todos los caracteres repetidos del inicio de la cadena. Luego devuelve una cadena que contiene (1.) la diferencia en longitudes entre la cadena original y la cadena despojada; (2.) el primer carácter de la cadena original; (3.) el resultado de la función recursiva aplicada a la cadena despojada. La recursión termina cuando se encuentra una cadena vacía.

Jitse
fuente
0

[Scala (shell)], 150 bytes

scala.io.Source.stdin.getLines.foreach(s=>println{val(x,y,z)=s.tail.foldLeft(("",s.head,1)){case((a,b,c),d)=>if(b==d)(a,b,c+1)else(a+c+b,d,1)};x+z+y})

Pruébalo en línea!

Aquí el Lambda puro se des-golf (103 bytes):

  s => {
    val (x,y,z) = s.tail.foldLeft(("", s.head, 1)) {
      case ((a, b, c), d) =>
        if (b == d)
          (a, b, c + 1)
        else
          (a + c + b, d, 1)
    }
    x+z+y
  }
lechuga cubica
fuente
0

Julia 1.1 , 94 84 81 bytes

foldl(((n,l),c)->(c==l||print(n,l);((c==l&&n)+1,c)),readline()*'\n',init=("",""))

Pruébalo en línea!

Simeon Schaub
fuente
Aquí hay 80 bytes . Sin embargo, creo que puede ir más corto
H.PWiz
Desafortunadamente, su código no funcionó en Julia 1.1 para mí. Todavía logré obtener 81 agregando un extra '\n' en readline()lugar de imprimir la última tupla manualmente
Simeon Schaub
0

CJam , 2 bytes

e`

e`es una función de codificación de longitud de ejecución. La salida implícita de CJam ignora los corchetes de la matriz, por lo que se convierte [[1 'h] [2 'e]]en"1h2e"

Pruébalo en línea!

lolad
fuente
0

Zsh, 70 bytes

Pruébalo en línea!

for ((n=1;i++<#w;n++))[[ $w[i] != $w[i+1] ]]&&printf $n$w[i]&&n=0
echo

Esta es una versión mucho más golfista de la respuesta zsh anterior ( enlace tio ). Probablemente podría jugar más golf usando string => conversión de matriz en lugar de iteración.

roblogic
fuente