Erweitern Sie die Registerkarten (implementieren Sie expand (1)).

10

Ihre Aufgabe besteht diesmal darin, eine Variante des POSIX- expand(1)Dienstprogramms zu implementieren, mit der Tabulatoren auf Leerzeichen erweitert werden.

Ihr Programm besteht darin, eine Tabstop-Spezifikation zu verwenden und dann die Eingabe für Standard-In zu lesen und Tabulatorzeichen in der Eingabe durch die entsprechende Anzahl von Leerzeichen zu ersetzen, um zum nächsten Tabstop zu gelangen. Das Ergebnis sollte auf Standard out geschrieben werden .

Tabstop-Spezifikation

Eine Tabstop-Spezifikation besteht entweder aus einer einzelnen Zahl oder einer durch Kommas getrennten Liste von Tabstops. Im Fall einer einzelnen Zahl wird sie wiederholt, als ob ein Vielfaches davon in einer durch Kommas getrennten Liste vorkommt (dh 4als 4,8,12,16,20,...). Jeder Eintrag in einer durch Kommas getrennten Liste ist eine positive Ganzzahl, der optional ein a vorangestellt ist +. Ein +Präfix gibt einen relativen Unterschied zum vorherigen Wert in der durch Kommas getrennten Liste an. Der erste Wert in der Liste muss absolut sein (dh nicht vorfixiert). Die Tabstops geben die Spalte des nächsten Nicht-Leerzeichens (nach dem erweiterten Tabulator) an, wobei die Spalte ganz links als Nummer 0 verwendet wird. Tabulatoren sollten immer auf mindestens ein Leerzeichen erweitert werden.

Input-Output

Die Tabstop-Spezifikation kann nach Ihrem Ermessen entweder als erster Befehlszeilenparameter für das Programm verwendet oder vom Standard als erste Eingabezeile (abgeschlossen durch eine neue Zeile) eingelesen werden. Nachdem der Tabstop gelesen wurde, soll die verbleibende Eingabe (im ersten Fall alle Eingaben) bis zur Verarbeitung von EOF verarbeitet und erweitert werden. Die erweiterte Ausgabe wird auf Standard ausgeschrieben.

Es wird angenommen, dass alle erweiterten Tabstops und alle Eingaben maximal 80 Spalten breit sind. Alle erweiterten Tabstops nehmen strikt zu.


Beispiel

Die Tabstop-Spezifikation 4,6,+2,+8entspricht 4,6,8,16und mit beiden Eingaben

ab<Tab>c
<Tab><Tab>d<Tab>e<Tab>f

wird erweitert in ( zeigt ein Leerzeichen an)

ab␣␣c
␣␣␣␣␣␣d␣e␣␣␣␣␣␣␣f

01234567890123456   (Ruler for the above, not part of the output)
          1111111

Scoring ist reines ; kürzester Code gewinnt.

FireFly
quelle

Antworten:

2

GolfScript ( 77 75 Zeichen)

n/(','/{'+'/{~t++}*~:t}%81,{t*}%+:T;{[0\{.9={;T{1$>}?(.)@-' '*}*\)}/;]n+}/;

Ich bin sehr zufrieden mit dem Tabspec-Parsing.

# Split on commas
','/
# For each element:
{
    # Split on '+'
    '+'/
    # We now have either ["val"] or ["" "val"]
    # The clever bit: fold
    # Folding a block over a one-element array gives that element, so ["val"] => "val"
    # Folding a block over a two-element array puts both elements on the stack and executes,
    # so ["" "val"]{~t++}* evaluates as
    #     "" "val" ~t++
    # which evaluates val, adds the previous value, and concatenates with that empty string
    {~t++}*
    # Either way we now have a string containing one value. Eval it and assign to t
    ~:t
}%

Dann füge ich ein Vielfaches des letzten Elements hinzu, bis ich garantiert genug habe, um das Ende der 80 Spalten zu erreichen:

81,{t*}%+

