Напишіть книгу письменника


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або BTякщо ви зробите бонус після цього), щоб книга виглядала так, як змінюються сторінки. (-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;
    }
}

4

Java, 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.*;працює?

@professorfish Я також думав про import java.*;це, але це не працює. І основний метод дійсно повинен бути точно public static void main(String[]c)(в тому числі public), інакше він не розпізнається. Але, звичайно, клас не повинен бути публічним, хороший улов.
час
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.