Napisz pisarza książek

10

Oto dość proste przedstawienie otwartej książki w ASCII:

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

Zauważ, że fragment tekstu jest tylko na prawej stronie i ma 7 znaków szerokości i 5 wysokości. Zauważ również, że górna krawędź książki ma 5 ukośników odwrotnych i 10 znaków podkreślenia. 10 pochodzi od szerokości tekstu plus 3, a 5 to połowa 10.

Stosując ten sam format skalowania możemy zmienić rozmiar książkę mieć obszar tekstu wagowo znaków szerokich i h High, gdzie w jest jakiś dziwny dodatnia i h jest dowolną liczbą całkowitą dodatnią.

Niektóre książki w × h : 1 × 1, 1 × 2, 3 × 2

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

Liczba znaków podkreślenia u góry wynosi zawsze w +3, a liczba odwrotnych ukośników wynosi zawsze ( w +3) / 2.

Cel

Napisz progam która przyjmuje nazwę pliku i w i h jako argumentów wiersza poleceń i wysyła książkę z tych wymiarów tekst na standardowe wyjście, wyświetlając zawartość pliku.

Gdy plik zawiera więcej tekstu niż zmieści się na jednej stronie, Nklawisz powinien wydrukować następną stronę i Bpowrócić na stronę. Nic nie powinno się zdarzyć, jeśli Bzostanie naciśnięty z pierwszej strony lub Nzostanie naciśnięty z ostatniej strony. Program powinien zatrzymać się po Qnaciśnięciu klawisza.

Przykład

Załóżmy, że f.txtzawiera Lorem ipsum dol?i użytkownik nacisnął sekwencję klawiszy N N B N N Q. Program powinien uruchomić coś takiego:

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

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

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

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

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

>>>

Zauważ, że po każdej książce jest nowa linia i brak spacji. To jest wymagane.

Notatki

  • Możesz założyć, że plik zawiera tylko drukowalne znaki ASCII (szesnastkowo od 20 do 7E).
  • Wydrukuj jeden znak w każdym dostępnym miejscu, niezależnie od granic słów.
  • w i hopcjonalnymi argumentami, które domyślnie wynoszą odpowiednio 7 i 5. Twój program nie otrzyma ani jednego, ani jednego i drugiego. (Możesz założyć, że dane wejściowe są zawsze dobrze sformułowane).
  • Wypełnij puste miejsce na ostatniej stronie spacjami.
  • Q nadal powinno być wymagane zamknięcie, jeśli jest tylko jedna strona.

Zwycięski

Najkrótszy program w bajtach po zastosowaniu bonusów wygrywa.

Bonusy

  • Usuń spacje wiodące, aby każda linia zaczynała się od słowa (lub segmentu słowa). np. | amet, |w pierwszym przykładzie stałoby się | amet, c |. (-30 bajtów)
  • Wyczyść ekran poprzednio narysowanych książek po naciśnięciu Nlub Bnaciśnięciu (i Tjeśli zrobisz bonus po tym), aby książka wyglądała, jakby zmieniała strony na swoim miejscu. (-20 bajtów)
  • Spraw, aby Tklawisz błyskawicznie przełączał się między rysowanym tekstem od lewej do prawej od góry do dołu (domyślnie), od góry do dołu od lewej do prawej. Jeśli zrobiłeś pierwszą premię, powinien działać dla kolumn w trybie od góry do dołu. (-100 bajtów)

    Na przykład:

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

    staje się

    |\
    | \
    |  \______
    |  ||     |
    \  || Lrm |
     \ || oe  |
      \||_____|
    
Hobby Calvina
źródło
bonus „wyczyść ekran” wydaje się być premią językową, a nie kodową…
John Dvorak
Mówi się w tekście, że nazwa pliku i wymiary książki pochodzą ze STDIN, ale następnie przyjmuje się je za argumenty. Co to jest?
John Dvorak,
Zauważyłem, dzięki waszemu zawiadomieniu, że nie ma spacji końcowych. Ale czy musimy też ich nie uwzględniać?
John Dvorak
@JanDvorak Przepraszam, miałem na myśli, że to tylko argumenty. Nie musisz mieć żadnych spacji. Czy możesz podać przykład, w którym rozliczenie staje się „premią kodową”?
Calvin's Hobbies
1
@JanDvorak, wydaje mi się, że jest to raczej premia za „uruchomienie programu w terminalu POSIX”. \033[2J\033[;H
Peter Taylor,

Odpowiedzi:

3

C # 535 bajtów

Wynik to 655 bajtów kodu -20 bajtów premii za wyczyszczenie i -100 bajtów premii za klawisz T ... Myślę, że nie mogę powiedzieć, że jestem pewien, że niczego nie przeoczyłem w specyfikacji

Mogę spróbować zwinąć pętle, zwracając argument W przez metodę W, ale wymagałoby to wysiłku, więc żadnych obietnic.

Kod do gry w golfa:

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

Trochę sformatowany:

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
źródło
4

Jawa, 1039 1001 993 953 946

Z premią: Usuń wiodące spacje (-30 bajtów) -> 1009 971 963 923 916

Wyczyszczenie ekranu nie jest tego warte w Javie (chyba że wydrukuję tylko kilka nowych linii. Ale wtedy użytkownik musi użyć właściwego rozmiaru konsoli)

Kod:

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

Ładny:

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

Jeśli program nie musi działać wiecznie, mógłbym również zaoszczędzić trochę bajtów, usuwając pętlę while i po prostu wywołując main.

To nie jest optymalne, ale to początek.

tim
źródło
Jestem pewien, że nie potrzebujesz publicsłów kluczowych ... Czy import java.*;działa?
@professorfish Myślałem import java.*;też, ale to nie działa. A główna metoda musi być dokładnie public static void main(String[]c)(w tym public), w przeciwnym razie nie zostanie rozpoznana. Ale klasa oczywiście nie musi być publiczna, dobry haczyk.
tim