Hacer mi pseudocódigo real

8

Tengo un pseudocódigo de Java que usa espacios en blanco en lugar de llaves, y quiero que lo conviertas.

I / O

Su programa debe tomar un archivo de entrada junto con un número que designe cuántos espacios se usan para sangrar un bloque. Aquí hay un ejemplo:

$ convert.lang input.p 4
// Convertir usando 4 espacios como delimitador de bloque
$ convert.lang input.p 2
// Convertir usando 2 espacios como delimitador de bloque

A continuación, debe convertir el resultado utilizando el delimitador de bloque especificado y generar el resultado en stdout.

La carne del programa.

Los bloques se abren :y cada línea dentro del bloque se sangra usando el delimitador de bloque, como el código Python.

while (verdadero):
    System.out.println ("Prueba");

Cada uno :se reemplaza con a {, y a }se agrega al final del bloque.

while (verdadero) {
    System.out.println ("Prueba");
}

Ejemplos

Entrada:

Prueba de clase pública:
    public static void main (String [] args):
        System.out.println ("Java es detallado ...");

Salida:

$ convert Test.pseudojava 4
Prueba de clase pública {
    public static void main (String [] args) {
        System.out.println ("Java es detallado ...");
    }
}

Entrada:

principal():
  printf ("Hola mundo");

Salida:

$ convert test.file 2
principal() {
  printf ("Hola mundo");
}

Entrada:

def generic_op (the_stack, func):
    # Código de manejo de operaciones genérico
    b = the_stack.pop ()
    if isinstance (b, list):
        si b:
            regreso
        top = b.pop (0)
        mientras b:
            top = func (top, b.pop (0))
        the_stack.push (arriba)
    más:
        a = the_stack.pop ()
        func de retorno (a, b)

Salida:

$ convert code.py 4
def generic_op (the_stack, func) {
    # Código de manejo de operaciones genérico
    b = the_stack.pop ()
    if isinstance (b, list) {
        si b {
            regreso
        }
        top = b.pop (0)
        mientras que b {
            top = func (top, b.pop (0))
        }
        the_stack.push (arriba)
    }
    más {
        a = the_stack.pop ()
        func de retorno (a, b)
    }
}

Puntuación

¡El código con la menor cantidad de bytes gana!

fase
fuente
1
¿Podemos suponer que la entrada no contiene comentarios?
Martin Ender
1
@ MartinBüttner Puede contener comentarios, pero los comentarios no contendrán ':'. Básicamente sí.
fase
3
¿Qué pasa con las etiquetas, que son la razón habitual por la que una línea terminaría en dos puntos en una fuente Java válida?
Peter Taylor
1
Nunca he visto una etiqueta en otra parte que no sea el comienzo de una línea.
SuperJedi224
2
Me acaban de recordar cuánto odio Java.
lirtosiast

Respuestas:

5

Perl, 41 bytes

#!perl -p0
1while s/( *).*\K:((
\1 .*)+)/ {\2
\1}/

Contando el shebang como dos, la entrada se toma de stdin. No es necesario proporcionar un argumento de línea de comando. Cualquier contexto de anidamiento válido puede determinarse (y coincidir) sin conocer el tamaño de sangría.


Desglose de expresiones regulares

( *)                   # as many spaces as possible (\1)
    .*                 # as many non-newline characters as possible \
                         (greediness ensures this will always match a full line)
      \K               # keep all that (i.e. look-behind assertion)
        :              # colon at eol (newline must be matched next)
         (
          (
           \n\1        # newline with at least one more space than the first match
                .*     # non-newlines until eol
                  )+   # as many of these lines as possible
                    )  # grouping (\2)

Uso de muestra

in1.dat

public class Test:
    public static void main(String[] args):
        System.out.println("Java is verbose...");

Salida

$ perl py2java.pl < in1.dat
public class Test {
    public static void main(String[] args) {
        System.out.println("Java is verbose...");
    }
}

in2.dat

main():
  printf("Hello World");

Salida

$ perl py2java.pl < in2.dat
main() {
  printf("Hello World");
}

