Convierte los brackets en Brace derecho (Brace triste)

26

La llave de la derecha es un estilo de horquillado de código en el que las llaves y los puntos y comas están todos alineados en un solo punto en el lado derecho de un archivo.

Imagen de ejemplo ir aquí

En general, esto se considera una mala práctica, por varias razones.

El reto

Tome una cadena multilínea a través de cualquier método y convierta su estilo de llave en Brace derecho.

Para este desafío, solo necesita que funcione en código Java, sin embargo, en teoría debería funcionar en cualquier código que use llaves y puntos y comas.

Debe tomar todos los {};caracteres en una fila, con cualquier cantidad de espacio en blanco entre ellos. P.EJ. }}, ; } }\n\t\t}y alinearlos en el lado derecho del archivo mediante el uso de espacios en blanco.

por ejemplo:

a {
b;
{c

debe convertirse

a {
b ;{
c

O, de manera más abstracta, empuje todos los espacios en blanco desde la izquierda de todos los {};caracteres, hacia la derecha.

La sangría de las líneas debe conservarse de otra manera. Las líneas que solo contienen espacios en blanco después del movimiento de los {};caracteres pueden eliminarse opcionalmente.

Por ejemplo:

a{
    b{
        c;
    }
}
d;

Puede convertirse en cualquiera

a        {
    b    {
        c;}}
d        ;

o

a        {
    b    {
        c;}}


d        ;

Empujado a la derecha se refiere a todos los {};caracteres que se alinean a un punto no más corto que la línea más larga. Cualquier cantidad de espacio después de eso es aceptable.

Entonces todo lo siguiente es aceptable:

a {
bc;

a  {
bc ;

a   {
bc  ;

etc ...

Las líneas en cualquier código pueden contener {};caracteres entre otros caracteres que no sean espacios en blanco, el manejo de este caso no es necesario, aunque si está inclinado, debe dejarlos en su lugar. Las líneas también pueden no contener ningún {};carácter, y esto debe manejarse correctamente. Como se muestra a continuación.

a {
b ;
c
d }

Debido a que no queremos que Code Review vea las cosas horribles que estamos haciendo, debe hacer que su código sea lo más pequeño posible.

Ejemplos / Casos de prueba

Java genérico

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

se convierte en ...

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

La imagen en sí

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

se convierte en ...

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 no tan perfectamente genérico

Por contraste

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

Main();

se convierte en ...

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

Notas

  • Se aplican lagunas estándar
  • Se aplica el estándar IO
  • Este es el , por lo que gana el programa más corto en bytes.
  • No soy responsable de los daños relacionados con la programación en el estilo de llave de mano derecha
  • ¡Que te diviertas!

Editar notas

Reescribí los detalles del desafío. Espero no haber roto la visión de las reglas de nadie, les aseguro que no fue intencional. Esta debería ser una especificación mucho más clara y menos conflictiva.

Un taco
fuente
¿Cuál es el veredicto en líneas con varios puntos y comas? Algo comoint a=0;System.out.println(a);
Value Ink
2
Esa podría no ser la mejor imagen para el desafío si no necesitamos manejar bucles como en la imagen de muestra.
Dennis
1
Parece que la imagen en la pregunta proviene de este ejemplo , que fue seguido por este seguimiento , que tiene ejemplos más complejos
Ray Toal
2
Podría aclararse que desea que los ;{}caracteres se reúnan si están en líneas separadas (solo está claro en el ejemplo, no en las reglas, y de hecho si una línea consiste en \t}preservar la sangría significaría no moverse }hasta el final de la línea anterior)
Chris H
2
Dios mío, dime que en realidad nadie hace esto en la práctica para un lenguaje detallado como Java ._.
Urna mágica del pulpo

Respuestas:

5

Utilidades V + Bash, 64 62 61 60 62 bytes

1 byte guardado gracias a @DJMcMayhem por juntar los comandos ex

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

^Res el carácter literal de <C-r>( 0x12) y <84>es 0x84y <94>es 0x94.

wc -Lfunciona en la mayoría de los sistemas basados ​​en * nix, pero no en macOS. Para macOS, debe hacerlo gwc -L después de obtener coreutils usando brew, si aún no lo ha hecho.

Pruébalo en línea! (Java)

Pruébalo en línea! (Pitón)

Pruébalo en línea! (Java de nuevo)

Esto conserva todas las líneas en blanco y no maneja pestañas, solo espacios.

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

Explicación

Primero necesitamos poder mover el cursor a cualquier parte del búfer, así que usamos

:se ve=all|...

y encadenamos esto con otro comando ex usando |

Necesitamos obtener la longitud de la línea más larga en la entrada. Esto se puede hacer con el comando de shell wc -L.

       ...|%!wc -L

Esto sobrescribe el búfer actual (que contiene la entrada) con el resultado de wc -L. Da una salida de algo como:

            42

y el cursor se posa en el 4en 42. Luego copiamos este número usando y$: tirar el texto desde la posición del cursor hasta el final de la línea. Esto almacena convenientemente este número en el registro 0. Pero más sobre eso más tarde. La entrada se reemplaza con este número, así que para volver atrás, hacemos u.

Ahora digamos que la entrada se parecía a esto:

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

necesitamos mover las llaves }desde el final del búfer hasta justo después de la printlndeclaración.

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

Si no se puede encontrar la expresión regular, se produce un error de ruptura y se libera de la recursión causada por ò.

Ahora viene la parte principal de este programa, mueva todas las llaves y punto y coma y alinéelos como se indica en la pregunta.

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

Nuevamente, esta recursión se detendrá por un error de ruptura causado cuando no se pudo encontrar la expresión regular en el búfer.

Ediciones

  • Usado en Dlugar de d$(ni siquiera sé por qué me perdí eso en primer lugar)
  • Comprimido [^(en la expresión regular) a<84>
  • Se corrigió el error al usar \zs(comprimirlo <93>) y al eliminar el $in$xk$pò
  • Se eliminó la línea nueva inútil
  • Se modificó la expresión regular para que el envío sea compatible con las nuevas reglas y ganó 2 bytes
Kritixi Lithos
fuente
Podría guardar un byte si une sus comandos ex juntos:se ve=all|%!wc -L
DJMcMayhem
@DJMcMayhem Gracias, TIL
Kritixi Lithos
4

Ruby, 100 114 108 bytes

Lee el nombre del archivo como argumento de línea de comando. Si no se proporciona ningún nombre de archivo, se leerá desde STDIN. No maneja pestañas.

Pruébalo en línea!

f=$<.read.gsub(/[\s;{}]*$/){$&.tr"
 ",''}
$><<f.gsub(/(.*?)([;{}]+)$/){$1.ljust(f.lines.map(&:size).max)+$2}
Tinta de valor
fuente
@Pavel prueba esto por tamaño.
Value Ink
No funciona con esto
Pavel
@Pavel gracias por hacérmelo saber. Los dos problemas que vi después de pasar al archivo fueron A. una catchdeclaración con sangría y B. un punto y coma que estaba demasiado sangrado, en la línea más larga del código. Creo que sé exactamente lo que necesito para solucionarlo, dame un segundo. (Además, actualicé la especificación para mencionar que no puede manejar pestañas, y su archivo tiene pestañas.)
Value Ink
¿Tiene pestañas? Acabo de encontrar y reemplazar en él, e hizo 0 cambios.
Pavel
3

Perl , 90 bytes

88 bytes de código + -p0banderas.

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

Pruébalo en línea!

Explicaciones breves:
\@a[y///c]for/.*/g; cuenta la longitud de la línea más larga: para cada línea, define el elemento en el índice y///c(es decir, el tamaño de la línea) de la matriz @a. Al final, el índice máximo de @a(es decir, el tamaño de @a) es el tamaño de la línea más larga.
s/(.*?)\K[{};]$/$"x(@a-$1=~y%%%c).$&/gmecoloca los {};caracteres al final de las líneas.
1while s/ *\n *([{};]+)$/$1/mmakes hace que las llaves en las líneas vacías vayan en la línea de arriba

Gracias a @primo de quien parcialmente "robé" el comienzo de mi código desde aquí para contar la longitud de la línea más larga.

Dada
fuente
Las llaves deben volver a la línea de arriba si solo hay espacios en blanco delante de ellos, esta respuesta no hace eso
Kritixi Lithos
@KritixiLithos, de hecho, parecía bien antes de que el desafío fuera redactado nuevamente (por lo que entendí tanto de los desafíos como de los comentarios). De todos modos, ahora está arreglado (ya tenía el código escrito en mi respuesta en caso de que no lo notara).
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
fuente
Horriblemente largo. Probablemente debería haber comenzado desde cero cuando me di cuenta de que era ;{}necesario ir solo al final de las líneas anteriores.
Chris H
1

apilado , 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

Pruébalo en línea! Podría estar pensando demasiado en esto ... pero lo que sea. Lo miraré de nuevo mañana. Algunos buenos consejos:

  1. "!a menudo se puede usar en lugar de mapguardar un byte o dos, dependiendo de si el próximo token comienza con una palabra. Sin embargo, solo se puede usar cuando cada átomo de la matriz desea mapearse. Es similar a un mapa profundo.
  2. No se necesita un espacio después de una función entre comillas, por lo que $MAXmapes equivalente a $MAX map, que a su vez es equivalente a [MAX] map. (Asigna cada matriz a su elemento máximo).
Conor O'Brien
fuente
1

JavaScript (Propuesta ES), 139 121 bytes

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>

Requiere Firefox 48 / Chrome 57 / Opera 44 / Safari 10 / Edge 15 para padEnd. Editar: guardado 18 bytes gracias a @ValueInk.

Neil
fuente
¿Realmente necesitas correr s.replace(r,`$1`)al calcular la longitud de la línea? Cualquier cantidad de relleno derecho razonable debería ser suficiente, por lo que contar la longitud de la línea con punto y coma y corchetes debería estar bien.
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]];

toma la entrada del archivo f; asume saltos de línea de un solo byte y sin pestañas; conserva líneas en blanco.

  • +2 bytes para delimitar espacios en blanco: agregar +1al segundo str_padparámetro.
  • -6 bytes si se garantiza que ninguna línea de código consta de una sola 0:
    eliminar ""<y reemplazar ""==con !.

Descompostura

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
fuente
¿Estás seguro de que necesitas escapar de las {}llaves en la expresión regular?
Kritixi Lithos
@KritixiLithos Probablemente no; pero encontré un enfoque más corto de todos modos.
Tito
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;}

Explicación:

Pruébalo aquí

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
fuente
Oye, estoy comentando esta respuesta, pero se aplica a muchos otros tuyos. Actualmente requerimos parámetros lambda para tener tipos en Java .
Nathan Merrill
1
@NathanMerrill temía que llegara el día del juicio. Jk, lo agregaré de ahora en adelante y he editado mi respuesta, gracias. ;)
Kevin Cruijssen