Converti le parentesi graffe in parentesi graffa destra (Sad Brace)


26

La parentesi graffa destra è uno stile di parentesi graffe di codice in cui parentesi graffe e punti e virgola sono tutti allineati a un singolo punto sul lato destro di un file.

Immagine di esempio vai qui

In generale, questa è considerata una cattiva pratica, per diversi motivi.

La sfida

Prendi una stringa multilinea con qualsiasi metodo e converti il ​​suo stile di controvento in Rinforzo a destra.

Per questa sfida, è necessario che funzioni solo sul codice Java, tuttavia, teoricamente dovrebbe funzionare su qualsiasi codice che utilizza parentesi graffe e punti e virgola.

Devi prendere tutti i {};personaggi di fila, con una quantità di spazio tra di loro. PER ESEMPIO. }}, ; } }\n\t\t}e allineali sul lato destro del file mediante l'uso di spazi bianchi.

per esempio:

a {
b;
{c

dovrebbe diventare

a {
b ;{
c

O, più astrattamente, spingi tutti gli spazi bianchi dalla sinistra di tutti i {};personaggi, a destra.

Il rientro delle righe dovrebbe essere altrimenti preservato. Le linee che contengono spazi bianchi solo dopo il movimento dei {};personaggi possono essere rimosse facoltativamente.

Per esempio:

a{
    b{
        c;
    }
}
d;

Può diventare neanche

a        {
    b    {
        c;}}
d        ;

o

a        {
    b    {
        c;}}


d        ;

Spinto a destra si riferisce a tutti i {};caratteri allineati a un punto non più corto della linea più lunga. Qualsiasi quantità di spazio dopo è accettabile.

Quindi tutto il seguito è accettabile:

a {
bc;

a  {
bc ;

a   {
bc  ;

eccetera...

Le righe in qualsiasi codice possono contenere {};caratteri tra altri caratteri non di spazi bianchi, la gestione di questo caso non è necessaria, anche se se sei propenso, dovresti lasciarli in posizione. Le righe potrebbero inoltre non contenere alcun {};carattere e questo dovrebbe essere gestito correttamente. Come mostrato di seguito.

a {
b ;
c
d }

Poiché non vogliamo che Code Review veda le cose orribili che stiamo facendo, devi rendere il tuo codice il più piccolo possibile.

Esempi / Testcase

Java generico

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

diventa ...

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

L'immagine stessa

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

diventa ...

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

Python non così perfettamente generico

Per contrasto

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

Main();

diventa ...

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

Gli appunti

  • Si applicano scappatoie standard
  • Si applica l' IO standard
  • Questo è , quindi vince il programma più breve in byte!
  • Non sono responsabile per i danni relativi alla programmazione nello stile del braccio destro
  • Divertiti!

Modifica note

Ho riformulato i dettagli della sfida, spero di non aver infranto la visione delle regole da parte di nessuno, ti assicuro che non era intenzionale. Questa dovrebbe essere una specifica molto più chiara e meno auto-conflittuale.


Qual è il verdetto sulle righe con più punti e virgola? Qualcosa di simileint a=0;System.out.println(a);
Value Ink

2
Potrebbe non essere la migliore immagine per la sfida se non abbiamo bisogno di gestire loop come nell'immagine di esempio?
Dennis,

1
Sembra che l'immagine nella domanda provenga da questo esempio , che è stato seguito da questo follow-up , che ha esempi più complessi
Ray Toal,

2
Potrebbe essere più chiaro che vuoi che i ;{}personaggi siano raccolti se sono su righe separate (è chiaro solo dall'esempio, non dalle regole, e infatti se una riga consiste nel \t}preservare il rientro significherebbe non spostarsi }fino alla fine della riga precedente)
Chris H,

2
Buon Dio, per favore, dimmi che nessuno lo fa in pratica per un linguaggio prolisso come Java ._.
Magic Octopus Urn,

Risposte:


5

Utilità V + Bash, 64 62 61 60 62 byte

1 byte salvato grazie a @DJMcMayhem per mettere insieme i comandi ex

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

^Rè il carattere letterale di <C-r>( 0x12) ed <84>è 0x84ed <94>è 0x94.

wc -Lfunziona sulla maggior parte dei sistemi basati su * nix, ma non su macOS. Per macOS, devi farlo gwc -L dopo aver ottenuto coreutils usando brew, se non l'hai già fatto.

Provalo online! (Giava)

Provalo online! (Pitone)

Provalo online! (Di nuovo Java)

Ciò preserva tutte le righe vuote e non gestisce le schede, ma solo gli spazi.

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

Spiegazione

Per prima cosa dobbiamo essere in grado di spostare il cursore in qualsiasi punto del buffer, quindi usiamo

:se ve=all|...

e lo concateniamo con un altro comando ex usando |

Dobbiamo ottenere la lunghezza della linea più lunga nell'input. Questo può essere fatto con il comando shell wc -L.

       ...|%!wc -L

Questo sovrascrive il buffer corrente (contenente l'input) con il risultato di wc -L. Dà un output di qualcosa come:

            42

e il cursore atterra sul 4a 42. Quindi copiamo questo numero usando y$: yank il testo dalla posizione del cursore alla fine della riga. Questo memorizza comodamente questo numero nel registro 0. Ma ne parleremo più avanti. L'input viene sostituito con questo numero, quindi per tornare indietro, non lo facciamo u.

Ora supponiamo che l'input sia in qualche modo simile a questo:

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

dobbiamo spostare le parentesi graffe }dalla fine del buffer a subito dopo l' printlnistruzione.

ò                  " 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
    ò

Se non è possibile trovare la regex, si verifica un errore di interruzione che si interrompe dalla ricorsione causata da ò.

Ora arriva la parte principale di questo programma, sposta tutte le parentesi graffe e i punti e virgola e allinearli come indicato nella domanda.

ò                  " 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 `ò`

Ancora una volta, questa ricorsione sarà interrotta da un errore di rottura causato quando il regex non è stato trovato nel buffer.

Le modifiche

  • Usato al Dposto di d$(non so nemmeno perché l'ho perso in primo luogo)
  • Compresso [^(nella regex) in<84>
  • Bug risolto usando \zs(comprimendolo in <93>) e rimuovendo $in$xk$pò
  • Newline inutile rimosso
  • Modificato regex per rendere l'invio conforme alle nuove regole e guadagnato 2 byte

Puoi salvare un byte se unisci i tuoi comandi ex:se ve=all|%!wc -L
DJMcMayhem

@DJMcMayhem Grazie, TIL
Kritixi Lithos,

4

Rubino, 100 114 108 byte

Legge il nome del file come argomento della riga di comando. Se non viene fornito alcun nome file, verrà letto da STDIN. Non gestisce le schede.

Provalo online!

f=$<.read.gsub(/[\s;{}]*$/){$&.tr"
 ",''}
$><<f.gsub(/(.*?)([;{}]+)$/){$1.ljust(f.lines.map(&:size).max)+$2}



Non funziona con questo
Pavel

@ Grazie grazie per avermelo fatto notare. I due problemi che ho riscontrato dopo aver eseguito il piping nel file erano A. un'istruzione rientrata catche B. un punto e virgola che era troppo rientrato, sulla riga più lunga del codice. Penso di sapere esattamente ciò di cui ho bisogno per sistemarlo, dammi un secondo. (Inoltre, ho aggiornato le specifiche per menzionare che non è in grado di gestire le schede e il tuo file ha schede.)
Value Ink

Ha le schede? Ho appena trovato e sostituito e ha apportato 0 modifiche.
Pavel,

3

Perl , 90 byte

88 byte di codice + -p0flag.

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

Provalo online!

Spiegazioni brevi:
\@a[y///c]for/.*/g; conta la lunghezza della linea più lunga: per ogni linea, definisce l'elemento all'indice y///c(cioè la dimensione della linea) dell'array @a. Alla fine, l'indice massimo di @a(cioè la dimensione di @a) è la dimensione della linea più lunga.
s/(.*?)\K[{};]$/$"x(@a-$1=~y%%%c).$&/gmeposiziona i {};personaggi alla fine delle linee.
1while s/ *\n *([{};]+)$/$1/mrende le parentesi graffe su linee vuote andare sulla riga sopra.

Grazie a @primo da cui ho parzialmente "rubato" l'inizio del mio codice da qui per contare la lunghezza della linea più lunga.


Le parentesi graffe devono risalire alla riga sopra se c'è solo spazio prima di loro, questa risposta non lo fa
Kritixi Lithos

@KritixiLithos, in effetti, è sembrato giusto prima che la sfida fosse riformulata (da quello che ho capito sia dalle sfide che dai commenti). Ad ogni modo, ora è stato risolto (avevo già scritto il codice nella mia risposta nel caso non l'avessi notato).
Dada,

1

Python 2: 228 byte

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

Orribilmente lungo. Probabilmente avrei dovuto ricominciare da capo quando mi sono reso conto che i soli ;{}dovevano andare alla fine delle righe precedenti.
Chris H,

1

impilato , 133 byte

'\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

Provalo online! Potrei pensare troppo a questo ... ma non è così. Lo guarderò di nuovo domani. Alcuni consigli utili:

  1. "!può spesso essere usato al posto di map, salvando un byte o due, a seconda che il token successivo inizi con una parola. Tuttavia, può essere utilizzato solo quando ciascun atomo dell'array desidera essere mappato. È simile a una mappa profonda.
  2. Uno spazio non è necessario dopo una funzione quotata, quindi $MAXmapè equivalente a $MAX map, che a sua volta è equivalente a [MAX] map. (Mappa ogni array sul suo elemento massimo.)

1

JavaScript (proposta ES), 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>

Richiede Firefox 48 / Chrome 57 / Opera 44 / Safari 10 / Edge 15 per padEnd. Modifica: salvato 18 byte grazie a @ValueInk.


Hai davvero bisogno di correre s.replace(r,`$1`)quando calcoli la lunghezza della linea? Qualsiasi quantità di ragionevole riempimento a destra dovrebbe essere sufficiente, quindi contare la lunghezza della linea con i punti e virgola e le parentesi dovrebbe andare bene.
Value Ink

0

PHP, 201 194 185 172 167 byte

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]];

accetta l'input dal file f; presuppone interruzioni di riga a byte singolo e nessuna scheda; conserva le righe vuote.

  • +2 byte per la delimitazione degli spazi bianchi: aggiungi +1al secondo str_padparametro.
  • -6 byte se è stato garantito che nessuna riga di codice è costituita da un singolo 0:
    Rimuovi ""<e sostituisci ""==con !.

abbattersi

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
;

Sei sicuro di dover sfuggire alle {}parentesi graffe nella regex?
Kritixi Lithos,

@KritixiLithos Probabilmente no; ma ho trovato comunque un approccio più breve.
Tito

0

Java 8, 312 305 byte

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

Spiegazione:

Provalo qui.

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

Ehi, sto commentando questa risposta, ma si applica a molti altri tuoi. Al momento abbiamo bisogno dei parametri lambda per avere tipi in Java .
Nathan Merrill,

1
@NathanMerrill Temeva che sarebbe arrivato il giorno del giudizio. Jk, lo aggiungerò d'ora in poi e ho modificato la mia risposta, grazie. ;)
Kevin Cruijssen il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.