Написать книгу писателю

10

Вот довольно простое описание открытой книги в формате ASCII:

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

Обратите внимание, что текстовая часть находится только на правой странице и имеет 7 символов в ширину и 5 в высоту. Также обратите внимание, что верхний край книги имеет 5 обратных слешей и 10 подчеркиваний. 10 прибывает из ширины текста плюс 3, и 5 - половина 10.

Используя тот же формат масштабирования, мы можем изменить размер книги, чтобы текстовая область имела ширину w и высоту h , где w - любое нечетное положительное целое число, а h - любое положительное целое число.

Некоторые книги в формате W × H : 1 × 1, 1 × 2, 3 × 2

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

Количество подчеркиваний в верхней части всегда равно w +3, а число обратных косых черт всегда ( w +3) / 2.

Цель

Напишите программу, которая принимает имя файла и w и h в качестве аргументов командной строки, и выводит книгу с этими размерами текста в стандартный вывод, отображая содержимое файла.

Если в файле больше текста, чем уместится на одной странице, Nключ должен напечатать следующую страницу и Bвернуться назад. Ничего не должно происходить, если Bнажать на первой странице или Nнажать на последней странице. Программа должна остановиться при Qнажатии клавиши.

пример

Предположим, f.txtсодержит Lorem ipsum dol?и пользователь нажал последовательность клавиш N N B N N Q. Программа должна запустить что-то вроде этого:

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

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

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

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

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

>>>

Обратите внимание, что после каждой книги стоит новая строка, а пробелы отсутствуют. Это обязательно.

Ноты

  • Вы можете предположить, что файл содержит только печатные символы ASCII (шестнадцатеричные от 20 до 7E).
  • Напечатайте один символ в каждом доступном месте, независимо от границ слова.
  • w и h являются необязательными аргументами, которые по умолчанию равны 7 и 5 соответственно. Ваша программа будет либо ни один, ни оба. (Вы можете предположить, что входные данные всегда правильно сформированы.)
  • Заполните любое пустое место на последней странице пробелами.
  • Q по-прежнему необходимо выйти, если есть только одна страница.

выигрыш

Самая короткая программа в байтах после применения бонусов выигрывает.

Бонусы

  • Удалите начальные пробелы, чтобы каждая строка начиналась со слова (или сегмента слова). например, | amet, |в первом примере станет | amet, c |. (-30 байт)
  • Очистите экран ранее нарисованных книг после Nили после Bнажатия (и Tесли вы делаете бонус после этого), чтобы книга выглядела как изменяющиеся страницы на месте. (-20 байт)
  • Сделайте так, чтобы Tклавиша мгновенно переключалась между текстом, рисуемым слева направо сверху вниз (по умолчанию), сверху вниз слева направо. Если вы сделали первый бонус, он должен работать для столбцов в режиме сверху вниз. (-100 байт)

    Так, например:

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

    становится

    |\
    | \
    |  \______
    |  ||     |
    \  || Lrm |
     \ || oe  |
      \||_____|
    
Кальвин Хобби
источник
бонус «очистить экран», похоже, является языковым бонусом, а не бонусом к коду ...
Джон Дворжак
В тексте вы говорите, что размеры имени файла и книги взяты из STDIN, но затем вы принимаете их в качестве аргументов. Что это тогда?
Джон Дворжак
Благодаря вашему уведомлению я заметил, что нет пробелов. Но должны ли мы их тоже не включать?
Джон Дворжак
@JanDvorak Извините, я имел в виду, что это всего лишь аргументы. Вам нужно, чтобы у вас не было висячих пробелов. Можете ли вы привести пример, когда клиринг становится «бонусом кода»?
Увлечения Кэлвина
1
@JanDvorak, мне кажется, это скорее бонус за запуск программы в терминале POSIX. \033[2J\033[;H
Питер Тейлор

Ответы:

3

C # 535 байтов

Оценка составляет 655 байт кода, бонус -20 байт для очистки и бонус -100 байт для клавиши T ... Я думаю, не могу сказать, я уверен, что я ничего не пропустил в спецификации

Я могу попытаться свернуть циклы с помощью метода W, возвращающего аргумент s, но это потребует усилий, поэтому никаких обещаний.

Гольф-код:

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

Отформатирован немного:

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
источник
4

Ява, 1039 1001 +993 +953 946

С бонусом: Удалить пробелы (-30 байт) -> 1009 +971 +963 +923 916

Очистка экрана с Java не стоит (за исключением случаев, когда я просто печатаю пару новых строк. Но тогда пользователь должен использовать правильный размер консоли)

Код:

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

Милая:

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

Если программе не нужно работать вечно, я мог бы также сохранить некоторые байты, удалив цикл while и просто вызвав main.

Это не оптимально, но это начало.

Тим
источник
Я уверен, что вам не нужны publicключевые слова ... Кроме того, import java.*;работает?
@professfishfish Я тоже об этом думал import java.*;, но это не работает. И основной метод должен быть точно public static void main(String[]c)(в том числе public), иначе он не распознается. Но класс, конечно, не должен быть публичным, хороший улов.
Тим