Есть ли «Файл ввода-вывода в Postscript для чайников»? - PullRequest
1 голос
/ 28 февраля 2011

Большая часть , сыгранного на переполнении стека, включает цифры ASCII, и codegolf.SE формируется аналогичным образом.

Это все хорошо, но я бы хотел добавить немного разнообразия в вывод и написал мой недавний вопрос Вывести сетку кроссвордов, которые можно воспроизвести , чтобы поощрять ввод в графическом формате.

Чтобы показать желание, я начал пытаться взломать ссылочную реализацию в postscript. Увы, я совершенно новичок в этом языке, и у меня проблемы с выполнением базового ввода-вывода файла Кто-нибудь знает основной ресурс, освещающий эту тему?

Мне известно о

  • file
  • (%stdin)
  • token
  • readstring
  • readline

но мне совершенно неясно, что именно возвращают последние три и как кто-то манипулирует им после того, как вы его получили.

Я выяснил, что выяснил, что некоторые возвращают пару <value> <boolean>, и что я могу использовать if для проверки логического значения. Тогда что?

Ответы [ 3 ]

10 голосов
/ 03 марта 2011

Хорошей книгой о постскриптуме является «мышление в постскриптуме» Глин Рейд.Раньше вы могли получить книгу бесплатно для личного пользования с его сайта, но его нет.Вы все еще можете загрузить его с http://replay.waybackmachine.org/20090621100720/http://www.rightbrain.com/pages/books.html

Глава 14 посвящена файлу io и содержит пример кода.

6 голосов
/ 01 мая 2011

В PostScript есть несколько хитростей и ярлыков для File IO, которые часто не упоминаются во вступительных разделах книг PostScript.Самым секретом среди них является оператор «токен».Это позволяет заимствовать собственный сканер интерпретатора для чтения голого слова (создание объекта типа имени), числа (создание объекта типа integer или realtype) или их массива (но только если вы используете нотацию исполняемого массива, т.е.фигурные скобки, в противном случае вы просто получите объект marktype, который представляет левую квадратную скобку).

В качестве простого примера я часто использую этот однострочный элемент для встраивания расширенного раздела комментариев в программу postscript:

%!
{ currentfile token pop /END-COMMENT eq {exit} if } loop
Each word here is read from the current file and converted
into a name object and compared to "/END-COMMENT".
It can have but does not need a preceeding slash.

This program produces an image of a snowman in a blizzard,
suitable for use as stationary.
END-COMMENT

showpage

Редактировать: Теперь я понимаю, что это действительно ужасный ответ ... пока.

Мой пример выше немного больше, чем:

(Some
multi-line
text)
pop

Итак, на этот раз по-настоящему.

Для начала вам понадобится loop.

{
} loop

Внутри этого цикла вы читаете некоторые данные.

/src (datafile) (r) file def
{
    src readline
} loop

Как вы заметили, все операторы чтения файлов возвращают логическое значение в верхней части стека.Отлично!

/src (datafile) (r) file def
{
    src readline {
    }{
        exit
    } ifelse
} loop

Таким образом, логическое true будет что-то делать и продолжать цикл, но логическое false (no-more-data) приводит к завершению цикла.Но для readline нужна строка, в которую нужно поместить свои данные.И он возвращает строку даже в ложном случае.

/src (datafile) (r) file def
/str 80 string def
{
    src str readline {
        processline
    }{
        pop exit
    } ifelse
} loop

Теперь у нас есть строка, содержащая строку (максимум 80 символов) данных из файла.Если он вообще напоминает синтаксис Postscript, вы можете использовать token в цикле (как в моем первом примере; он читает каждое слово из файла, преобразует его в имя исполняемого файла, а затем сравнивает его с буквальным именем; если имена совпадают;, выйти из цикла).Или вы можете использовать get в цикле (или цикле forall), чтобы извлечь каждый байт как целое число.Но самое интересное, что нужно сделать, это search.

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

/processline { % (line)
     ( ) { % (line) ( )
         search { % (post) ( ) (pre)
             =
         }{ % (no-match)
             =
             exit
         } ifelse
     } loop
} def

Обычно это прощепросто для того, чтобы дублировать случаи здесь, когда вы хотите сделать то же самое с последним словом, как и все остальные.Вы можете сделать некоторые хитрые вещи для обработки самой верхней строки и затем протестировать логическое значение;но это действительно не стоит хлопот.Крутая вещь в search - это удобный порядок, в котором он возвращает свои результаты.Он помещает начало строки сверху, чтобы вы могли работать с ним.Затем он дает вам «match» (который совпадает с «поиском», который вы дали изначально (хотя теперь он ссылается на рабочую строку)) и остаток;и они уже в правильном порядке для следующего обхода цикла.

Так что вы хотите сделать с вашими извлеченными, разделенными пробелом словами, прочитанными из внешнего файла?

Если они представляют числа, вы можете cvi или cvr их и делать арифметику.Если они буквенно-цифровые, вы можете print или show их;или cvn их и используйте их как атомарные символы.

5 голосов
/ 02 марта 2011

