空白とPerl、992 975文字
今晩はみなさん。
まず、base64でエンコードされた提出物を示します。これは、大規模なホワイトスペースプログラムと通信するための最良の方法だと感じています。(空白をそのままにするエンコーディングを使用したくないので、「読みやすい」ものを選択しても意味がありません。)
c2F5PDwgeDI7c2F5PDwwLDAgIApzYXk8PCB4MjtzYXk8PDAsMCAgCgoJCQogICAJCSAgCSAgCSAJ
CSAgCSAgCQkgCSAJIAkJCQkJICAJCSAJCQkgCQkJCQkgCSAJIAkJIAkgCSAgIAkJCQkJICAgCQkg
IAkgCQkgCSAJCSAJICAgIAkJCQkgCSAgCSAJCSAJICAgIAkgCQkgICAJICAgICAgCQkJIAkJCQkJ
IAkJCSAJCQkJICAgICAJCQkgCSAgICAgIAkJCQkJICAgICAgCQkgICAJCSAgICAJCQkJCQkJCSAg
CSAJIAkgICAJCQkgICAJCQkJCSAgCQkJCSAJICAgIAkgCQkJCQkgCSAgICAgCSAgCSAJICAgICAg
CSAgICAJICAgICAJCSAgIAkJCSAJIAkJCQkJCSAJCSAJIAkgICAgICAgCQkgIAkgICAgICAgICAg
IAkJICAgCSAJCQkgCSAgICAgCQkJCQkJIAkgICAgCQkJCSAJCQkJICAJCQkgICAJCQkgCSAgCSAg
IAkJCQkgIAkJIAkJCSAgIAkJCSAJCQkgCQkJICAJCSAJICAJIAkJCSAJIAkgCQkgICAgIAkgCSAJ
ICAJICAJIAkJICAgICAJIAkgICAgCQkJCSAgCSAJCSAJIAkJIAkgIAkgCSAJCSAJCSAJCSAJCQkg
CQkJICAgIAkJCSAgCSAgCQogICAJICAgICAJCQkJCSAJCSAJIAkgCSAJICAJCQkgICAJICAgCSAg
ICAJCSAJICAgICAgICAgCSAgIAkJCQkgCQkgICAgCQkgCSAJICAJCQkgCQkJCSAJCQkgICAJICAg
IAkgCSAJCQkgIAkJCQkgCSAJCSAJIAkgCQkJCSAJICAJIAkJIAkgICAJCiAKICAKICAgIAogCSAg
CQoKICAJCiAKICAgIAkJCQkgCSAKCSAJCQkKICAgICAJCQkJIAkgCgkgCSAgCiAgIAkJCgkgIAoK
CQkJCiAKCgoJIAkKICAgCSAgIAkgIAoKIAkKIAkgIAkKCiAJIAogICAJIAoKIAkKCiAJIAoKIAkK
CQogCSAgIAkgCgogCQoKCgoKICAgCiAgIAogCiAKIAkKCiAJCgogICAgCiAKIAoJIAogCiAgICAJ
IAoJIAkJIAoJICAgCSAKCSAJIAogCSAgCgogIAogCiAgICAJCQoJIAkJICAJCSAJCQkKCSAgCiAg
CQkJICAgCgkgCQkgICAJICAgICAKCSAgIAkKICAgICAJCQoJIAkgIAogICAJCQoJICAKCgkJCiAK
CgoJCjAK
以下は、ソースのすべての可視部分を強調した抜粋です。⇥
タブ↲
を示し、改行を示すために使用されます。
say<< x2;say<<0,0 ↲
say<< x2;say<<0,0 ↲
↲
⇥⇥↲
⇥⇥ ⇥ [... etcetera ... skipping rest of a really long line ...]↲
⇥⇥⇥ ⇥⇥[... etcetera ... shorter but still quite a long line ...]↲
↲
↲
↲
⇥ ⇥↲
[... etcetera ... whole lotta whitespace in here ...]
⇥⇥↲
↲
↲
↲
⇥↲
0↲
Perlは、この課題における第2言語の自然な選択であり、コンパクトなクインを作成するための最高の汎用言語の1つです。私の最短のPerlクインは19バイトです。
say<< x2
say<< x2
–そして、それがどのようにダブルクインのPerl半分の種であったかを見ることができます。それに比べて、私の最高のホワイトスペースクインは541バイトです。(短いものもありますが、445バイトが私が見た中で最高です。)
Perlインタープリターの観点から見ると、ダブルクインのソースファイルの最初の行には、プログラム全体を構成する2つのステートメントが含まれています。残りの内容は2つの引用符付き文字列です。最初の文字列はPerlの繰り返し行であり、空白の3行目で区切られています。2番目の文字列はすべて空白で、ソースの4行目から0
ファイルの最後の区切り文字まで続きます。
空白プログラムとして使用すると、最初の4行にはほとんど役に立たない3つの命令が含まれます。(それらの効果は、2つのゼロ値をスタックにプッシュし、2番目のゼロ値を破棄することです。)これらは、Perlプログラムが必要とする改行を安全に通過するために含まれています。読み取り不可能なソースをさらに引用するのではなく、ホワイトスペースプログラムを構成する命令をアセンブリのような形式で言い換えます。
# Representation of "say<< ;say<<0,0 \n" in base 122 as ASCII chars.
PERLCODE = 44892457841068708924520433691075560592081
# Represention of the whitespace program, following the "push PERLCODE"
# instruction, in base 3 (see comments on wsout).
WSCODE = 9823454421986355730445143846606456399449033186160554878002671428613111806443504867738858766142050504887335990409088441824104338753030405625930185
# Set up the stack and the heap. The first three instructions are not
# particularly useful; they're just there to skip past the newlines in
# the Perl code. (Though the initial zero on the stack does get used
# at the very end.)
push 0
push 0
jneg wsout
push WSCODE
push PERLCODE
dup
dup
push 0
copy 1
# Output the first four lines of the file.
perl: dup
mod 122
putchar
div 122
dup
jnzero perl
pop
jzero perl
push 68 # represents "jneg wsout"
call wsout
# Output the rest of the file.
copy 1
call pushout
push 2
call wsout
call pushout
call wsout
putnum
push 2
call wsout
exit
# pushout: Output a Whitespace push instruction, using the number on
# the top of the stack as the instruction's argument. (Recursion is
# used to output the bits MSB-first.)
pushout:
push 0
dup
call wsout
call wsout
bits: dup
jzero bitend
dup
mod 2
swap
div 2
call bits
bitend: call wsout
ret
# wsout: Output a sequence of whitespace characters as represented by
# the number on the top of the stack. The number is read in base 3,
# LSB-first, with 0 = SPC, 1 = TAB, 2 = NL. Calling wsout with a value
# of zero will output a single space.
wsout:
dup
mod 3
mul -23 # some ugly math that transforms
mod -24 # (0, 1, 2) into (32, 9, 10)
add 32
putchar
div 3
dup
jnzero wsout
pop
ret
上部の巨大な数字は、実際の文字列の代わりにホワイトスペースユーザーが使用しなければならないものです。適切なbignumサポートを持たないホワイトスペースインタープリターでこれを実行しようとしないでください。
最後に、再びプログラムを示しますが、今回はCスタイルのエスケープを使用しています。特にリクエストされたためです。
say<< x2;say<<0,0 \nsay<< x2;say<<0,0 \n\n\t\t\n \t\t \t \t \t\t \t \t\t \t \t \t\t\t\t\t \t\t \t\t\t \t\t\t\t\t \t \t \t\t \t \t \t\t\t\t\t \t\t \t \t\t \t \t\t \t \t\t\t\t \t \t \t\t \t \t \t\t \t \t\t\t \t\t\t\t\t \t\t\t \t\t\t\t \t\t\t \t \t\t\t\t\t \t\t \t\t \t\t\t\t\t\t\t\t \t \t \t \t\t\t \t\t\t\t\t \t\t\t\t \t \t \t\t\t\t\t \t \t \t \t \t \t \t\t \t\t\t \t \t\t\t\t\t\t \t\t \t \t \t\t \t \t\t \t \t\t\t \t \t\t\t\t\t\t \t \t\t\t\t \t\t\t\t \t\t\t \t\t\t \t \t \t\t\t\t \t\t \t\t\t \t\t\t \t\t\t \t\t\t \t\t \t \t \t\t\t \t \t \t\t \t \t \t \t \t \t\t \t \t \t\t\t\t \t \t\t \t \t\t \t \t \t \t\t \t\t \t\t \t\t\t \t\t\t \t\t\t \t \t\n \t \t\t\t\t\t \t\t \t \t \t \t \t\t\t \t \t \t\t \t \t \t\t\t\t \t\t \t\t \t \t \t\t\t \t\t\t\t \t\t\t \t \t \t \t\t\t \t\t\t\t \t \t\t \t \t \t\t\t\t \t \t \t\t \t \t\n \n \n \n \t \t\n\n \t\n \n \t\t\t\t \t \n\t \t\t\t\n \t\t\t\t \t \n\t \t \n \t\t\n\t \n\n\t\t\t\n \n\n\n\t \t\n \t \t \n\n \t\n \t \t\n\n \t \n \t \n\n \t\n\n \t \n\n \t\n\t\n \t \t \n\n \t\n\n\n\n\n \n \n \n \n \t\n\n \t\n\n \n \n \n\t \n \n \t \n\t \t\t \n\t \t \n\t \t \n \t \n\n \n \n \t\t\n\t \t\t \t\t \t\t\t\n\t \n \t\t\t \n\t \t\t \t \n\t \t\n \t\t\n\t \t \n \t\t\n\t \n\n\t\t\n \n\n\n\t\n0\n