Escribe un escritor de libros

10

Aquí hay una representación ASCII bastante simple de un libro abierto:

|\
| \
|  \
|   \
|    \__________
|    ||         |
|    || Lorem i |
\    || psum do |
 \   || lor sit |
  \  ||  amet,  |
   \ || consect |
    \||_________|

Observe que la porción de texto está solo en la página derecha y tiene 7 caracteres de ancho por 5 de alto. Observe también que el borde superior del libro tiene 5 barras diagonales invertidas y 10 guiones bajos. El 10 proviene del ancho del texto más 3 y el 5 es la mitad de 10.

Utilizando el mismo formato de escala podemos cambiar el tamaño del libro que tiene un área de texto w caracteres anchos y h de altura, donde w es cualquier extraño número entero positivo y h es cualquier número entero positivo.

Algunos libros w × h : 1 × 1, 1 × 2, 3 × 2

                    |\
          |\        | \
|\        | \____   |  \______
| \____   | ||   |  |  ||     |
| ||   |  | || L |  \  || Lor |
\ || L |  \ || o |   \ || em  |
 \||___|   \||___|    \||_____|

El número de guiones bajos en la parte superior siempre es w +3 y el número de barras invertidas siempre es ( w +3) / 2.

Objetivo

Escriba un programa que tome un nombre de archivo yw y h como argumentos de línea de comando, y muestre un libro con esas dimensiones de texto en stdout, mostrando el contenido del archivo.

Cuando el archivo tiene más texto del que cabe en una página, la Nclave debe imprimir la página siguiente y Bdebe retroceder una página. No debe suceder nada si Bse presiona desde la primera página o si Nse presiona desde la última página. El programa debe detenerse cuando se Qpresiona la tecla.

Ejemplo

Supongamos que f.txtcontiene Lorem ipsum dol?y el usuario ha presionado la secuencia de teclas N N B N N Q. El programa debería ejecutar algo como esto:

>>> bookmaker f.txt 3 2
|\
| \
|  \______
|  ||     |
\  || Lor |
 \ || em  |
  \||_____|

|\
| \
|  \______
|  ||     |
\  || ips |
 \ || um  |
  \||_____|

|\
| \
|  \______
|  ||     |
\  || dol |
 \ || ?   |
  \||_____|

|\
| \
|  \______
|  ||     |
\  || ips |
 \ || um  |
  \||_____|

|\
| \
|  \______
|  ||     |
\  || dol |
 \ || ?   |
  \||_____|

>>>

Observe que hay una nueva línea después de cada libro y no hay espacios finales. Esto es requerido.

Notas

  • Puede suponer que el archivo solo contiene caracteres ASCII imprimibles (hexadecimal 20 a 7E).
  • Imprima un carácter en cada lugar disponible, independientemente de los límites de las palabras.
  • w y h son argumentos opcionales que por defecto son 7 y 5 respectivamente. Su programa recibirá ninguno o ambos. (Puede suponer que la entrada siempre está bien formada).
  • Rellene cualquier espacio de texto vacío en la última página con espacios.
  • Q aún se debe exigir que salga si solo hay una página.

Victorioso

El programa más corto en bytes después de aplicar los bonos gana.

Bonos

  • Elimine los espacios iniciales para que cada línea comience con una palabra (o segmento de palabra). por ejemplo, | amet, |en el primer ejemplo se convertiría | amet, c |. (-30 bytes)
  • Despeje la pantalla de los libros dibujados previamente después No Bse presione (y Tsi hace la bonificación después de esto) para que el libro se vea como si sus páginas cambiaran en su lugar. (-20 bytes)
  • Haga que la Ttecla cambie instantáneamente entre el texto que se dibuja de izquierda a derecha de arriba a abajo (el valor predeterminado), de arriba a abajo de izquierda a derecha. Si hiciste la primera bonificación, debería funcionar para las columnas en el modo de arriba a abajo. (-100 bytes)

    Así por ejemplo:

    |\
    | \
    |  \______
    |  ||     |
    \  || Lor |
     \ || em  |
      \||_____|
    

    se convierte

    |\
    | \
    |  \______
    |  ||     |
    \  || Lrm |
     \ || oe  |
      \||_____|
    