in3.dat

def generic_op(the_stack, func):
    # Generic op handling code
    b = the_stack.pop()
    if isinstance(b, list):
        if b:
            return
        top = b.pop(0)
        while b:
            top = func(top, b.pop(0))
        the_stack.push(top)
    else:
        a = the_stack.pop()
        return func(a, b)

Salida

$ perl py2java.pl < in3.dat
def generic_op(the_stack, func) {
    # Generic op handling code
    b = the_stack.pop()
    if isinstance(b, list) {
        if b {
            return
        }
        top = b.pop(0)
        while b {
            top = func(top, b.pop(0))
        }
        the_stack.push(top)
    }
    else {
        a = the_stack.pop()
        return func(a, b)
    }
}
primo
fuente
Acabo de escribir esto en rubí
No es que Charles
2

Python 3, 299 265 bytes

import sys;s=int(sys.argv[2]);t="";b=0
for l in open(sys.argv[1]):
 h=l;g=0
 for c in l:
  if c!=" ":break
  g+=1
 if g/s<b:h=" "*g+"}\n"+h;b-=1
 if l.strip().endswith(":"):h=l.split(":")[0];h+=" {";b+=1
 t+=h+"\n"
b-=1
while b>-1:
 t+=" "*(b*s)+"}\n"b-=1
print(t)

Boom bam pow.

Algoritmo utilizado:

// vars globales
cadena total // programa modificado total
int b // sangrado buffer

line thru lines: // itera sobre cada línea
  string mline = "" // línea que se agregará al total

  // calcula la cantidad de espacios antes de la línea (podría ser mucho más fácil)
  espacios int = 0 // espacios totales
  c a través de la línea: // revisa todos los caracteres de la línea
    if c! = "": // si el carácter actual no es un espacio (lo que significa que los revisamos todos)
        romper // salir de iterar a través de caracteres
    espacios ++ // incrementa los espacios porque hemos golpeado un espacio (hurr derr)

  si espacios / SPACE_SETTING <b: // si el recuento de sangría de la línea actual es menor que el búfer de sangría
    mline = "} \ n" + línea // agrega el corchete de cierre al comienzo de la línea
    b-- // decremento buffer

  if line.endswith (":"): // si la línea termina con un `:`
    eliminar: de la línea
    mline + = "{" // agregar {
    b ++ // incremento de búfer
  total + = mline // agrega línea modificada al total

imprimir (total)
fase
fuente
¿Puedes incluir una explicación?
TanMath
@TanMath Agregó el algoritmo que usé
fase
¿Funciona con Python 2?
wb9688
@ wb9688 No tengo idea, solo lo probé con Python 3
fase
Acabo de probar, y funciona con Python 2
wb9688
2

Rubí, 70

x=$_+"
"
1while x.sub! /^(( *).*):
((\2 .*?
)*)/,'\1 {
\3\2}
'
$><<x

Agrega una nueva línea final. No necesita el parámetro sangrar tamaño de bloque.

Ejecute esto con -n0(esto es realmente 68 + 2). Muchas gracias a @primo por guardar más de una docena de bytes.

No es que Charles
fuente
Creo que -p0también funciona para ruby ​​( -0lee todas las entradas a la vez, -palmacena stdin $_y las imprime automáticamente al final).
primo
@primo Buen punto. En caso de que no estuviera claro con mi comentario anterior, este no es un puerto de su código, sino mi propio trabajo que hace exactamente lo que hace el suyo (pero con más bytes)
No es que Charles
Lo entendí correctamente, solo proporcioné una sugerencia para eliminar el (bastante detallado) x=$<.readlines*''. Mientras yo estoy haciendo eso, sub!también tiene una sobrecarga de dos parámetros (en lugar de un parámetro de bloque +) que acepta una cadena de reemplazo, para que pueda utilizar \1, \2, etc., en lugar de tener que concatenar todo.
primo
@primo Gracias! Probé la versión de dos parámetros antes y la abandoné en algún momento anoche.
No es que Charles