Umwandlung von Zahnspange in rechte Zahnspange (traurige Zahnspange)

26

Die rechte Klammer ist eine Art von Code-Klammer, bei der geschweifte Klammern und Semikolons an einem einzelnen Punkt auf der rechten Seite einer Datei ausgerichtet sind.

Beispielbild hier

Im Allgemeinen wird dies aus mehreren Gründen als schlechte Praxis angesehen.

Die Herausforderung

Führen Sie eine mehrzeilige Zeichenfolge durch eine beliebige Methode und konvertieren Sie den Klammerstil in die rechte Klammer.

Für diese Herausforderung benötigen Sie sie nur, um mit Java-Code zu arbeiten. Theoretisch sollte sie jedoch mit jedem Code funktionieren, der geschweifte Klammern und Semikolons verwendet.

Sie müssen alle {};Zeichen hintereinander mit beliebigem Leerzeichen abrufen. Z.B. }}, ; } }\n\t\t}und richten Sie sie mit Leerzeichen auf der rechten Seite der Datei aus.

beispielsweise:

a {
b;
{c

soll werden

a {
b ;{
c

Oder, abstrakter ausgedrückt, schieben Sie alle Leerzeichen von der linken Seite aller {};Zeichen nach rechts.

Einrückungen von Linien sollten ansonsten erhalten bleiben. Zeilen, die nach dem Verschieben der {};Zeichen nur Leerzeichen enthalten, können optional entfernt werden.

Beispielsweise:

a{
    b{
        c;
    }
}
d;

Kann auch werden

a        {
    b    {
        c;}}
d        ;

oder

a        {
    b    {
        c;}}


d        ;

Nach rechts verschoben bezieht sich auf alle {};Zeichen, die an einem Punkt ausgerichtet sind, der nicht kürzer als die längste Linie ist. Jede Menge Platz danach ist akzeptabel.

Das Folgende ist also akzeptabel:

a {
bc;

a  {
bc ;

a   {
bc  ;

etc...

Zeilen in jedem Code können {};Zeichen zwischen anderen Nicht-Leerzeichen enthalten. Die Behandlung dieses Falls ist nicht erforderlich. Wenn Sie jedoch geneigt sind, sollten Sie sie an Ort und Stelle belassen. Zeilen dürfen auch überhaupt keine {};Zeichen enthalten , und dies sollte korrekt gehandhabt werden. Wie unten gezeigt.

a {
b ;
c
d }

Da wir nicht möchten, dass Code Review die schrecklichen Dinge sieht, die wir tun, müssen Sie Ihren Code so klein wie möglich machen.

Beispiele / Testfälle

Generisches Java

public class HelloWorld{
       public static void main(String[] args){
           System.out.println("Hello, World!");
       }
}

wird...

public class HelloWorld                        {
    public static void main(String[] args)     {
        System.out.println("Hello, World!")    ;}}

Das Bild selbst

public class Permuter{
    private static void permute(int n, char[] a){
        if (n == 0){
            System.out.println(String.valueOf(a));
        }else{
            for (int i=0; i<= n; i++){
                permute(n-1, a);
                swap(a, n % 2 == 0 ? i : 0, n);
            }
        }
    }
    private static void swap(char[] a, int i, int j){
        char saved = a[i];
        a[i] = a[j];
        a[j] = saved;
    }
}

wird...

public class Permuter                                {
    private static void permute(int n, char[] a)     {
        if (n == 0)                                  {
            System.out.println(String.valueOf(a))    ;}
        else                                         {
            for (int i=0; i<= n; i++)                {
                permute(n-1, a)                      ;
                swap(a, n % 2 == 0 ? i : 0, n)       ;}}}
    private static void swap(char[] a, int i, int j) {
        char saved = a[i]                            ;
        a[i] = a[j]                                  ;
        a[j] = saved                                 ;}}

Nicht so perfekt generisches Python

Für den Kontrast

def Main():
    print("Hello, World!");

Main();

wird...

def Main():
    print("Hello, World!")    ;
Main()                        ;

Anmerkungen

  • Es gelten Standard-Regelungslücken
  • Standard IO gilt
  • Das ist , also gewinnt das kürzeste Programm in Bytes!
  • Ich hafte nicht für Schäden, die mit der Programmierung im Stil der rechten Zahnspange zusammenhängen
  • Habe Spaß!

Notizen bearbeiten

Ich habe die Herausforderungsdetails umformuliert. Hoffentlich habe ich nicht gegen die Regeln verstoßen. Ich versichere Ihnen, dass es unbeabsichtigt war. Dies sollte eine deutlichere und weniger widersprüchliche Spezifikation sein.

Ein Taco
quelle
Wie lautet das Urteil für Zeilen mit mehreren Semikolons? So etwas wieint a=0;System.out.println(a);
Value Ink
2
Das ist vielleicht nicht das beste Bild für die Herausforderung, wenn wir nicht mit Schleifen wie im Beispielbild umgehen müssen?
Dennis
1
Es sieht so aus, als stammte das Bild in der Frage von diesem Beispiel , auf das dieses Follow-up mit komplexeren Beispielen folgte
Ray Toal,
2
Es könnte deutlicher gemacht werden , dass Sie die wollen ;{}Zeichen gesammelt, wenn sie in separaten Zeilen sind (es ist nur aus dem Beispiel klar, nicht die Regeln, und in der Tat , wenn eine Zeile besteht \t}würde die Vertiefung Haltbarmachung nicht bewegt }bis zum Ende der vorherigen Zeile)
Chris H
2
Guter Gott, bitte sagen Sie mir, dass das in der Praxis für eine wörtliche Sprache wie Java niemand tut.
Magic Octopus Urn

Antworten:

5

V + Bash-Dienstprogramme, 64 62 61 60 62 Byte

Dank @DJMcMayhem für die Zusammenstellung der ex-Befehle 1 Byte gespart

:se ve=all|%!wc -L
y$uò/^ *<93>[{};]
xk$pòò/<84> {};][{};]«$
lDî^R0|p

^Rist das Zeichenliteral für <C-r>( 0x12) und <84>ist 0x84und <94>ist 0x94.

wc -LFunktioniert auf den meisten * nix-basierten Systemen, jedoch nicht auf macOS. Für macOS müssen Sie dies tun, gwc -L nachdem Sie coreutils mit brew erhalten haben, falls Sie dies noch nicht getan haben.

Probieren Sie es online! (Java)

Probieren Sie es online! (Python)

Probieren Sie es online! (Wieder Java)

Dadurch werden alle leeren Zeilen beibehalten und Tabulatoren, nur Leerzeichen, werden nicht verarbeitet.

Hexdump:

00000000: 3a73 6520 7665 3d61 6c6c 7c25 2177 6320  :se ve=all|%!wc 
00000010: 2d4c 0a79 2475 f22f 5e20 2a93 5b7b 7d3b  -L.y$u./^ *.[{};
00000020: 5d0a 786b 2470 f2f2 2f84 207b 7d3b 5d5b  ].xk$p../. {};][
00000030: 7b7d 3b5d ab24 0a6c 44ee 1230 7c70       {};].$.lD..0|p

Erläuterung

Zuerst müssen wir den Cursor irgendwo im Puffer bewegen können, also verwenden wir

:se ve=all|...

und wir verketten dies mit einem anderen ex-Befehl unter Verwendung von |

Wir müssen die Länge der längsten Zeile in der Eingabe ermitteln. Dies kann mit dem Shell-Befehl erfolgen wc -L.

       ...|%!wc -L

Dies überschreibt den aktuellen Puffer (der die Eingabe enthält) mit dem Ergebnis von wc -L. Es gibt eine Ausgabe von etwas wie:

            42

und die Cursor landen auf dem 4in 42. Dann kopieren wir diese Nummer mit y$: yank text von der Cursorposition bis zum Zeilenende. Dadurch wird diese Nummer bequem im Register gespeichert 0. Aber dazu später mehr. Die Eingabe wird durch diese Nummer uersetzt.

Sagen wir nun, die Eingabe sah ungefähr so ​​aus:

public class HelloWorld{
    public static void main(String[] args){
        System.out.println("Hello, World!");
    }
}

Wir müssen die geschweiften Klammern }vom Ende des Puffers direkt nach der printlnAnweisung verschieben.

ò                  " recursively do this until a breaking error:
 /^ *<93>[{};]     "   this compressed regex becomes /^ *\zs[{};]
                   "   this finds any character from `{};` after leading spaces
                   "   the cursor then goes to the `{};`

x                  "   delete character
 k$                "   go to the end of the line above
   p               "   and paste
    ò

Wenn der reguläre Ausdruck nicht gefunden werden kann, tritt ein Unterbrechungsfehler auf und die durch verursachte Rekursion wird abgebrochen ò.

Jetzt kommt der Hauptteil dieses Programms, bewegen Sie alle Klammern und Semikolons und richten Sie sie wie in der Frage angegeben aus.

ò                  " starts recursion
 /<84> {};][{};]«$ "   compressed form of [^ {};][{};]\+$
                   "   finds a sequence of `{};`s at the end of the line with a non-`{};` char to preceding it
 l                 "   move the cursor 1 to the right (since we were on the non-`{};` char now)
  D                "   delete everything from this position to the end of line
                   "   the deleted text contains `{};`
   î               "   execute as normal commands:
    ^R0            "   contains what's in register `0`, ie the length of the longest line
       |           "   now go to the column specified by that number
        p          "   and paste the contents 
                   " implicit ending `ò`

Wieder wird diese Rekursion durch einen Unterbrechungsfehler gestoppt, der verursacht wird, wenn der reguläre Ausdruck nicht im Puffer gefunden werden konnte.

Bearbeitungen

  • Verwendet Dstatt d$(ich weiß nicht einmal, warum ich , dass in erster Linie verpasst)
  • Komprimiert [^(im regulären Ausdruck) auf<84>
  • Fehler durch Verwenden \zs(Komprimieren in <93>) und Entfernen des $In behoben$xk$pò
  • Nutzlose Newline entfernt
  • Der reguläre Ausdruck wurde geändert, um die Übermittlung an die neuen Regeln anzupassen, und es wurden 2 Byte hinzugefügt
Kritixi Lithos
quelle
Sie könnten ein Byte sparen, wenn Sie Ihre Ex-Befehle zusammenfügen:se ve=all|%!wc -L
DJMcMayhem
@DJMcMayhem Danke, TIL
Kritixi Lithos
4

Ruby, 100 114 108 Bytes

Liest den Dateinamen als Befehlszeilenargument. Wenn kein Dateiname angegeben wird, wird von STDIN gelesen. Behandelt keine Tabs.

Probieren Sie es online!

f=$<.read.gsub(/[\s;{}]*$/){$&.tr"
 ",''}
$><<f.gsub(/(.*?)([;{}]+)$/){$1.ljust(f.lines.map(&:size).max)+$2}
Wert Tinte
quelle
Funktioniert nicht damit
Pavel
@Pavel danke, dass du mich informiert hast. Die beiden Probleme, die ich nach dem Piping in die Datei sah, waren A. eine eingerückte catchAnweisung und B. ein Semikolon, das in der längsten Zeile des Codes viel zu stark eingerückt war. Ich glaube, ich weiß genau, was ich tun muss, gib mir eine Sekunde. (Außerdem habe ich die Spezifikation aktualisiert, um zu erwähnen, dass sie keine Registerkarten verarbeiten kann und Ihre Datei Registerkarten enthält.)
Value Ink
Hat es Tabs? Ich habe es gerade gefunden und ersetzt und es hat 0 Änderungen vorgenommen.
Pavel
3

Perl , 90 Bytes

88 Byte Code + -p0Flags.

\@a[y///c]for/.*/g;s/(.*?)\K[{};]$/$"x(@a-$1=~y%%%c).$&/gme;1while s/ *
 *([{};]+)$/$1/m

Probieren Sie es online!

Kurze Erklärungen:
\@a[y///c]for/.*/g; Zählt die Länge der längsten Zeile: Für jede Zeile definiert sie das Element am Index y///c(dh die Größe der Zeile) des Arrays @a. Am Ende ist der maximale Index von @a(dh die Größe von @a) die Größe der längsten Zeile.
s/(.*?)\K[{};]$/$"x(@a-$1=~y%%%c).$&/gmePlatziert die {};Zeichen am Ende der Zeilen.
1while s/ *\n *([{};]+)$/$1/mmake bewirkt, dass die geschweiften Klammern in leeren Zeilen in der darüber liegenden Zeile stehen.

Dank an @primo, von dem ich den Anfang meines Codes teilweise "gestohlen" habe , um die Länge der längsten Zeile zu zählen.

Dada
quelle
Die Streben der Linie wieder nach oben muss oben , wenn es nur Leerzeichen vor ihnen, diese Antwort nicht , dass macht
Kritixi Lithos
@KritixiLithos in der Tat, es schien in Ordnung, bevor die Herausforderung umformuliert wurde (nach dem, was ich sowohl aus den Herausforderungen als auch aus den Kommentaren verstanden habe). Wie auch immer, es ist jetzt behoben (ich hatte bereits den Code in meiner Antwort geschrieben, falls Sie es nicht bemerkt haben).
Dada
1

Python 2: 228 Bytes

import re
g=re.search
def b(a):
    s,l="",a.split('\n')
    r=max([len(k)for k in l]) 
    for k in l:
        n,m=g('[;}{]',k),g('[\w]',k)
        if n:n=n.start()
        if m:m=m.start()
        if n>m and m!=None:s+="\n"+k[:n]+" "*(r-n)
        s+=k[n:]
    print s
Chris H
quelle
Schrecklich lang. Ich hätte wahrscheinlich von vorne anfangen sollen, als mir klar wurde, dass Einzelpersonen ;{}am Ende der vorherigen Zeilen weiterarbeiten müssen.
Chris H
1

gestapelt , 133 Bytes

'\s+([;{}])' '$1'repl lines{!n'[\s;{}]+$'match''join:n\'$'+del\,}"!tr:$size"!$MAXmap@k{e i:e[' 'k i#rpad]"!}map tr[' 'join]map'
'join

Probieren Sie es online! Ich könnte das stark überdenken ... aber was auch immer. Ich werde es mir morgen noch einmal ansehen. Einige nette Tipps:

  1. "!kann oft anstelle von mapein oder zwei Bytes verwendet werden, je nachdem, ob das nächste Token mit einem Wort beginnt. Sie kann jedoch nur verwendet werden, wenn jedes Atom des Arrays abgebildet werden soll. Es ist ähnlich wie bei einer tiefen Karte.
  2. Ein Leerzeichen wird nach einer Funktion in Anführungszeichen nicht benötigt, $MAXmapist also äquivalent zu $MAX map, was wiederum äquivalent zu ist [MAX] map. (Ordnet jedes Array seinem maximalen Element zu.)
Conor O'Brien
quelle
1

JavaScript (ES-Vorschlag), 139 121 Byte

f=
s=>s.replace(/^(.*?)\s*(([;{}]\s*)+)$/gm,(_,t,u)=>t.padEnd(Math.max(...s.split`
`.map(s=>s.length)))+u.replace(/\s/g,``))
<textarea rows=10 cols=40 oninput=o.textContent=f(this.value)></textarea><pre id=o>

Benötigt Firefox 48 / Chrome 57 / Opera 44 / Safari 10 / Edge 15 für padEnd. Bearbeiten: 18 Bytes dank @ValueInk gespeichert.

Neil
quelle
Müssen Sie s.replace(r,`$1`)bei der Berechnung der Leitungslänge wirklich ausführen ? Jede Menge an vernünftigem Rechtsabstand sollte ausreichen, daher sollte das Zählen der Zeilenlänge mit den Semikolons und Klammern in Ordnung sein.
Value Ink
0

PHP, 201 194 185 172 167 Bytes

foreach($f=file(f)as$s)$x=max($x,strlen($a[]=rtrim($s,"{} ;
")));foreach($a as$i=>$c)echo str_pad($c,""<$c|!$i?$x:0),trim(substr($f[$i],strlen($c))),"
"[""==$a[$i+1]];

Übernimmt die Eingabe aus der Datei f; setzt einzeilige Zeilenumbrüche und keine Tabulatoren voraus; Bewahrt Leerzeilen.

  • +2 Byte zur Begrenzung des Leerzeichens: +1An den zweiten str_padParameter anhängen .
  • -6 Bytes, wenn garantiert wurde, dass keine Codezeile aus einem einzigen besteht 0:
    Entfernen ""<und ersetzen ""==durch !.

Nervenzusammenbruch

foreach($f=file(f)as$s)             // loop through file
    $x=max($x,strlen(                   // 3. set $x to maximum code length
        $a[]=                           // 2. append to array $a
            rtrim($s,"{} ;\n")          // 1. strip trailing whitespace and braces
    ));
foreach($a as$i=>$c)echo            // loop through $a
    str_pad($c,                         // 1. print code:
        !$i|""<$c                       // if first line or not empty
        ?$x                             // then padded to length $x
        :0                              // else unpadded (= print nothing)
    ),
    trim(substr($f[$i],strlen($c))),    // 2. print braces
    "\n"[""==$a[$i+1]]                  // 3. if next line has code, print newline
;
Titus
quelle
Sind Sie sicher, dass Sie den {}Klammern im Regex entkommen müssen?
Kritixi Lithos
@KritixiLithos Wahrscheinlich nicht; aber ich habe trotzdem einen kürzeren ansatz gefunden.
Titus
0

Java 8, 312 305 Bytes

s->{String t="([;{}]+)",z[],r="",a;s=s.replaceAll(t+"[\\s\\n]*","$1").replaceAll(t,"$1\n");int m=0,l;for(String q:s.split("\n"))m=m>(l=q.length())?m:l;for(String q:s.split("\n")){z=q.split("((?<="+t+")|(?="+t+"))",2);for(a="",l=0;l++<m-z[0].length();a+=" ");r+=z[0]+a+(z.length>1?z[1]:"")+"\n";}return r;}

Erläuterung:

Probieren Sie es hier aus.

s->{                                  // Method with String parameter and String return-type
  String t="([;{}]+)",                //  Temp regex-String we use multiple times
    z[],a,                            //  Temp String-array and temp String
    r="";                             //  Result-String
  s=s.replaceAll(t+"[\\s\\n]*","$1")  //  We replace all ;{} in the input with zero or more whitespaces/newlines to just ;{}
     .replaceAll(t,"$1\n");           //  and then add a single newline after each group of ;{}
  int m=0,l;                          //  Two temp integers
  for(String q:s.split("\n"))         //  Loop (1) over the lines
    m=m>(l=q.length())?m:l;           //   To determine the longest line
                                      //  End of loop (1)
  for(String q:s.split("\n")){        //  Loop (2) over the lines again
    z=q.split("((?<="+t+")|(?="+t+"))",2);
                                      //   Split on groups of ;{}, but keep them in the array
    for(a="",l=0;l++<m-z[0].length();a+=" "); 
                                      //   Amount of spaces we should add
    r+=z[0]+a+(z.length>1?z[1]:"")+"\n"; 
                                      //   Append this line to the result-String
  }                                   //  End of loop (2)
  return r;                           //  Return the result-String
}                                     // End of method
Kevin Cruijssen
quelle
Hey, ich kommentiere diese Antwort, aber sie trifft auf viele andere von Ihnen zu. Derzeit benötigen wir Lambda-Parameter, um Typen in Java zu haben .
Nathan Merrill
1
@ NathanMerrill hatte Angst, der Tag des Gerichts würde kommen. Jk, werde es von nun an hinzufügen und ich habe meine Antwort bearbeitet, danke. ;)
Kevin Cruijssen