Beenden Sie die Tabs gegen Space War

24

Beenden Sie die Tabs gegen Space War

Es gab also viele Diskussionen darüber, ob Tabulatoren oder Leerzeichen zum Einrücken / Formatieren von Code verwendet werden sollen. Können Sie der Universität helfen, den Streit beizulegen, indem Sie eine unglaublich verrückte und einzigartige Formatierungsmethode anwenden?


Ihre Aufgabe ist es, ein vollständiges Programm oder eine Funktion zu schreiben, die alle Tabulatoren in vier Leerzeichen erweitert. Und ersetzt dann eine Folge von n führenden Leerzeichen durch "/ (n - zwei Sterne hier) /". Sie erhalten Eingaben über mehrere Zeilen in jedem vernünftigen Format (einzelnes String-Array von Strings für jede neue Zeile. Spalten-Array usw.).

Probeneingabe schamlos gestohlen . Beachten Sie, dass, da Tabulatoren in SE automatisch auf vier Leerzeichen erweitert werden, ich sie als "^" -Zeichen repräsentiere, Sie jedoch auch Tabulatoren (Codepunkt 0x09) behandeln müssen. Alle "^" Zeichen stehen für eine Tabellierung.

Calculate the value 256 and test if it's zero
If the interpreter errors on overflow this is where it'll happen
++++++++[>++++++++<-]>[<++++>-]
+<[>-<
    Not zero so multiply by 256 again to get 65536
    [>++++<-]>[<++++++++>-]<[>++++++++<-]
    +>[>
        # Print "32"
        ++++++++++[>+++++<-]>+.-.[-]<
    <[-]<->] <[>>
        # Print "16"
        +++++++[>+++++++<-]>.+++++.[-]<
<<-]] >[>
    # Print "8"
    ++++++++[>+++++++<-]>.[-]<
<-]<
# Print " bit cells\n"
+++++++++++[>+++>+++++++++>+++++++++>+<<<<-]>-.>-.+++++++.+++++++++++.<.
>>.++.+++++++..<-.>>-
Clean up used cells.
[[-]<]l
^this is preceded by a tab
^^two tabs
^^^three tabs etcetera! 

Beispielausgabe

Calculate the value 256 and test if it's zero
If the interpreter errors on overflow this is where it'll happen
++++++++[>++++++++<-]>[<++++>-]
+<[>-<
/**/Not zero so multiply by 256 again to get 65536
/**/[>++++<-]>[<++++++++>-]<[>++++++++<-]
/**/+>[>
/******/# Print "32"
/******/++++++++++[>+++++<-]>+.-.[-]<
/**/<[-]<->] <[>>
/******/# Print "16"
/******/+++++++[>+++++++<-]>.+++++.[-]<
<<-]] >[>
/**/# Print "8"
/**/++++++++[>+++++++<-]>.[-]<
<-]<
# Print " bit cells\n"
+++++++++++[>+++>+++++++++>+++++++++>+<<<<-]>-.>-.+++++++.+++++++++++.<.
>>.++.+++++++..<-.>>-
Clean up used cells.
[[-]<]l
/**/this is preceded by a tab
/******/two tabs
/**********/three tabs etcetera! 

Da die Universität Speicherplatz zum Herunterladen von Vim und Emacs benötigt, dürfen Sie nur sehr wenig Speicherplatz für Ihren Code verwenden. Daher ist dies und der kürzeste Code gewinnt. Sie können davon ausgehen, dass die Eingabe korrekt ist und Zeilen mit weniger als vier Leerzeichen (nach dem Ersetzen von Tabulatoren) zu undefiniertem Verhalten führen können.

Haftungsausschluss

Diese "ausgezeichnete" Formatierungsstrategie wurde mit freundlicher Genehmigung von Geobits erstellt und mit seiner Erlaubnis reproduziert. Bei der Erstellung dieser Herausforderung wurden keine Programmierer verletzt.

