Erweitern Sie eine codierte Zeichenfolge

18

Es gibt die klassische Lauflängencodierung und -decodierung.

input   output
a3b2c5  aaabbccccc

Und das ist ziemlich einfach und schon mal gemacht.

Die Herausforderung besteht darin, auch ein nicht standardmäßiges Verhalten zu berücksichtigen, wenn mehrere Zeichen vor der Lauflänge stehen (eine einzelne Ziffer von 0 bis 9). Auf jedes Zeichen vor der Lauflängenziffer (die letzte Ziffer vor einer Nichtziffer oder dem Ende der Zeichenfolge) wird dieser Wert einzeln angewendet und der Reihe nach ausgedruckt.

Einige Testeingaben und -ausgaben, einschließlich einiger Randfälle:

input   output
ab3c5   aaabbbccccc
a0b3    bbb  
13b1    111b
a13b1   aaa111b
a123b1  aaa111222b
aa2a1b1 aaaaab
  • Einer Zeichenfolge ( [a-zA-Z0-9]+) muss die Lauflänge length ( [0-9]) folgen.
  • Es müssen nur gültige Eingaben berücksichtigt werden ( ([a-zA-Z0-9]+[0-9])*)
    • ja, leere Zeichenfolge ist gültige Eingabe.
  • Die Eingabe erfolgt über die Standardeingabe, die Ausgabe über die Standardausgabe

Dies ist Code Golf, die Anzahl der Bytes bestimmt den Gewinner.


quelle
@AlexA. Richtig. Es gibt einige Esolangs , die ich von Zeit zu Zeit gerne sehe und die ansonsten durch die Anzahl der Bytes bestraft werden. (Ich bin auf jeden Fall offen für Vorschläge, warum dies ein Fehler sein könnte, dies so zu zählen)
4
@MichaelT Bei der Bewertung nach Zeichen wird dringend empfohlen, den Quellcode in UTF32 zu komprimieren. Dies ermöglicht die Codierung von bis zu 4 Bytes pro Zeichen, ist jedoch völlig unlesbar.
isaacg
@isaacg fair 'nuff. Ich bearbeite, um in Bytes zu wechseln. Ich werde darüber nachdenken, wie ich den Stil von sclipting ausdrücken kann, um für zukünftige Herausforderungen akzeptabel zu sein.
Soll unsere Übermittlung fehlerfrei abgeschlossen werden, wenn die Eingabe eine leere Zeichenfolge ist? Der Konsens über Meta ist, dass die Ausgabe in STDERR ignoriert werden kann, aber da Sie es ausdrücklich erwähnt haben, muss ich fragen.
Dennis
@Dennis sollte eine leere Zeichenkette als Eingabe stehen bleiben. Es sollte nicht in eine Endlosschleife gehen oder anderen Text zur Standardausgabe drucken.

Antworten:

3

Pip, 22 + 1 = 23 Bytes

Verwendet -rFlagge. Beachten Sie, dass Sie dazu entweder 1) eine EOF nach der Eingabe eingeben müssen (Strg-D unter Linux, Strg-Z unter Windows) oder 2) die Eingabe von einer anderen Stelle einleiten müssen.

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

Erläuterung:

                        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)

Das Ergebnis des Kartenvorgangs ist eine Liste von Listen. Standardmäßig werden Listen jedoch beim Drucken einfach miteinander verkettet, sodass keine manuelle Konvertierung in eine Zeichenfolge erforderlich ist.

Beispiel mit Eingabe a13b1:

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

Pip hat grundlegende Regex-Unterstützung ab ... vor 2 Tagen . Großartiges Timing!

DLosc
quelle
Dieser arbeitet (und auch der Meister) mit der -rFlagge. (Die Frage gibt an, dass die Eingabe von STDIN stammen muss.)
Dennis
@ Tennis Ups, das habe ich verpasst. Fahne zur Bytezahl hinzugefügt. Ich sollte ich in der Lage, die spezielle Variable zu verwenden , qanstatt aohne zusätzliche Flaggen, aber es scheint ein Fehler zu sein , und es ist für die Eingabe zu fragen zweimal.
DLosc
Endlich eine Golfsprache mit Regex-Unterstützung!
Dennis
@Dennis Ich sehe dich jetzt zu Pip wechseln!
Optimierer
8

Perl / Bash 54 40 + 1 = 41 Bytes

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

Es ist im Grunde ein Regex innerhalb eines Regex. Und ein bisschen Magie.

Erläuterung

Der äußere reguläre Ausdruck /(\D*\d*)(\d)/gextrahiert jede lauflängencodierte Gruppe. Wir erfassen die zu wiederholenden Dinge $1und die Anzahl der Wiederholungen $2. Jetzt ersetzen wir jede solche Gruppe durch die Erweiterung dieser Gruppe. Dazu werten wir den Code "\$1=~s/./\$&x$2/egr" zwei Mal (wie von der /eeFahne auf der äußeren Substitution).