Pasatiempos de Calvin
fuente
el bono "borrar la pantalla" parece ser un bono lenguaje en lugar de un código de bono ...
John Dvorak
Usted dice en el texto que el nombre del archivo y las dimensiones del libro provienen de STDIN, pero luego procede a tomarlos como argumentos. ¿Cuál es entonces?
John Dvorak
He notado, gracias a su aviso, que no hay espacios finales. ¿Pero estamos obligados a no incluirlos tampoco?
John Dvorak
@ JanDvorak Lo siento, quise decir que son solo argumentos. No necesita tener espacios finales. ¿Puede dar un ejemplo de dónde la compensación se convierte en un "bono de código"?
Aficiones de Calvin
1
@ JanDvorak, me parece más una bonificación de "ejecutar el programa en un terminal POSIX". \033[2J\033[;H
Peter Taylor

Respuestas:

3

C # 535bytes

El puntaje es 655bytes de código -20byte de bonificación para borrar, y -100byte de bonificación para la tecla T ... Creo que no puedo decir que estoy seguro de que no me he perdido algo en la especificación

Puedo intentar colapsar los bucles haciendo que el método W devuelva el argumento s, pero eso requeriría esfuerzo, por lo que no hay promesas.

Código de golf:

using C=System.Console;using K=System.ConsoleKey;class P{static void W(int x,int y,string s){C.SetCursorPosition(x,y);C.Write(s);}static void Main(string[]a){int b=a.Length,w=b>0?int.Parse(a[0]):7,h=b>1?int.Parse(a[1]):5,p=0,i,j,o,T=1;var F=System.IO.File.ReadAllText("f.txt");b=(w+3)/2;S:C.Clear();for(i=0;i<w+3;i++){W(o=i+b+1,b-1,"_");W(o,h+b+1,"_");}for(i=0;i<h+2;){W(0,i,"|");W(b,o=i+++b,"||");W(b+w+4,o,"|");}for(i=0;i<b;){W(i+1,i,"\\");W(i,++i+h+1,"\\");}for(i=0;i<w;i++)for(j=0;j<h;)if((o=T>0?j++*w+p+i:i*h+p+j++)<F.Length)W(i+b+3,j+b,F[o]+"");K k=C.ReadKey(1>0).Key;p+=k==K.N&p<F.Length-w*h?w*h:k==K.B&p>0?-w*h:0;T=k!=K.T?T:-T;if (k!=K.Q)goto S;}}

Formateado un poco:

using C=System.Console;
using K=System.ConsoleKey;

class P
{
    static void W(int x,int y,string s)
    {
        C.SetCursorPosition(x,y);
        C.Write(s);
    }

    static void Main(string[]a)
    {
        int b=a.Length,w=b>0?int.Parse(a[0]):7,h=b>1?int.Parse(a[1]):5,p=0,i,j,o,T=1;
        var F=System.IO.File.ReadAllText("f.txt");
        b=(w+3)/2;

    S:
        C.Clear();

        for(i=0;i<w+3;i++)
        {
            W(o=i+b+1,b-1,"_");
            W(o,h+b+1,"_");
        }

        for(i=0;i<h+2;)
        {
            W(0,i,"|");
            W(b,o=i+++b,"||");
            W(b+w+4,o,"|");
        }

        for(i=0;i<b;)
        {
            W(i+1,i,"\\");
            W(i,++i+h+1,"\\");
        }

        for(i=0;i<w;i++)
            for(j=0;j<h;)
                if((o=T>0?j++*w+p+i:i*h+p+j++)<F.Length)
                    W(i+b+3,j+b,F[o]+"");

        K k=C.ReadKey(1>0).Key;
        p+=k==K.N&p<F.Length-w*h?w*h:k==K.B&p>0?-w*h:0;
        T=k!=K.T?T:-T;
        if (k!=K.Q)
            goto S;
    }
}
VisualMelon
fuente
4

Java, 1039 1001 993 953 946

Con bonificación: Eliminar espacios iniciales (-30 bytes) -> 1009 971 963 923 916

Limpiar la pantalla no vale la pena con Java (excepto si solo imprimo un par de líneas nuevas. Pero entonces el usuario tiene que usar el tamaño de consola correcto)

Código:

import java.io.*;import java.util.*;class B {static int w=7,h=5,p,l;static String t="",o,u=" ",y="\\";public static void main(String[]c)throws Exception{if(c.length>1){w=Integer.valueOf(c[1]);h=Integer.valueOf(c[2]);}Scanner s=new Scanner(new FileReader(c[0]));while(s.hasNext()){t+=s.nextLine();}l=t.length();s = new Scanner(System.in);while(true){int q=w+3,z=q/2,i=0,j=0,a=w*h;o="";for(;i<z;i++)o+="\n|"+r(u,i)+y;o+=r("_", q);for(;j<h+2-z;j++){o+="\n|"+r(u,i-1)+"||";if(j==0)o+=r(u,w+2);else o+=u+t()+u;o+="|";}for(;i>0;i--){o+="\n"+r(u,z-i)+y+r(u,i-1)+"||";if(i>1)o+=u+t()+" |";}o+=r("_",w+2)+"|";System.out.print(o);switch(s.next().charAt(0)){case'Q':return;case'B':p=p>a?p-2*a:p-a;break;case'N':p=p>l?p-a:p;}}}static String t(){int e=p+w>l?l:p+w;String r="";if(p<=e)r=t.substring(p,e);r=r.replaceAll("^\\s+","");int y=r.length();p+=w;return y==w?r:r+r(u,w-y);}static String r(String s,int i){return new String(new char[i]).replace("\0",s);}

Bonita:

import java.io.*;import java.util.*;
class B {
    static int w=7,h=5,p,l; // w = text width, h = text height, p = current position in text
    static String t="",o,u=" ",y="\\";
    public static void main(String[]c)throws Exception{
        // get w and h of text, default to 7x5
        if(c.length>1){w=Integer.valueOf(c[1]);h=Integer.valueOf(c[2]);}
        // read file
        Scanner s=new Scanner(new FileReader(c[0]));while(s.hasNext()){t+=s.nextLine();}         
        l=t.length();
        // read input
        s = new Scanner(System.in);
        while(true){
            // print book
        int q=w+3,z=q/2,i=0,j=0,a=w*h; // q = number of underscores at the top, z = number of backslashes
        o="";
        // print top of book
        for(;i<z;i++)o+="\n|"+r(u,i)+y;
        o+=r("_", q);
        // print middle of book (hp-z lines). right now: i = z -1
        for(;j<h+2-z;j++){o+="\n|"+r(u,i-1)+"||";if(j==0)o+=r(u,w+2);else o+=u+t()+u;o+="|";}
        // print bottom of book
        for(;i>0;i--){o+="\n"+r(u,z-i)+y+r(u,i-1)+"||";if(i>1)o+=u+t()+" |";}
        o+=r("_",w+2)+"|";
        System.out.print(o);
        // user input
            switch(s.next().charAt(0)){                
                case'Q':return;
                case'B':p=p>a?p-2*a:p-a;break;
                case'N':p=p>l?p-a:p;
            }
        }       
    }

    /** return w characters of string t, from given position p. increase p*/
    static String t(){
        int e=p+w>l?l:p+w;
        String r="";        
        if(p<=e)r=t.substring(p,e);
        r=r.replaceAll("^\\s+",""); // remove leading spaces (cost:28 chars)
        int y=r.length();
        p+=w;
        return y==w?r:r+r(u,w-y);
    }
    static String r(String s,int i){return new String(new char[i]).replace("\0",s);} // repeat given string i times

Si el programa no tiene que ejecutarse para siempre, también podría guardar algunos bytes eliminando el bucle while y simplemente llamando a main.

Esto no es óptimo, pero es un comienzo.

tim
fuente
Estoy bastante seguro de que no necesita las publicpalabras clave ... Además, ¿ import java.*;funciona?
También pensé en @professorfish import java.*;, pero no funciona. Y el método principal debe ser exactamente public static void main(String[]c)(incluido public), de lo contrario no se reconoce. Pero la clase, por supuesto, no necesita ser pública, buena captura.
tim