Dies ergibt das gewünschte Verhalten, wenn nur ein Tabstop angegeben wurde, und ist ansonsten nur in Fällen relevant, die in der Spezifikation nicht erwähnt werden. (Hinweis: Die Liste der Tabulatoren wird auf 0 zurückgesetzt und das zuletzt analysierte Element wiederholt. Dies ist jedoch irrelevant, da bei der Verwendung der Liste nach dem ersten Element gesucht wird, das größer als die aktuelle Position ist.)

Der Rest ist ziemlich einfach.

Peter Taylor
quelle
2

Ruby 161 145

Liest die Tabstop-Spezifikation in der ersten Eingabezeile.

i=t=[]
gets.scan(/(\+)?(\d+)/){t<<i=$2.to_i+($1?i:0)}
81.times{|j|t<<j*i}
while gets
$_.sub!$&," "*(t.find{|s|s>i=$`.size}-i)while~/\t/
print
end

Bearbeiten: Es wurden zwei Zeilen hinzugefügt, mit denen der zuletzt gelesene Tabstop wiederholt wird, sodass die Tabstop-Spezifikationen einer einzelnen Zahl ebenfalls korrekt funktionieren

iist eine temporäre Variable zum Halten des zuletzt analysierten Tabstops. tist die Liste der Tabstobs, die aus der gets.scanZeile analysiert werden. Für ein gutes Maß addieren wir 81 Vielfache des zuletzt analysierten Tabstops. Die while getsSchleife läuft weiter, bis keine Eingabe mehr erfolgt. Für jede Eingabezeile ersetzen wir Leerzeichen durch Tabulatoren, jeweils eine Registerkarte, da sich die Zeichenfolge beim Hinzufügen der Leerzeichen bewegt und wir den richtigen Tabulator neu berechnen müssen.

daniero
quelle
Ich kenne Ruby nicht wirklich, aber kannst du x+($1?i:0)als die kürzere schreiben $1?x+i:x?
Timwi
@ Timwi Nein! Ruby ist ein wenig seltsam mit dem ternären Operator. Normalerweise müssen Sie irgendwo ein Leerzeichen einfügen, da der Doppelpunkt ( :) auch den Anfang eines Symbols markieren kann. Da ein Symbol jedoch nicht mit einer Ziffer beginnen kann, :0ist es ohne Leerzeichen in Ordnung. Oder so. Es ist komisch. Die Klammern sind auch entscheidend, wie es scheint.
Daniero
Das Tabstop-Scannen sieht für mich fehlerhaft aus. In t<<x+($1?i:0);i=xder ersten Aussage ändert sich nichts x, oder? Ich denke, Sie müssen es umkehren alsi=x+($1?i:0);t<<i
Peter Taylor
1
Tatsächlich können Sie 16 sparen, indem Sie die ersten beiden Zeilen durch ersetzen i=t=[](da idies beim ersten Mal garantiert nicht benötigt wird). Vereinfachung der Tab-Stop-Analyse {t<<i=$2.to_i+($1?i:0)}und lvollständige Eliminierung ( ienthält diesen Wert bereits). Aber schön, dass Sie sich nicht darum kümmern, dass der Tab nicht mehr ständig zunimmt: Das spart Ihnen 4 Zeichen, und ich kann ihn ausleihen, um 2 zu sparen.
Peter Taylor
@ PeterTaylor Danke für die Eingabe! Es war nicht direkt fehlerhaft, aber sicherlich ein wenig aufgebläht. Ich finde es zu einfach, sich auf solchen Code blind zu starren.
Daniero
1

C 228 Zeichen

Hier ist eine C-Lösung, um die Dinge zu starten. Hier gibt es noch viel Golf zu spielen (schauen Sie sich all diese ifs und fors und putchars an ...). Getestet mit dem Beispieltestfall sowie mit derselben Eingabe, jedoch 4und 8für die Registerkartenspezifikation.

S[99],i;L,C;main(v){for(v=1;v;)v=scanf("+%d",&C),v=v>0?C+=L:scanf("%d",&C),
v&&(S[L=C]=++i,getchar());for(;i==1&&C<80;)S[C+=L]=1;for(C=L=0;C=~getchar();)
if(C+10)putchar(~C),L+=C+11?1:-L;else for(putchar(32);!S[++L];)putchar(32);}
FireFly
quelle