Die erste Auswertung interpoliert nur die Anzahl der Wiederholungen in den String - die anderen Variablen sind durch einen Backslash geschützt. Wenn a14wir also die Eingabe annehmen , hätten wir jetzt den Code $1=~s/./$&x4/egr, der erneut ausgewertet wird.

Dies wird die Ersetzung auf den Inhalt von $1(das Zeug zu wiederholen a1) anwenden . Die Ersetzung entspricht jedem Zeichen .. Die $&Variable enthält die gesamte Übereinstimmung, die wir x4mal wiederholen . Wir tun dies /global für jede Übereinstimmung und /rdrehen den ersetzten String um, anstatt die $1Variable (die schreibgeschützt ist) zu ändern . Das Ergebnis der inneren Substitution ist also aaaa1111.

Das -pFlag wendet die Ersetzung auf jede Eingabezeile an und druckt das Ergebnis aus.

amon
quelle
3
Es ist üblich, dies als Perl-Lösung zu bewerten, bei der Sie nur 1 Byte für den -pModifikator hinzufügen . Ich zähle 45 Bytes. Außerdem solltest du \Dstattdessen verwenden können [a-z], wodurch auch die Notwendigkeit entfällt i.
Dennis
7

CJam, 33 31 27 Bytes

Ughh, das Fehlen regulärer Ausdrücke macht das ziemlich lang ...

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

Wie es funktioniert

Wir durchlaufen alle Zeichen der Eingabezeichenfolge und verfolgen in jeder Iteration das zuletzt gefundene Zeichen (beginnend mit dem ersten leeren Zeichen). Dann prüfen wir, ob das aktuelle Zeichen nicht numerisch ist und das letzte Zeichen numerisch ist. Wenn ja, wiederholen wir jedes vorherige Zeichen (das noch nicht wiederholt wurde), die Anzahl mal.

(Ein bisschen veraltete Code-Erweiterung)

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

Probieren Sie es hier online aus

Optimierer
quelle
Ich schätze die Demonstration des Problems, das der Bytequalifizierer verursacht. Vielen Dank. Ich denke ein wenig darüber nach, wie man die Qualifikation so formuliert, dass Sprachen, bei denen eine einzelne Anweisung ein Mehrbyte-Zeichen ist, für diesen Sprachstil nicht bestraft werden, ohne dass die UTF-Codierung, die Sie gezeigt haben, über eine Lücke hereinkommt. PS Ich mag es wirklich, die algorithmische Aufschlüsselung zu sehen, die Sie bereitstellen.
6

rs , 43 71 Zeichen

Nun, das drehte sich schnell. Dumme Zahlen ...

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

Probieren Sie es hier aus!

Originalversion (funktionierte nicht mit Eingaben wie 123):

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

Erläuterung

Die erste Zeile stellt Räume zwischen den Läufen mit Zahlen, zB Drehen a313in a3 13.

Die zweite Zeile erweitert kontinuierlich die komprimierten Kodierungen wie aa5zu a5a5.

Die dritte Zeile konvertiert jede Instanz von a5in aaaaaden Wiederholungsoperator .

Die letzte Zeile entfernt die Leerzeichen.

kirbyfan64sos
quelle
Wie geht das a123b1?
Optimierer
@Optimizer Nicht gut. Ich muss es ein bisschen optimieren ...
kirbyfan64sos
@Optimizer behoben.
kirbyfan64sos
5

Javascript ( ES6 ), 86 83 Bytes

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

Kommentiert:

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
quelle
Willst alert(prompt().replace(/(.+?)(\d)(?!\d)/g,(a,b,c)=>Array(c+1).join(b)))du nicht das Gleiche tun? Es ist nur 71 Byte lang.
Ismael Miguel
@IsmaelMiguel das würde nur funktionieren, wenn es ein einzelnes Zeichen vor der Ziffer gäbe. Das Array-Verständnis behandelt das Wiederholen jedes Zeichens einzeln.
nderscore
Versuchen Sie es Array(6).join('12')und es wird zurückkehren '1212121212'.
Ismael Miguel
Dieser funktioniert: alert(prompt().replace(/(.+?)(\d)(?!\d)/g,(a,b,c)=>Array(-~c).join(b)))(gleiche 71 Bytes lang, getestet auf es6fiddle.net/ia7gocwg )
Ismael Miguel
1
Ich habe einen anderen (offensichtlichen) Weg gefunden, um 3 Bytes zu sagen: D
nderscore
4

CJam, 27 25 Bytes

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

Probieren Sie es online im CJam-Interpreter aus .

Wie es funktioniert

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
quelle
3

Pyth, 33 32 28 Bytes

