FizzBazz
PostScript で http://karetta.jp/book-node/gauche-hacks/023107 っぽいやり方で書いてみる。むしろ、Unix コマンドをパイプで繋げていくのに似ているような。
/map{[3 1 roll forall]}def % map は簡単に自作できます /integer?{type/integertype eq}def [1 1 100{}for] {dup integer?{dup 15 mod 0 eq{pop(FizzBuzz)}if}if}map {dup integer?{dup 5 mod 0 eq{pop(Buzz)}if}if}map {dup integer?{dup 3 mod 0 eq{pop(Fizz)}if}if}map {=}forall
似たようなパターンはまとめるべきなんじゃないかと思ったので、こうする。
% EUC-JP で保存してね /の倍数なら{ % any1 integer2 -- boolean % any1 が integer2 の倍数であれば true、 % そうでなければ false をスタックに置く % any1 が整数でない場合も false 1 index type/integertype eq{ mod 0 eq }{ pop pop false }ifelse }def /置換{ % array1 proc any -- array2 % 配列の各要素について、それを proc に渡した時 true を返すのであれば % any に置き換える 2 dict begin /..x exch def /..proc exch def [exch{dup ..proc{pop ..x}if}forall] end }def [1 1 100{}for] {15 の倍数なら} (FizzBuzz) 置換 {5 の倍数なら} (Buzz) 置換 {3 の倍数なら} (Fizz) 置換 {=}forall
15 を直接書くのはいかがなものかと思ったら、そこんところを
{dup 3 の倍数なら exch 5 の倍数なら and} (FizzBuzz) 置換
と書き換えたり
/最小公倍数{ % integer1 integer2 -- integer3 % integer1 と integer2 の最小公倍数を計算 % ユークリッドの互除法を使用 2 copy { dup 0 eq{exit}if exch 1 index mod }loop pop idiv mul }def
を定義して
{3 5 最小公倍数 の倍数なら} (FizzBuzz) 置換
と書き換えたりする。毎回最小公倍数を計算すると遅くなるんじゃないかと思ったら、適当に変数にでも代入する。
でもいちばん PostScript らしいのは
1 = 2 = (Fizz) = 4 = (Buzz) = (Fizz) = 7 = 8 = (Fizz) = (Buzz) = % 以下略
というスクリプトではないだろうか。機械生成した PostScript はだいたいこんな感じで書かれているような気がする。