Kürzen Sie Text mit Run Length Encoding

8

Kürzen Sie den Text mithilfe der Lauflängencodierung (oder nicht)

Eingang:

heeeello
woooorld

Ausgabe:

1h4e2l1o
1w4o1r1l1d
  • Lesen Sie die Zeilen von stdin.
  • Auf Standard drucken.
  • Stderr wird natürlich verworfen.
  • Angenommen, es gibt versteckte Testfälle (keine Einbettung der Ausgabe)
  • Eingabe / Ausgabe als ASCII
  • Jede Sprache wird akzeptiert
mroman
quelle
3
Sie können (normalerweise) einiges sparen, wenn Sie alle ignorieren, z. B. w4orldanstelle von 1w4o1r1l1d(Sie müssten sich den Zahlen entziehen, z. B. `f111 -> f3 \ 1´). Aber dann wäre es fast
primo
1
Da es nahe genug an der Run-Length-Codierung liegt , stimme ich dafür, dass es als Dupe geschlossen wird. Es wird keine neuen Herausforderungen oder Punkte von Interesse bieten.
Peter Taylor
Bonuspunkte für jeden, der es schafft, einen Fixpunkt zu finden.
FUZxxl
4
@FUZxxl 22ist ein trivialer Fixpunkt.
Peter Taylor
2
@ PeterTaylor Und der einzige nicht leere. Wir wissen, dass es mit einer Ziffer beginnen muss. 11ist unmöglich. 22muss dort enden oder von einem anderen Fixpunkt gefolgt werden, der nicht mit beginnt 2. 333nnnist ein unmögliches Muster, denn Sie werden niemals das gleiche Zeichen an aufeinanderfolgenden ungeraden Indizes finden. 4444und bis scheitern aus dem gleichen Grund.
Khuldraeseth na'Barya

Antworten:

2

Perl: 46 → 36 oder 27 Zeichen

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

Alle begrüßen @ardnew für die Idee, mit dem tr///cOperator die Anzahl der Zeichen in der übereinstimmenden Zeichenfolge zu zählen, anstatt sie zu teilen:

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
}

Verwendungszweck:

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

oder über STDIN

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

druckt

1h4e2l1o
amon
quelle
Sie ändern Ihre Zeichenanzahl kurz - ich zähle 37 Zeichen, darunter 1 für die pOption.
Gareth
Sie können 10 Zeichen speichern, indem Sie verwenden s|((.)\2*)|$1=~y///c.$2|eg, was 27 Zeichen insgesamt ergibt (unter Verwendung der gleichen Zeichenzählregeln wie @Gareth)
ardnew
1
Kann -pdurch Eliminieren der äußeren Parens noch weiter auf 25 Bytes (einschließlich ) verkürzt werden : Probieren Sie es online aus!
Xcali
2

Stax , 7 Bytes

ûèB☼å°╤

Führen Sie es aus und debuggen Sie es st staxlang.xyz!

Entpackt (8 Bytes) und Erklärung:

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, funktioniert nur in einer einzelnen Zeile:

∩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

Führen Sie es aus und debuggen Sie es unter staxlang.xyz!

Vielleicht nicht legal. Dieses Programm druckt jedes Paar in einer eigenen Zeile. Ein bisschen lückenhaft.

Wenn dieses Ausgabeformat unzulässig ist, gebe ich Ihnen 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

Führen Sie es aus und debuggen Sie es unter staxlang.xyz!

Der rekursive Ersteller der Sprache weist darauf hin, dass uncons-right ( N) dies auf sechs entpackte Bytes verkürzen kann, da es das Eund das ]alleine handhabt . Programme, die so kurz sind, werden jedoch beim Packen oft nicht kürzer, und dies ist ein Beispiel. Noch sechs Bytes: |RFNppBearbeiten: Musste meine Hauptantwort aktualisieren; Dieses Formular habe ich verwendet.

Khuldraeseth na'Barya
quelle
1
Schön gemacht. |RFNppkann die angegebene Ausgabe in 6 Bytes entpackt geben, packt aber leider nicht.
rekursiv
1
@ KevinCruijssen Ja. Hoppla.
Khuldraeseth na'Barya
1

J, 35 31 Zeichen

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

Verwendungszweck:

   ,(](":@#,{.);.1~1,2~:/\])1!:1[1
heeeello
1h4e2l1o
   ,(](":@#,{.);.1~1,2~:/\])1!:1[1
woooorld
1w4o1r1l1d
Gareth
quelle
Verwenden Sie moderne Site-Regeln und eine Funktion [:,(#,&":{.)/.~für 15: Probieren Sie es online aus!
Jonah
1

Brachylog , 11 Bytes

ḅ⟨{lṫ}ch⟩ᵐc

Probieren Sie es online aus!

(Wenn die Ausgabe wirklich auf stdout erfolgen muss, fügen Sie wam Ende ein Byte für hinzu .)

          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.
Nicht verwandte Zeichenfolge
quelle
1

Python 3 iterativ, 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)

Probieren Sie es online aus!

Python 3 rekursiv, 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()))

Probieren Sie es online aus!

Der iterative Ansatz scheint recht erfolgreich zu sein, während die rekursive Version viel Raum für Verbesserungen bietet.

movatica
quelle
Netter Ansatz! Es sieht so aus, als ob die whileSchleife in Ihrem Code nur dazu dient, die Eingabe zu demonstrieren. Ohne sie ist Ihr Code noch gültig. In diesem Fall muss die Schleife nicht Teil des Codes sein, und Sie können das erste Beispiel wie folgt auf 85 Byte reduzieren: Probieren Sie es online aus!
Jitse
Ihr zweites Beispiel kann wie folgt auf 121 Byte reduziert werden: Probieren Sie es online aus!
Jitse
Ja, die while-Schleife dient nur zur zeilenweisen Eingabe. Die Frage erfordert jedoch, dass alle Zeilen gelesen werden, nicht nur eine, sodass die Externalisierung der Schleife gegen die Regeln verstößt.
Movatica
1

05AB1E , 9 Bytes

|εÅγs.ιJ,

Probieren Sie es online aus.

Oder alternativ:

|εÅγøí˜J,

Probieren Sie es online aus.

Erläuterung:

|          # 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
quelle
0

Bash: 104 Zeichen

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

Probelauf:

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
Mann bei der Arbeit
quelle
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

Führen Sie es so aus:

zsh script.zsh < infile

De-Golf gespielt

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
quelle
Sind diese Leerzeichen notwendig oder können Sie "if [" auf "if [" usw. kürzen?
Frau
Das [[Konstrukt ist ein eigenständiger Befehl (wie [) und muss von anderen Befehlen getrennt werden. Für die Verwendung von [over [[müssen die Argumente in Anführungszeichen gesetzt werden, sodass vier "hinzugefügt werden müssen.
Thor
0

APL (24)

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

Burlesque (17B)

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

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

Ältere / alternative und längere Versionen:

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

Netzhaut , 12 Bytes

(.)\1*
$.0$1

Probieren Sie es online aus.

Erläuterung:

Holen Sie sich einen Teil von 1 oder mehr desselben Charakters und erfassen Sie den Charakter in Erfassungsgruppe 1.

(.)\1*

Ersetzen Sie es durch die Länge der gesamten Übereinstimmung, die mit dem Charakter aus der Erfassungsgruppe 1 verknüpft ist:

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

Probieren Sie es online aus!

Erläuterung

Überprüft, ob das erste und das zweite Zeichen der Zeichenfolge gleich sind. Wenn dies der Fall ist, erhöhen Sie den Zähler um 1. Wenn dies nicht der Fall ist, drucken Sie den Zähler und das erste Element und setzen Sie den Zähler auf 1 zurück. In beiden Fällen wird die Funktion rekursiv aufgerufen, wobei das erste Zeichen entfernt wird.

Löst einen Fehler aus, wenn das Ende der Zeichenfolge erreicht ist.


Ohne E / A-Einschränkungen, aber mit minimaler Byteanzahl:

Python 3.8 (Vorabversion) , 70 Bytes

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

Probieren Sie es online aus!

Python 3-Äquivalent (77 Bytes)

Erläuterung

Entfernt alle sich wiederholenden Zeichen vom Anfang der Zeichenfolge. Dann wird eine Zeichenfolge zurückgegeben, die (1.) den Längenunterschied zwischen der ursprünglichen Zeichenfolge und der abisolierten Zeichenfolge enthält. (2.) das erste Zeichen der ursprünglichen Zeichenfolge; (3.) das Ergebnis der rekursiven Funktion, die auf die gestrippte Zeichenfolge angewendet wird. Die Rekursion endet, wenn eine leere Zeichenfolge gefunden wird.

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

Probieren Sie es online aus!

Hier de-golfed der reine Lambda (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
  }
kubischer Salat
quelle
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=("",""))

Probieren Sie es online aus!

Simeon Schaub
quelle
Hier sind 80 Bytes . Ich denke, es kann kürzer werden
H.PWiz
Leider hat Ihr Code bei Julia 1.1 für mich nicht funktioniert. Ich habe es immer noch geschafft, 81 zu bekommen, indem ich ein Extra hinzugefügt habe '\n' , readline()anstatt das letzte Tupel manuell zu drucken
Simeon Schaub
0

CJam , 2 Bytes

e`

e`ist eine integrierte Funktion für die Lauflängencodierung. Die implizite Ausgabe von CJam ignoriert Array-Klammern und wird so [[1 'h] [2 'e]]zu"1h2e"

Probieren Sie es online aus!

lolad
quelle
0

Zsh, 70 Bytes

Probieren Sie es online aus!

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

Dies ist eine viel Golfversion der früheren zsh-Antwort ( tio link ). Könnte wahrscheinlich mehr mit string => Array-Konvertierung anstelle von Iteration gespielt werden.

Roblogik
quelle