golden-luckyの日記

ツイッターより長くなるやつ

2021年賀状(というかPostScriptのQuineの話)

もう10年間、ほぼ毎年PostScriptのプログラムを手書きして年賀状を作ってきたわけだけど、いつも年賀状を出しているのは親戚などの非コンピューターな人たちが大半なので、PostScriptでプログラマティックにデザインを生成している面白さはわからないし、もうプログラムとしてのネタ性をデザインに向けなくてもいいだろうということで、今年はデザインには一ミリも努力せずプログラムだけ工夫してみました。年賀状っぽいPDFを出力しつつPostScriptのコードとしてはQuineになっているというプログラムです。*1

<< /PageSize [420 285] >> setpagedevice
/SaucerBB.ttf findfont 140 scalefont setfont
1 0 0 setrgbcolor
/a
(\(<< /PageSize [420 285] >> setpagedevice\) =)
def
/b
(\(/SaucerBB.ttf findfont 140 scalefont setfont\) =)
def
/c
(\(1 0 0 setrgbcolor\) =)
def
/y
(2021)
def
/s
(/a == a == \(def\) = /b == b == \(def\) = /c == c == \(def\) = /y == y == \(def\) = /s == s == \(def\) =)
def
/x
(/x == x == \(def 20 100 moveto y show a cvx exec b cvx exec c cvx exec y cvx exec s cvx exec x cvx exec showpage\) =)
def 20 100 moveto y show a cvx exec b cvx exec c cvx exec y cvx exec s cvx exec x cvx exec showpage

できるのはこんなつまらないPDFですが…、

f:id:golden-lucky:20201227174329p:plain

PostScript言語としての出力結果はもとのソースコードと同一になります。

$ ps2pdf 2021.ps 2> result.ps 
$ diff 2021.ps result.ps 
$ # もとのソースと同一なので差分がない!

どうやって書いたか

Quineには標準的な書き方のようなものがあって、『あなたの知らない超絶技巧プログラミングの世界』という、21世紀の人類が到達した狂気のひとつであるような名著に詳しく書いてあります。

PostScriptのQuineとしては、この書籍でも紹介されている次のチートっぽいやつが有名です。

(dup == =)
dup == =

しかし、PostScriptにも文字列を評価する方法(exec)があるので、同書においてRubyで紹介されている手法でも書けます。ポイントは === の違いを利用して丸括弧のエスケープをごまかすところです。

/a
(/a == a == \(def a cvx exec\) =)
def a cvx exec

これをベースにページ記述言語の部分を足していくことで、今年の年賀状のコードを書きました。

*1:本当はデザインのネタが思いつかなかった、かつ、アスキーアートにしたかったけどPostScriptに標準出力と文字列操作の機能がなさすぎて手に余った。