ssmm*vedkPdPcz-hMJf<@zT\=UzJ

Probieren Sie es online aus: Vorführ- oder Testgeschirr

Erläuterung

Ich erkläre den Code anhand der Beispieleingabe aa1a23b2. Hoffentlich ist dies ein bisschen einfacher zu befolgen als ohne.

                               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
quelle
2

Rubin 73

gets.split(/(\d)(?!\d)/).each_slice(2){|s,i|s.chars.map{|c|$><<c*i.to_i}}

Tests: http://ideone.com/L1fssb

Cristian Lupascu
quelle
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}))

Wolfhammer
quelle
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])

Dies führt lediglich eine einfache reguläre Suche nach Ziffern durch, auf die keine Ziffer folgt, und führt dann die Zeichenfolgenarithmetik für jede Gruppe durch und führt sie alle wieder zusammen.

rekursiv
quelle
Sie könnten 2 Bytes sparen, indem Sie von Python 2 auf 3 wechseln. Dies raw_inputwird inputjedoch printzu Klammern.
Alex A.
Stimmt, aber ich spiele lieber mit Python 2.7.
rekursiver
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)])

Dadurch wird eine unbenannte Funktion erstellt, die eine Zeichenfolge als Eingabe annimmt und eine Zeichenfolge zurückgibt. Um es zu nennen, geben Sie ihm einen Namen, z f=s->....

Hier werden zwei ineinander verschachtelte Array-Auffassungen verwendet. Das äußere Verständnis wirkt sich auf jede Übereinstimmung der Eingabezeichenfolge mit dem regulären Ausdruck aus \D*\d*\d. Das innere Verständnis wiederholt jedes Zeichen der Übereinstimmung entsprechend der nachfolgenden Ziffer. Die Elemente des inneren Arrays sind zu einer Zeichenfolge verbunden, sodass das äußere Array ein Array von Zeichenfolgen ist. Diese werden zusammengefügt und zurückgegeben.

In Julia können Zeichenfolgen wie Zeichenfelder behandelt werden. Beachten Sie jedoch, dass für die Charund String-Typen in Julia nicht dieselben Methoden definiert sind. Insbesondere gibt es keine Methode zur Wiederholung von ^for-Zeichen. Hierfür wird eine verschlungene Problemumgehung verwendet:

  • Durchlaufen Sie die Zeichenfolge und lassen Sie das letzte Zeichen aus, das mit entfernt wird chop().
  • Konvertieren Sie das aktuelle Zeichen mit in eine Zeichenfolge string() .
  • Konvertieren Sie die nachfolgende Ziffer, die auch ein Zeichen ist, in eine Ganzzahl. Beachten Sie jedoch, dass beispielsweiseint('4') nicht 4 zurückgegeben wird. Stattdessen wird der Codepunkt zurückgegeben, der in diesem Fall 52 ist. Somit können wir 48 subtrahieren, um die tatsächliche Ganzzahl zurückzuerhalten.
  • Wiederholen string(b) nach int(p[end]) - 48.

Beispiele:

julia> f("ab3c5")
"aaabbbccccc"

julia> f("a0b3")
"bbb"

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

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

Danke an Pietu1998 und mbomb007 für die Vorschläge.

Python 2, 161 151 147 139 138 Bytes

Vielleicht war der heutige Tag nur ein langer Arbeitstag, aber ich kann für mein ganzes Leben nicht herausfinden, wie ich Golf spielen kann.

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
quelle
3
Wenn Sie zu Python 3 wechseln, werden einige Bytes gespart ( raw_out, parenthes to print). len(d)>0kann durch ersetzt werden, dda eine leere Liste falsch und eine nicht leere Liste wahr ist. list(...)kann direkt zum gehen for. Die eckigen Klammern w([...])sind nicht erforderlich, da dies das einzige Argument ist. Sie können das Leerzeichen in entfernen ) for. Das sind alles Kleinigkeiten, die mir bisher eingefallen sind.
PurkkaKoodari
@ Pietu1998 Danke für die Hilfe!
Kade
Wenn Sie Ihren Ansatz nicht zu sehr ändern, können Sie ihn entfernen, list()da Zeichenfolgen iterabel sind. Sie können verwenden w=r=''. Wenn Sie bereit sind, es zu ändern, sehen Sie sich meine Lösung an. :)
rekursiv
if c.isdigit()kann werden if'/'<c<':', wenn ich mich nicht irre.
DLosc
@ DLosc danke, das scheint zu funktionieren.
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;}

Die Herausforderung ist schwieriger als es aussieht, imo ..

Ungolfed & Testcode:

Probieren Sie es hier aus.

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"));
  }
}

Ausgabe:

aaabbbccccc
bbb
111b
aaa111b
aaa111222b
aaaaab
111222
Kevin Cruijssen
quelle