Scrivi uno scrittore di libri


10

Ecco una rappresentazione ASCII abbastanza semplice di un libro aperto:

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

Si noti che la parte di testo è solo sulla pagina giusta ed è larga 7 caratteri per 5 di altezza. Nota anche che il bordo superiore del libro ha 5 barre rovesciate e 10 caratteri di sottolineatura. Il 10 viene dalla larghezza del testo più 3 e il 5 è la metà di 10.

Utilizzando lo stesso formato di scala possiamo ridimensionare il libro di avere un'area di testo w caratteri di larghezza e h alta, dove w è un qualsiasi dispari numero intero positivo e h è un qualsiasi numero intero positivo.

Alcuni libri w × h : 1 × 1, 1 × 2, 3 × 2

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

Il numero di trattini bassi in alto è sempre w +3 e il numero di barre rovesciate è sempre ( w +3) / 2.

Obbiettivo

Scrivere un progamma che prende un nome di file e w e h come argomenti della riga di comando, ed emette un libro con quelle dimensioni di testo a stdout, che visualizza il contenuto del file.

Quando il file ha più testo di quello che si adatta a una pagina, il Ntasto dovrebbe stampare la pagina successiva e Bdovrebbe tornare indietro di una pagina. Non dovrebbe succedere nulla se Bviene premuto dalla prima pagina o Ndall'ultima pagina. Il programma dovrebbe fermarsi quando si Qpreme il tasto.

Esempio

Supponiamo che f.txtcontenga Lorem ipsum dol?e l'utente abbia premuto la sequenza di tasti N N B N N Q. Il programma dovrebbe eseguire qualcosa del genere:

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

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

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

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

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

>>>

Nota che c'è una nuova riga dopo ogni libro e nessuno spazio finale. Questo è richiesto

Appunti

  • Si può presumere che il file contenga solo caratteri ASCII stampabili (esadecimale da 20 a 7E).
  • Stampa un carattere in ogni punto disponibile, indipendentemente dai limiti delle parole.
  • w e h sono argomenti opzionali predefiniti rispettivamente a 7 e 5. Il tuo programma non verrà fornito né in entrambi né in entrambi. (Si può presumere che l'input sia sempre ben formato.)
  • Riempi qualsiasi spazio di testo vuoto nell'ultima pagina con spazi.
  • Q dovrebbe comunque essere richiesto di uscire se esiste solo una pagina.

vincente

Vince il programma più breve in byte dopo l'applicazione dei bonus.

bonus

  • Rimuovi gli spazi iniziali in modo che ogni riga inizi con una parola (o segmento di parole). ad esempio | amet, |nel primo esempio diventerebbe | amet, c |. (-30 byte)
  • Cancella lo schermo dei libri precedentemente disegnati dopo No Bviene premuto (e Tse fai il bonus dopo questo) in modo che il libro sembri cambiare le pagine in atto. (-20 byte)
  • Fai in modo che la Tchiave passi istantaneamente tra il testo disegnato da sinistra a destra dall'alto verso il basso (impostazione predefinita), dall'alto verso il basso da sinistra a destra. Se hai fatto il primo bonus, dovrebbe funzionare per le colonne nella modalità dall'alto verso il basso. (-100 byte)

    Quindi per esempio:

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

    diventa

    |\
    | \
    |  \______
    |  ||     |
    \  || Lrm |
     \ || oe  |
      \||_____|
    

il bonus "cancella lo schermo" sembra essere un bonus di lingua piuttosto che un bonus di codice ...
John Dvorak

Dici nel testo che il nome del file e le dimensioni del libro provengono da STDIN, ma poi procedi a prenderli come argomenti. Cos'è allora?
John Dvorak,

Ho notato, grazie al tuo avviso, che non ci sono spazi finali. Ma dobbiamo anche non includerli?
John Dvorak,

@JanDvorak Siamo spiacenti, volevo dire che sono solo argomenti. Non devi avere spazi finali. Puoi fare un esempio di dove la compensazione diventa un "bonus di codice"?
Calvin's Hobbies,

1
@JanDvorak, mi sembra più un bonus "esegui il programma in un terminale POSIX". \033[2J\033[;H
Peter Taylor,

Risposte:


3

C # 535 byte

Il punteggio è 655 byte di codice bonus di -20 byte per la cancellazione e bonus di -100 byte per il tasto T ... Penso, non posso dire di essere sicuro di non aver perso qualcosa nelle specifiche

Potrei provare a far collassare i loop facendo in modo che il metodo W restituisca l'argomento s, ma ciò richiederebbe uno sforzo, quindi nessuna promessa.

Codice golfizzato:

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

Formattato un po ':

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

4

Giava, 1039 1001 993 953 946

Con bonus: rimuove gli spazi iniziali (-30 byte) -> 1009 971 963 923 916

Cancellare lo schermo non vale la pena con Java (tranne se stampo solo un paio di righe. Ma poi l'utente deve usare la dimensione corretta della console)

Codice:

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

Bella:

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

Se il programma non dovesse funzionare per sempre, potrei anche salvare alcuni byte rimuovendo il ciclo while e chiamando semplicemente main.

Questo non è ottimale, ma è un inizio.


Sono abbastanza sicuro che non hai bisogno delle publicparole chiave ... Inoltre, import java.*;funziona?

Ho pensato anche a @professorfish import java.*;, ma non funziona. E il metodo principale deve essere esattamente public static void main(String[]c)(incluso public), altrimenti non viene riconosciuto. Ma la classe ovviamente non deve essere pubblica, buona cattura.
tim
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.