String-Replikator

15

In Vim können Sie einen Befehl wiederholen, indem Sie ihm eine Zahl voranstellen, wie dies 3ddäquivalent zu ist dd dd dd. Nun, dieses sich wiederholende Muster ist nicht auf Vim-Befehle beschränkt. String kann auch auf diese Weise repliziert werden.

Spezifikation:

Ausgehend von einer Zeichenfolge, die nur aus Ziffern, alphabetischen Zeichen (sowohl Groß- als auch Kleinbuchstaben) und Leerzeichen besteht, und einer optionalen nachgestellten Zeile als Eingabe schreiben Sie ein Programm, das die folgenden Aufgaben ausführt:

  • Jedes "Wort" besteht aus Ziffern und Buchstaben. Wenn einem Buchstaben eine Zahl vorangestellt ist (es kann mehr als eine Ziffer in einer Zahl geben oder die Zahl ist Null), wiederholen Sie diesen Buchstaben für die angegebenen Zeiten. Beispielsweise:

    a2bc -> abbc
    3xx1yz -> xxxxyz
    10ab0c0d0e -> aaaaaaaaaab # No 'cde' because there's a zero
    2A2a2A2a -> AAaaAAaa
    
  • Wörter werden durch Leerzeichen getrennt. Zwischen zwei benachbarten Wörtern darf maximal ein Leerzeichen stehen.

Einfach richtig? Hier ist das zusätzliche Zeug:

  • Wenn vor dem Leerzeichen eine Zahl steht, wiederholen Sie das nächste Wort für die angegebenen Zeiten. Die Nummer wird immer am Ende des vorherigen Wortes oder am Anfang der Zeichenkette angehängt. Beispiel:

    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
    
  • Wenn ein leeres Wort wiederholt werden soll, geben Sie nicht mehrere Leerzeichen hintereinander aus. Zerdrücke sie:

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

    Mit anderen Worten, Ihr Programm sollte niemals zwei Leerzeichen zusammen ausgeben.

  • Die Eingabe ist nie leer, es ist jedoch nicht erforderlich, dass die Ausgabe nicht leer ist:

    0 3x -> (empty)
    
  • Ein- und Ausgabe können auf beliebige Weise erfolgen. Eine Funktion, die die Eingabe von Argumenten und die Ausgabe über Rückgabewerte übernimmt, ist ebenfalls akzeptabel.

    Wenn es sich um ein Programm handelt, darf es nicht mit einem Fehler beendet werden (dh der Rückgabewert ist Null).

  • Zahlen sind immer dezimal und beginnen nie mit einer Null, es sei denn, die Zahl selbst ist Null. In diesem Fall gibt es nur eine Null. Das heißt, Sie müssen nicht berücksichtigen 077aoder 000aals Eingabe geben.

  • Alle Zahlen sind unter 2 ^ 31 (2.147.483.648). Die maximale Ausgabelänge liegt unter 2 ^ 32 (4.294.967.296) Bytes.

  • Das Programm kann optional ein nachfolgendes Leerzeichen und / oder eine nachfolgende neue Zeile ausgeben. Diese Leerzeichen und Zeilenumbrüche wirken sich nicht auf die Gültigkeit der Ausgabe aus. Auch wenn die richtige Ausgabe leer sein sollte, wird eine Ausgabe eines Leerzeichens gefolgt von einer neuen Zeile qualifiziert.

Kurz gesagt, eine gültige Eingabe entspricht diesem regulären Ausdruck:

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

Und für eine gültige Ausgabe:

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

Beispiel Testfälle:

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

Dies ist ein , also gewinnt das kürzeste Programm in Bytes in jeder Sprache!

iBug
quelle
3
.... "Programm darf nicht mit Fehler beendet werden" "Eingabe darf nicht als Zeichenliste erfolgen ..." aus welchem ​​Grund? (wie Sie bereits wussten) erlauben wir generell ein flexibles I / O-Format.
user202729
@ user202729 Ich überlege mir letzteres zu entfernen. Für das Programm-Exit-Ergebnis möchte ich es behalten. Bearbeiten : Fertig
iBug
1
Ähnlich .
Cole
1
Auch ähnlich
danieltakeshi
Ich denke, ein Test wie a3 0xc b-> a c c c bsollte hinzugefügt werden, da ich ursprünglich Code hatte, der für alle oben genannten Testfälle funktionierte, aber dafür nicht richtig funktionierte.
Brad Gilbert b2gills

Antworten:

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}

Probier es aus

Erweitert:

{ # 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)
}

Die ~(…).wordsKombination entfernt überflüssige Leerzeichen, was nützlich ist, wenn ein „Wort“ entfernt wird.

Brad Gilbert b2gills
quelle
1

Python 2, 286 275 260 257 238 Bytes

-19 bytes dank 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 Nimmt eine Zeichenfolge als Argument und druckt die formatierte Zeichenfolge.

Hier ist eine Antwort mit den Testfällen.

Ungolfed-Code:

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

Wir arbeiten immer noch an Verbesserungen.

nog642
quelle
238 bytes
ovs
@ovs Danke. Ich kann nicht glauben, dass ich nicht daran gedacht habe, den Zeilenvorschub und den Einzug für den loszuwerden exec, da dies die einzige Zeile in der Funktion ist.
nog642
1

Perl 5 , 77 + 1 ( -p) = 78 Bytes

s/\d+( .*?)(\d*)( |$)/$1x$&.$2.$3/eg&&redo;s/\d+(\D)/$1x$&/eg;s/ +/ /g;s;^ +;

Probieren Sie es online!

Xcali
quelle
0

Sauber , 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]]])

Probieren Sie es online!

Οurous
quelle
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)

Probieren Sie es online!

Jonathan S.
quelle