Encurtar o texto com a codificação de comprimento de execução

8

Encurte (ou não) o texto usando a codificação de duração da execução

Entrada:

heeeello
woooorld

Resultado:

1h4e2l1o
1w4o1r1l1d
  • Leia as linhas de stdin.
  • Imprimir para stdout.
  • Stderr é naturalmente descartado.
  • Suponha que haja casos de teste ocultos (sem incorporação da saída)
  • Entrada / Saída como ASCII
  • Qualquer idioma é aceito
mroman
fonte
3
Você pode (normalmente) economizar um pouco se ignorar todos, por exemplo, em w4orldvez de 1w4o1r1l1d(você precisaria escapar de números, por exemplo, `f111 -> f3 \ 1 '). Mas então seria um quase duplicado deste: codegolf.stackexchange.com/questions/6774
primo
1
Como está, é perto o suficiente da codificação de comprimento de execução que eu voto para fechar como burro. Não vai oferecer nenhum novo desafio ou ponto de interesse.
Peter Taylor
Pontos de bônus para quem conseguir encontrar um ponto fixo.
FUZxxl 15/09/12
4
@FUZxxl, 22é um ponto de correção trivial.
Peter Taylor
2
@ PeterTaylor E o único não vazio. Sabemos que deve começar com um dígito. 11é impossível. 22deve terminar aí ou ser seguido por outro ponto fixo que não comece com 2. 333nnné um padrão impossível, pois você nunca encontrará o mesmo caractere em índices ímpares consecutivos. 4444e até falham pelo mesmo motivo.
Khuldraeseth na'Barya 5/08/19

Respostas:

2

Perl: 46. → 36 ou 27 caracteres

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

Todos saudam o @ardnew por ter a ideia de usar o tr///coperador para contar o número de caracteres na sequência correspondente em vez de dividir:

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

Degolfado:

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

ou via STDIN

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

impressões

1h4e2l1o
amon
fonte
Você está mudando rapidamente sua contagem de caracteres - conto 37 caracteres, incluindo 1 para a popção.
Gareth
Você pode economizar 10 caracteres usando s|((.)\2*)|$1=~y///c.$2|eg, que resume a 27 caracteres totais (usando as mesmas regras de contagem de caracteres como @Gareth)
ardnew
1
Pode reduzir ainda mais para 25 bytes (inclusive -p), eliminando os parâmetros externos: Experimente online!
Xcali 5/08/19
2

Stax , 7 bytes

ûèB☼å°╤

Execute e depure st staxlang.xyz!

Descompactado (8 bytes) e explicação:

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 apenas em uma única linha:

∩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

Execute e depure-o em staxlang.xyz!

Talvez não seja legal. Este programa imprime cada par em uma linha própria. Um pouco superficial.

Se esse formato de saída for ilegal, eu lhe dou 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

Execute e depure-o em staxlang.xyz!

Criador da linguagem recursiva assinala que uncons-direita ( N) pode encurtar isso para seis bytes descompactados, como ele lida com a Ee ]por conta própria. Programas tão curtos, no entanto, geralmente não ficam mais curtos quando embalados, e este é um exemplo. Ainda seis bytes: |RFNppEditar: tive que atualizar minha resposta principal; esse formulário é o que eu usei.

Khuldraeseth na'Barya
fonte
1
Bem feito. |RFNpppode dar a saída especificada em 6 bytes descompactada, mas infelizmente não compacta.
recursivo
1
@KevinCruijssen Yep. Ops.
Khuldraeseth na'Barya 7/08/19
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
fonte
Usando regras modernas do site e uma função, [:,(#,&":{.)/.~para 15: Experimente on-line!
Jonah
1

Braquilog , 11 bytes

ḅ⟨{lṫ}ch⟩ᵐc

Experimente online!

(Se a saída realmente precisar estar em stdout, adicione um byte wno 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.
String não relacionada
fonte
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)

Experimente online!

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

Experimente online!

A abordagem iterativa parece bastante bem-sucedida, enquanto a versão recursiva tem muito espaço para melhorias.

movatica
fonte
Boa abordagem! Parece que o whileloop no seu código está lá apenas para demonstrar a entrada. Sem ele, seu código ainda é válido. Nesse caso, o loop não precisa fazer parte do código e você pode reduzir o primeiro exemplo para 85 bytes da seguinte forma: Experimente online!
Jitse
Seu segundo exemplo pode ser reduzido para 121 bytes assim: Experimente online!
Jitse 7/08/19
Sim, o loop while é apenas para entrada em linha. Mas a pergunta requer a leitura de todas as linhas, não apenas uma, de modo que externalizar o loop seria contrário às regras.
movatica 7/08/19
1

05AB1E , 9 bytes

|εÅγs.ιJ,

Experimente online.

Ou alternativamente:

|εÅγøí˜J,

Experimente online.

Explicação:

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

Wolfram Language (Mathematica) , 98 bytes

Print[""<>StringCases[#,s:x_..:>ToString@StringLength@s<>x]]&/@StringSplit[$ScriptInputString,"
"]

Experimente online!

Um formato de E / S mais flexível reduz essa solução para 54 bytes :

""<>StringCases[#,s:x_..:>ToString@StringLength@s<>x]&

Experimente online!

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

Exemplo de execução:

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
homem a trabalhar
fonte
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

Execute-o assim:

zsh script.zsh < infile

De-golfe

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
fonte
Esses espaços em branco são necessários ou você pode reduzir `if ['para' if ['etc?
mroman 14/09/12
A [[construção é um comando por si só (como [) e deve ser separada de outros comandos. Quanto ao uso [excessivo [[, é necessário que os argumentos sejam citados para que quatro "sejam adicionados.
Thor
0

APL (24)

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

Burlesco (17B)

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

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

Mais antigas / alternativas e versões mais longas:

{= [{^^ 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
fonte
0

Retina , 12 bytes

(.)\1*
$.0$1

Experimente online.

Explicação:

Faça parte de 1 ou mais do mesmo personagem, capturando o personagem no grupo de captura 1.

(.)\1*

Substitua-o pelo comprimento da correspondência total, concaturado com o personagem do grupo de captura 1:

$.0$1
Kevin Cruijssen
fonte
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())

Experimente online!

Explicação

Verifica se o primeiro e o segundo caracteres da sequência são iguais. Se estiverem, aumente o contador em 1. Se não estiverem, imprima o contador e o primeiro item e redefina o contador para 1. Nos dois casos, a função é chamada recursivamente com o primeiro caractere removido.

Gera um erro quando o final da string é atingido.


Sem restrições de E / S, mas com contagem mínima de bytes:

Python 3.8 (pré-lançamento) , 70 bytes

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

Experimente online!

Equivalente ao Python 3 (77 bytes)

Explicação

Retira todos os caracteres repetidos do início da sequência. Em seguida, ele retorna uma string contendo (1.) a diferença de comprimentos entre a string original e a stripped; (2) o primeiro caractere da string original; (3.) o resultado da função recursiva aplicada à string removida. A recursão termina quando uma string vazia é encontrada.

Jitse
fonte
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})

Experimente online!

Aqui o Lambda puro retirou o golfe (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
  }
alface cúbica
fonte
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=("",""))

Experimente online!

Simeon Schaub
fonte
Aqui estão 80 bytes . Eu acho que pode ir mais curto embora
H.PWiz
Infelizmente, seu código não funcionou na Julia 1.1 para mim. Eu ainda conseguiu 81 adicionando um extra '\n' para readline()em vez de imprimir a última tupla manualmente
Simeon Schaub
0

CJam , 2 bytes

e`

e`é um built-in para codificação de execução. A saída implícita do CJam ignora os colchetes da matriz e se transforma [[1 'h] [2 'e]]em"1h2e"

Experimente online!

lolad
fonte
0

Zsh, 70 bytes

experimente online!

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

Esta é uma versão muito mais eficiente da resposta zsh anterior ( link tio ). Provavelmente poderia ser jogado mais usando string => conversão de matriz em vez de iteração.

roblogic
fonte