Stack Overflow上播放的大部分code-golf都涉及ASCII数字,而codegolf.SE正在形成相同的方式。
这一切都很好,但是我想在输出中注入一些变化,并且明确地写了我最近的问题Output a playable crossword grid以鼓励图形格式条目。
为表示愿意,我已经开始尝试在postscript中破解参考实现。唉,我对语言完全不熟悉,并且在执行基本文件IO时遇到了麻烦。有没有人知道涵盖这个主题的基本资源?
我知道
file
(%stdin)
token
readstring
readline
但是我很清楚最后三个回归的确切内容以及在你得到之后如何操纵它。
我已经发现有几个返回<value> <boolean>
对,并且我可以使用if
来测试布尔值。什么?
答案 0 :(得分:10)
关于后记的好书是Gleen Reid的“后记思考”。您以前可以从他的网站上免费获取该书供个人使用,但它已经失效。你仍然可以从中下载它 http://replay.waybackmachine.org/20090621100720/http://www.rightbrain.com/pages/books.html
第14章介绍了文件io并提供了示例代码。
答案 1 :(得分:6)
在postscript中有一些文件IO的技巧和快捷方式,这些技巧通常在postscript书的介绍部分中没有提到。其中最保守的秘密是“令牌”操作符。它允许你借用解释器自己的扫描器来读取一个裸字(产生一个名称对象),一个数字(生成 一个integertype或realtype对象),或者这些的数组(但是只有你使用可执行数组表示法,即花括号,否则你只需要一个代表左方括号的marktype对象)。
作为一个简单的例子,我经常使用这个单行程序在后记程序中嵌入扩展的评论部分:
%!
{ 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(无更多数据)会导致循环终止。但readline
需要一个字符串来放入其数据。它甚至在错误的情况下返回字符串。
/src (datafile) (r) file def
/str 80 string def
{
src str readline {
processline
}{
pop exit
} ifelse
} loop
现在我们有一个字符串,其中包含来自文件的一行(最多80个字符)数据。如果它完全类似于Postscript语法,你可以在循环中使用token
(就像我的第一个例子;它从文件中读取每个单词,将其转换为可执行文件名,然后将其与文字名称进行比较;如果名称匹配,退出循环)。或者,您可以在循环(或get
循环)中使用forall
将每个字节提取为整数。但最酷的事情是search
。
此过程扫描字符串以查找以空格分隔的单词,并将每个单词打印到stdout各自的行。
/processline { % (line)
( ) { % (line) ( )
search { % (post) ( ) (pre)
=
}{ % (no-match)
=
exit
} ifelse
} loop
} def
在这里复制案例通常更容易,当你想要对所有其他案件做同样的事情时。你可以做一些棘手的事情来处理最顶层的字符串,然后测试布尔值;但这并不值得麻烦。关于search
的一个很酷的事情是它返回结果的方便顺序。它将字符串的开头放在顶部,以便您可以使用它。然后它给你“匹配”(这与你最初给出的“搜索”相同(尽管它现在引用了工作字符串))和余数;并且它们已经按照正确的顺序进行下一轮循环。
那么你想用从外部文件中读取的提取的,以空格分隔的单词做什么?
如果它们代表数字,您可以cvi
或cvr
进行算术运算。如果它们是字母数字,您可以print
或show
;或cvn
他们并将它们用作原子符号。
答案 2 :(得分:5)
听起来您想要将简单的文本文件(表示填字游戏布局)转换为在页面上绘制填字游戏的PostScript代码。虽然PostScript确实是Turing-complete,因此可以编程来实现这一点,但我认为用PostScript编写整个东西并不是一个好方法。
PostScript是一种难以编程的语言,特别是如果你想搞乱任意数据。当我想要PostScript输出时,我首先将一些样本的PostScript混合在一起,绘制出我想要的东西,所有参数都是硬编码的。然后我用其他语言编写代码,输出PostScript代码,根据输入根据需要改变相应的部分。
我看到它读得不太好,所以这是一个例子。如果我有一个包含圆的半径的输入文件,那么我将在Python中编写一个读取该半径的程序,然后编写PostScript代码来绘制圆,并在PostScript中对半径进行硬编码。
几年前我开始从事填字游戏项目。没有走得太远,但附加的PostScript代码将绘制一个小填字游戏。请注意,“正确的”PostScript遵循一些我没有打扰的文档约定;我有一些关于他们的粗略笔记,我可以发布。
此PostScript代码会进行一些计算。通常我会在PostScript中编写我希望做的事情,或者需要只有PostScript解释器会有数据的东西,例如当前字体中字符串的宽度,以便居中。
我还没有清理过这个。随意要求澄清。 HTH。
%!
% "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