Звучит так, будто вы хотите преобразовать простой текстовый файл (представляющий макет кроссворда) в код PostScript, который рисует этот кроссворд на странице. Хотя это правда, что PostScript является полным по Тьюрингу и, следовательно, может быть запрограммирован для этого, я думаю, что программирование всего на PostScript не является хорошим подходом.

PostScript - сложный язык для программирования, особенно если вы хотите возиться с произвольными данными. Когда я хочу вывод PostScript, я начинаю со взлома некоторого примера PostScript, который рисует то, что я хочу, со всеми параметрами, жестко закодированными. Затем я пишу код на каком-то другом языке, который выводит этот код PostScript, изменяя при необходимости соответствующие части в зависимости от ввода.

Я вижу, что это не очень хорошо читается, так что вот пример. Если у меня есть входной файл, который содержит радиус круга, то я напишу программу на Python, которая читает этот радиус, а затем пишет код PostScript для рисования круга с радиусом, жестко закодированным в PostScript.

Я начал работать над проектом кроссворда много лет назад. Не слишком далеко, но прикрепленный код PostScript нарисует небольшой кроссворд. Обратите внимание, что «правильный» PostScript следует некоторым соглашениям документа, с которыми я не беспокоился; У меня есть отрывочные заметки о них, которые я могу опубликовать.

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

Я этого не убирал. Не стесняйтесь просить разъяснений. НТН.

%!

% "Example"
% by (author)
% Generated 16 Apr 2005 22:19 by (program name)

% should really be eps

% unit conversions

/inch {72 mul} bind def
/cm {inch 2.54 div} bind def



%%%%%% start of adjustable parameters

% these may be fiddled with, within reason
% be careful not to change the syntax

% paper size
/page_width 8.5 inch def
/page_height 11 inch def

% page margins
/top_margin 1 inch def
/left_margin 1 inch def

% how many "cells" wide and high
/puzzle_width 9 def
/puzzle_height 9 def

% cell_size: height and width of a one-letter square, in points
/cell_size .25 inch def

% line width, in points. 1 is about maximum.
/line_width .375 def

% font and size for the numbers
/cell_font {/Helvetica 5} bind def

% top/left margin for numbers within a cell
/num_margin 1.5 def

%%%%%% end of adjustable parameters



<< /PageSize [page_width page_height] >> setpagedevice


/w_pts puzzle_width cell_size mul def
/h_pts puzzle_height cell_size mul def

/ulx left_margin def
/uly page_height top_margin sub def
/lrx ulx w_pts add def
/lry uly h_pts sub def


% draw grid

line_width setlinewidth
0 setgray

newpath ulx uly w_pts h_pts neg rectstroke

lry cell_size uly {
  newpath ulx exch moveto w_pts 0 rlineto stroke
} for

ulx cell_size lrx {
  newpath lry moveto 0 h_pts rlineto stroke
} for


% fill in black spaces

% ulx uly width height blackrect
% all in terms of cells; upper-left-most is 0,0
/blackrect
{
  << >> begin
  /h exch def /w exch def /y exch def /x exch def
  newpath
  ulx x cell_size mul add
  uly y cell_size mul sub
  w cell_size mul
  h cell_size mul neg
  rectfill
  end
} bind def

0 setgray
0 0 1 1 blackrect
3 0 2 1 blackrect
8 0 1 1 blackrect
4 1 1 1 blackrect
2 2 1 1 blackrect
6 2 1 1 blackrect
8 3 1 1 blackrect
0 4 2 1 blackrect
7 4 2 1 blackrect
0 5 1 1 blackrect
2 6 1 1 blackrect
6 6 1 1 blackrect
4 7 1 1 blackrect
0 8 1 1 blackrect
4 8 2 1 blackrect
8 8 1 1 blackrect


% draw numbers

% x y h s drawnum
% x and y in terms of cells; upper-left-most is 0,0. s is string.
% h is height of numbers. should never change, so compute once before any calls.
/drawnum
{
  << >> begin
  /s exch def /h exch def /y exch def /x exch def
  newpath
  ulx x cell_size mul add num_margin add
  uly y cell_size mul sub num_margin sub h sub
  moveto s show
  end
} bind def

0 setgray
cell_font selectfont

% compute font height
mark
newpath 0 0 moveto
(0) false charpath flattenpath pathbbox
/fh exch def
cleartomark newpath

1 0 fh (1) drawnum
2 0 fh (2) drawnum
5 0 fh (3) drawnum
6 0 fh (4) drawnum
7 0 fh (5) drawnum
0 1 fh (6) drawnum
3 1 fh (7) drawnum
5 1 fh (8) drawnum
8 1 fh (9) drawnum
0 2 fh (10) drawnum
3 2 fh (11) drawnum
4 2 fh (12) drawnum
7 2 fh (13) drawnum
0 3 fh (14) drawnum
2 3 fh (15) drawnum
6 3 fh (16) drawnum
2 4 fh (17) drawnum
1 5 fh (18) drawnum
7 5 fh (19) drawnum
8 5 fh (20) drawnum
0 6 fh (21) drawnum
3 6 fh (22) drawnum
7 6 fh (23) drawnum
0 7 fh (24) drawnum
2 7 fh (25) drawnum
5 7 fh (26) drawnum
6 7 fh (27) drawnum
1 8 fh (28) drawnum
6 8 fh (29) drawnum


showpage
...