Rohan Jhunjhunwala
quelle
1
Treten Tabulatoren nur am Zeilenanfang auf (dh als Einrückung)? Können Zeilen gemischte Einrückungen haben (Tabulatoren + Leerzeichen)?
Lynn
20
Jemand schickt bitte eine Antwort in Whitespace .
GuitarPicker
2
Sollten wir Zeilen in Betracht ziehen, die mit beginnen /*, oder kann dies als nicht "wohlgeformter Eingang" angesehen werden? Eine C ++ - Quelldatei wäre ein besserer Test gewesen, da der mehrzeilige Kommentar /* */möglicherweise einige Antworten unterbrechen würde, die das erste und das letzte der führenden Leerzeichen durch ein ersetzen /und dann Leerzeichen füllen *.
Seshoumara
1
Der Krieg ist beendet: medium.com/@hoffa/… (Es sei denn, Sie programmieren anscheinend in C.)
Becherglas
1
@RohanJhunjhunwala Jetzt stelle ich meine erste Frage erneut, da es nicht um kompilierbaren Code ging. Stellen Sie sich denselben /* */C ++ - Code vor, diesmal jedoch am Anfang der Zeile. Entsprechend Ihrer Spezifikation sollte es so belassen werden, wie es ist. Hier ist die Falle, und es wurden bereits falsche Antworten gefunden, dass ein regulärer Ausdruck, der /\** /verwendet wird, um diese Leerzeichen zwischen // mit Sternchen zu füllen, die Zeile in umwandeln würde /***/. Ich habe diese Konvertierung auch gesehen /*//*/. Ich gehe davon aus, dass beide falsch sind.
Seshoumara

Antworten:

2

V , 21 , 20 Bytes

Íô/    
Î^hr/hv0r*r/

Probieren Sie es online!

Dies ist buchstäblich nur ein direkter Teil meiner vim Antwort. Die bemerkenswerten Unterschiede:

  • Der ÍBefehl (Globaler Ersatz) füllt das /gFlag automatisch aus , wodurch zwei Bytes eingespart werden

  • ô ist identisch mit \t

  • ÎIst eine Mnemonik für :%normund füllt auch den erforderlichen Abstand zwischen :%normund den Tastenanschlägen aus.

  • Der abschließende Wagenrücklauf am Ende wird implizit hinzugefügt.

DJMcMayhem
quelle
27

Vim, 37, 34, 33, 32 Bytes

:%s/\t/    /g|%norm ^hr/hv0r*r/

Probieren Sie es online!

Beachten Sie, dass dies einen abschließenden Wagenrücklauf (Enter) in vim erfordert, jedoch nicht im Online-Interpreter.

Dies verwendet den V-Interpreter, da er abwärtskompatibel ist. Eine sehr einfache Lösung.

Hier ist ein GIF, mit dem Sie die Lösung in Echtzeit sehen können. Dies verwendet eine etwas ältere Version, und ich habe einige zusätzliche Tastenanschläge hinzugefügt, um die Ausführung zu verlangsamen, damit Sie sehen können, was passiert:

Bildbeschreibung hier eingeben

Und hier ist die Erklärung, wie es funktioniert:

:%s/\t/    /g           "Replace every tab with 4 spaces
|                       "AND
%norm                   "On every line:
      ^                 "  Move to the first non-whitespace char
       h                "  Move one character to the left. If there is none, the command will end here.
         r/             "  Replace it with a slash
           h            "  Move to the left
            v0          "  Visually select everything until the first column
              r*        "  Replace this selection with asterisks
                r/      "  Replace the first character with a slash
DJMcMayhem
quelle
Ich wollte +1 für die Verwendung, gaber dann haben Sie bearbeitet, um g: / +1 trotzdem nicht zu verwenden: D
Downgoat
@downgoat Haha, danke! Ich bin sogar viel stolzer über die Version ohne, :gweil sie eine weniger bekannte Funktion missbraucht: Der normBefehl wird abgebrochen, wenn er ^F<space>fehlschlägt. Ist :%norm ^F<space>fooalso im Wesentlichen dasselbe wie :g/^ /norm foolustige Vim-Hacks. : D
DJMcMayhem
huh, ich dachte, ^ F wurde verwendet, um den Bildschirm zu positionieren. Hat es ein anderes Verhalten im Inneren norm?
Downgoat
1
@downgoat Haha, nein, es ist ^Fkeine <C-f>Silly Vim- Tastennotation . In diesem Fall ist es ^, zum ersten Nicht-Leerzeichen zu springen und F<space>das erste Leerzeichen hinter dem Cursor zu finden.
DJMcMayhem
ohhh, das macht jetzt so viel mehr Sinn> _>
Downgoat
11

Perl, 41 Bytes

s,␉,    ,g;s,^  ( +),/@{[$1=~y| |*|r]}/,

Laufen Sie mit der -pFlagge wie folgt:

perl -pe 's,␉,    ,g;s,^  ( +),/@{[$1=~y| |*|r]}/,'
#     ↑   └───────────────────┬───────────────────┘
#     1 byte               40 bytes

Durch einen Tabulator ersetzen (in Bash versuchen Sie, etwas einzugeben Control-V Tab.)

Lynn
quelle
1
Die Art perlund Weise , wie diese Rückbeziehung an Ort und Stelle ersetzt wurde, hätte ich mir auch gewünscht sed.
Seshoumara
7

Cheddar , 60 57 56 Bytes

3 Bytes gespart dank @Conor O'Brien

@.sub(/\t/g," "*4).sub(/^ +/gm,i->"/"+"*"*(i.len-2)+"/")

Ich wünschte, Cheddar hätte eine bessere String-Formatierung.

Probieren Sie es online!

Erläuterung

Dies ist eine Funktion. @ist eine funktionalisierte Eigenschaft (z. B. ruby's &:), mit der Sie Folgendes ausführen können: `ar.map (@. head (-1))

@                      // Input
 .sub( /\t/g, " "*4)   // Replace tabs with four spaces
 .sub(
   /^ +/gm,            // Regex matches leading spaces
   i ->                // i is the matched leading spaces
     "/"+              // The / at the beginning
     "*"*(i.len-2)+    // Repeat *s i-2 times
     "/"                // The / at the end
 )

Wenn Sie mit Regex nicht vertraut sind:

/^ +/gm

Dies stimmte im Grunde mit einem oder mehreren ( +) Leerzeichen ( ) am Anfang ( ^) jeder ( g) Zeile ( m) überein .

Downgoat
quelle
funktionieren wörtliche Tabulatoren in Cheddar-Regexen? Auch /^ +/als Regex genügt, da davon ausgegangen werden kann, dass die führenden Leerzeichen mindestens 4 lang sind.
Conor O'Brien
@ ConorO'Brien Ich glaube, sie tun, aber ich habe nicht getestet
Downgoat
Die Registerkarten sollen vor der Transformation ersetzt werden.
Conor O'Brien
@ ConorO'Brien oh> _> Ich hatte es ursprünglich so und dann habe ich es geändert
Downgoat
6

Mathematica, 97 Bytes

a=StringReplace;a[a[#,"\t"->"    "],StartOfLine~~b:" "..:>"/"<>Table["*",StringLength@b-2]<>"/"]&

Anonyme Funktion. Nimmt einen String als Eingabe und gibt einen String als Ausgabe zurück.

LegionMammal978
quelle
5

Python 3, 124 Bytes

Benutzt guten alten Regex.

import re
lambda I:re.sub('^\s*(?m)',lambda m:'/'+'*'*len(m.group()[:-2])+'/',re.sub('\t+',lambda g:' '*4*len(g.group()),I))

Ideone es!

Beta-Zerfall
quelle
4

Java 210 207 Bytes

Dies ist die Referenzlösung, die sie naiv implementiert.

void a(String[]a){for(String s:a){s=s.replaceAll("\t", "    ");String x,y="";int j,i=s.length()-(x=s.replaceAll("^\\s+", "")).length();if(i>3){y="/";for(j=0;j++<i-1;)y+="*";y+="/";}System.out.println(y+x);}}
Rohan Jhunjhunwala
quelle
6
Vim: 37 Bytes, Cheddar: 65 Bytes, JavaScript: 75 Bytes, dann gibt es Java bei 210 Bytes: P Warum bin ich nicht überrascht
Downgoat
1
Sehr prägnanter Code in Java: P
Rohan Jhunjhunwala
Sie können die letzte for-Schleife ändern 1 Byte zu speichern: for(int j=0;++j<i-1;). Sie können aber auch das Entfernen int vor jund legte es nach dem bereits int:int i=s.length()-(x=s.replaceAll("^\\s+", "")).length(),j;
Kevin Cruijssen
Kann es nicht ein Lambda sein, um Bytes mit (a) -> {...} zu rasieren?
BunyaCloven
Zumindest ist es noch lesbar und benötigt keine weiteren Kommentare: o)
René
3

JavaScript ES6, 75 Byte

s=>s.replace(/\t/g,"    ").replace(/^ +/gm,k=>`/${"*".repeat(k.length-2)}/`)

Ersetzen \tSie den Code durch einen wörtlichen Tabulator.

Conor O'Brien
quelle
3

Java, 185 184 167 152 Bytes

S->S.map(s->{s=s.replace("\t","    ");String t=s.replaceAll("^ +","");int n=s.length()-t.length();if(n>3){s="/";for(;n-->2;)s+="*";s+="/"+t;}return s;})

Angesichts der sehr losen Definition des String-Arrays im ersten Beitrag habe ich verwendet, Stream<String>was einige konsequente Byte-Einsparungen ermöglicht.

Ich habe andere Techniken als die RI verwendet, um das gleiche Ziel zu erreichen. Der Algorithmus selbst ist eher der gleiche.

Testen und ungolfed :

import java.util.Arrays;
import java.util.stream.Stream;

public class Main {

  public static void main(String[] args) {
    StringStreamTransformer sst = lines -> lines.map(line -> {
      line = line.replace("\t","    ");
      String trimmed = line.replaceAll("^ +", "");
      int startingSpaces = line.length() - trimmed.length();
      if (startingSpaces > 3) {
        line = "/";
        for(;startingSpaces > 2; startingSpaces--) {
          line += "*";
        }
        line += "/" + trimmed;
      }
      return line;
    });


    Stream<String> lines = Arrays.stream(new String[]{
      "lots of spaces and tabs after\t\t    \t\t         \t\t\t\t\t",
      "no space",
      " 1 space",
      "  2 spaces",
      "   3 spaces",
      "    4 spaces",
      "     5 spaces",
      "      6 spaces",
      "       7 spaces",
      "        8 spaces",
      "\t1 tab",
      "\t\t2 tabs",
      "\t\t\t3 tabs"
    });
    sst.map(lines).map(s -> s.replace(" ", ".").replace("\t","-")).forEach(System.out::println);


  }
}
Olivier Grégoire
quelle
2

Retina , 25 Bytes

Das \tsollte durch ein tatsächliches Tabulatorzeichen (0x09) ersetzt werden.

\t
4$* 
%`^  ( +)
/$.1$**/

Probieren Sie es online!

Erläuterung

\t
4$* 

Ersetzen Sie jede Registerkarte durch vier Leerzeichen.

%`^  ( +)
/$.1$**/

Transformieren jede Zeile einzeln ( %) durch Abgleichen 2+NLeerzeichen am Anfang der Zeile und ersetzt sie mit /.../denen ...sind NKopien *.

Martin Ender
quelle
2

Python, 125 111 Bytes

lambda s:'\n'.join(('/'+(len(L.replace('\t',' '*4))-len(L.strip())-2)*'*'+'/'+L.strip(),L)[L[0]>' ']for L in s)

https://repl.it/DGyh/2

Atlasologe
quelle
2

SED (56 + 1 für -r) 57

s/⇥/    /g;tr;:r;s,^ ( *) ,/\1/,;T;:l;s,^(/\**) ,\1*,;tl

Wo ist ein Tabulator?
1. Ersetzt Tabulatoren durch Leerzeichen.
2. Ersetzt das erste und letzte führende Leerzeichen durch /.
3. Ersetzt das erste Leerzeichen nach /und 0+ *durch ein, *bis keine Übereinstimmung mehr vorliegt.

Riley
quelle
Da sed angegeben ist, sind keine einfachen Anführungszeichen im Code erforderlich, ebenso wenig wie das Entfernen von -r '' aus Ihren anderen sed-Antworten, da Sie das Skript als in einer Quelldatei gespeichert betrachten können, mit der Sie ausgeführt werden -f. Alle zusätzlichen Flags, die wie n oder r verwendet werden, sollten als jeweils ein Byte gezählt werden. Sie sparen hier also 2 Bytes.
Seshoumara
Das habe ich mir gedacht, aber ich will sicher. Vielen Dank.
Riley
Der ;Befehl nach dem t ist ebenfalls nicht erforderlich. Für den Code selbst benötigen Sie ein ^ am Anfang des dritten sBefehls, andernfalls wird eine Eingabe wie diese "3/5" in "3 / * 5" umgewandelt. Im ersten sBefehl befindet sich tatsächlich ein Tabulator, der jedoch nicht korrekt angezeigt und irreführend ist. Verwenden Sie daher entweder \ t oder geben Sie an, dass char ein Tabulator war.
Seshoumara
@seshoumara Danke, ich versuche von meinem Handy aus zu posten ... Das ist nicht die einfachste Sache.
Riley
Ich glaube, ich habe mehr Zeit damit verbracht, diese Antwort zu bearbeiten als alle anderen zusammen. Danke für die Hilfe!
Riley
1

Die Universität soll ein bisschen mehr Platz für Programme in Emacs Lisp (oder Standard prüfen , so dass tabifyund untabifyallein), wie sie noch mehr bekommen ausführlicher als Java. Es sollte auch Schülern (oder Lehrern), deren Identifizierungsgröße kleiner als vier ist oder die in einer nicht-C-ähnlichen Sprache codieren, besondere Aufmerksamkeit geschenkt werden.

Die folgende Lösung hat 206 Bytes

(lambda (b e)(let((tab-width 4))(untabify b e)(goto-char b)(while(re-search-forward"^ +"e t)(replace-match(format"/%s/"(apply'concat(mapcar(lambda(x)"*")(number-sequence 1(-(length(match-string 0))2)))))))))

Unter der Annahme, dass dies tab-widthnicht explizit festgelegt werden muss, können wir 20 davon speichern.

(lambda(b e)(untabify b e)(goto-char b)(while(re-search-forward"^ +"e t)(replace-match(format"/%s/"(apply'concat(mapcar(lambda(x)"*")(number-sequence 1(-(length(match-string 0))2))))))))

Und ungolfed Version würde so aussehen

(defun end-tab-war (beg end)
  (let ((tab-width 4))
    (untabify beg end)
    (goto-char beg)
    (while (re-search-forward "^ +" end t)
      (replace-match
       (format
        "/%s/"
        (apply 'concat
               (mapcar (lambda(x) "*")
                       (number-sequence 1
                                        (- (length (match-string 0))
                                           2)))))))))

Wir begeben uns zuerst in untabifydie Region, bevor es losgeht. Während am Anfang einer Zeile ein Leerzeichen angezeigt wird, wird dieses durch einen Kommentar ersetzt, der so lang ist wie das angegebene Leerzeichen. Um genau zu sein, wird der einzufügende Kommentar von konstruiert

 (format"/%s/"(apply'concat(mapcar(lambda(x)"*")(number-sequence 1(-(length(match-string 0))2)))))

die selbst nimmt 97 Bytes. Eine kürzere Lösung zum n-maligen Kopieren von Zeichenfolgen wird sehr geschätzt.

Lord Yuuma
quelle
1

Ruby, 52 47 + 1 (p Flag) = 48 Bytes

Bearbeiten : ganze 5 Bytes dank Value Ink gespeichert

ruby -pe 'gsub ?\t," "*4;sub(/^ +/){?/+?**($&.size-2)+?/}'
michau
quelle
1
Können Sie das pFlag verwenden, um die Tatsache auszunutzen, dass (g) sub $_den gedruckten Wert ändert und somit ändert? ruby -pe 'gsub ?\t," "*4;sub(/^ +/){?/+?**($&.size-2)+?/}'
Value Ink
Danke, ich wusste nicht, (g)subohne dass sich $_hier etwas ändern lässt .
Michau
1

GNU sed, 66 64 + 1 (r Flag) = 65 Bytes

Edit: 1 Byte weniger dank Rileys Vorschlag.

s/\t/    /g
s,^ ( *) ,/\1\n,
:
s,^(/\**) ( *\n),\1*\2,
t
s,\n,/,

Führen Sie Folgendes aus : sed -rf formatter.sed eingabedatei

Der Grund für die mit einer Trennung \nvom Rest des Textes auf dieser Linie die führenden Leerzeichen, ist , weil sonst ein C ++ Zeile mit einem Kommentar wie dieser Start /* */wäre wiederum in /*****/durch eine einfachere Linie 4 wie s,^(/\**) ,\1*,oder sogar s,^(/\**) ( */),\1*\2,. Da sed das Skript für jede Eingabezeile ausführt, \nwird beim Lesen no in den Musterraum eingefügt.

Seshoumara
quelle
Sie können ein Byte speichern, indem /Sie den Abschluss erst eingeben, wenn Sie den ersetzen \n. Das erspart Ihnen den Abgleich in Zeile 4.
Riley
@ Riley Guter Fang. Der Code wurde aktualisiert.
Seshoumara
Sie können einen anderen speichern, indem Sie ihn durch \tein Tabulatorzeichen ersetzen .
Riley
@ Riley Das stimmt, aber da es hier nicht als Tab gedruckt wird, bin ich im Zweifel. Ich werde dies für zukünftige Sed-Antworten berücksichtigen, bei denen die Anzahl der Bytes wettbewerbsfähiger ist.
Seshoumara