Ecrire un écrivain

10

Voici une représentation ASCII assez simple d'un livre ouvert:

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

Notez que la partie texte est uniquement sur la page de droite et fait 7 caractères de large par 5 de haut. Notez également que le bord supérieur du livre comporte 5 barres obliques inverses et 10 traits de soulignement. Le 10 vient de la largeur du texte plus 3 et le 5 est la moitié de 10.

En utilisant le même format de mise à l'échelle, nous pouvons redimensionner le livre pour avoir une zone de texte w caractères large et h haut, où w est tout entier positif impair et h est tout entier positif.

Certains livres w × h : 1 × 1, 1 × 2, 3 × 2

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

Le nombre de traits de soulignement en haut est toujours w +3 et le nombre de barres obliques inverses est toujours ( w +3) / 2.

Objectif

Écrivez un programme qui prend un nom de fichier et w et h comme arguments de ligne de commande, et sort un livre avec ces dimensions de texte vers stdout, affichant le contenu du fichier.

Lorsque le fichier contient plus de texte que ne peut en contenir une page, la Nclé doit imprimer la page suivante et Brevenir en arrière d'une page. Rien ne devrait se produire si vous Bappuyez sur la première page ou Nsur la dernière page. Le programme devrait s'arrêter lorsque la Qtouche est enfoncée.

Exemple

Supposons que f.txtcontient Lorem ipsum dol?et que l'utilisateur ait appuyé sur la séquence de touches N N B N N Q. Le programme devrait exécuter quelque chose comme ceci:

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

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

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

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

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

>>>

Notez qu'il y a une nouvelle ligne après chaque livre et aucun espace de fin. Ceci est nécessaire.

Remarques

  • Vous pouvez supposer que le fichier contient uniquement des caractères ASCII imprimables (hex 20 à 7E).
  • Imprimez un caractère à chaque emplacement disponible, quelles que soient les limites des mots.
  • w et h sont des arguments facultatifs par défaut à 7 et 5 respectivement. Votre programme ne recevra ni l'un ni l'autre ni les deux. (Vous pouvez supposer que l'entrée est toujours bien formée.)
  • Remplissez tout espace de texte vide sur la dernière page avec des espaces.
  • Q devrait toujours être requis pour quitter s'il n'y a qu'une seule page.

Gagnant

Le programme le plus court en octets après application des bonus gagne.

Bonus

  • Supprimez les espaces de début pour que chaque ligne commence par un mot (ou segment de mot). par exemple | amet, |dans le premier exemple deviendrait | amet, c |. (-30 octets)
  • Effacer l'écran des livres préalablement dessinés après Nou Best pressé (et Tsi vous faites le bonus après) de sorte que les regards du livre comme ses pages l' évolution en place. (-20 octets)
  • Faites en sorte que la Ttouche bascule instantanément entre le texte en cours de dessin de gauche à droite de haut en bas (par défaut), de haut en bas de gauche à droite. Si vous avez fait le premier bonus, cela devrait fonctionner pour les colonnes en mode de haut en bas. (-100 octets)

    Ainsi, par exemple:

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

    devient

    |\
    | \
    |  \______
    |  ||     |
    \  || Lrm |
     \ || oe  |
      \||_____|
    
Loisirs de Calvin
la source
le bonus "clear the screen" semble être un bonus de langue plutôt qu'un bonus de code ...
John Dvorak
Vous dites dans le texte que le nom de fichier et les dimensions du livre proviennent de STDIN, mais vous continuez à les prendre comme arguments. C'est quoi alors?
John Dvorak
J'ai remarqué, grâce à votre avis, qu'il n'y a pas d'espaces de fuite. Mais sommes-nous tenus de ne pas les inclure non plus?
John Dvorak
@JanDvorak Désolé, je voulais dire que ce ne sont que des arguments. Vous vous devez avoir aucun espace de fin. Pouvez-vous donner un exemple où la compensation devient un "bonus de code"?
Les loisirs de Calvin le
1
@JanDvorak, il me semble plus être un bonus "exécuter le programme dans un terminal POSIX". \033[2J\033[;H
Peter Taylor

Réponses:

3

C # 535 octets

Le score est de 655 octets de code -20 octets de bonus pour la suppression et -100 octets de bonus pour la touche T ... Je pense, je ne peux pas dire que je suis sûr que je n'ai rien manqué dans la spécification

Je peux essayer de réduire les boucles en demandant à la méthode W de renvoyer l'argument s, mais cela nécessiterait des efforts, donc aucune promesse.

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

Formaté un peu:

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
la source
4

Java, 1039 1001 993 953 946

Avec bonus: Supprimer les espaces de tête (-30 octets) -> 1009 971 963 923 916

Effacer l'écran ne vaut pas la peine avec java (sauf si j'imprime juste quelques nouvelles lignes. Mais alors l'utilisateur doit utiliser la taille de console correcte)

Code:

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

Joli:

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 le programme ne doit pas s'exécuter indéfiniment, je pourrais également enregistrer quelques octets en supprimant la boucle while et en appelant simplement main.

Ce n'est pas optimal, mais c'est un début.

Tim
la source
Je suis quasiment sûr que vous n'avez pas besoin des publicmots - clés ... De plus, ça import java.*;marche?
@professorfish J'y ai pensé import java.*;aussi, mais ça ne marche pas. Et la méthode principale doit être exactement public static void main(String[]c)(y compris public), sinon elle n'est pas reconnue. Mais la classe n'a bien sûr pas besoin d'être publique, bonne prise.
tim