zsh、603 594 566 561 548 440 415 399 378 370バイト
ec
ho \\n;ca t<<<$'\x20';exi t
d$c -e8BC6P
d0c -eKp
$'\172\163\150' $'\055\143' $'\146\157\162 v \151\156 \173\043\056\056\134\175\175\073\173 \146\147\162\145\160 \055\161 $\166 '$0$'\174\174\074\074\074$\166\073\175'
$'\145v\141\154' $':\073\072\046\046\145\170\151\164';#%&()*+,/9=>?@ADEFGHIJLMNOQRSTUVWXYZ[]^_`jklmsuwy
0# $#;for b in {$..z};{ fgrep -q $b $0||<<<$b;}
coreutils +に依存しdc
ます。
オンラインでお試しください!
それは...旅でした。
この答えには3つの部分があります。最初の4行は、特定の特殊なケースを処理して、後続のコードを簡素化します。次の2行と最後の行はどちらも本質的に同じことを実現しますが、特定の文字を削除して1つだけ実行します。それらはほとんど補完的な文字セットで書かれているため、文字を削除してもせいぜい1つだけが壊れ、もう1つは機能し続けます。
最初の部分を見て、最初に処理します
- 改行の削除
ec\nho \\n
- スペースの除去
ca t<<<$'\x20'
(後続のexi t
コードの実行を回避するために続きます。これにより、余分な出力が発生します)
$
除去d$c -e8BC6P
(8BC6
= 9226
であり36*256 + 10
、そして36及び10は、のバイト値であり$
、それぞれ、改行文字、我々はライン6に大きいコメントに含めることを回避するために小数で進数字を使用して)
0
を使用した削除d0c -eKp
(K
10進精度を取得0
します。これはデフォルトです)
次の部分では、使用される文字(2行目の終わりのゴミを除く)は$'\01234567v;
、スペース、改行のみです。これらのうち、4つが考慮されているため、残りの行('\1234567v
)は最後の行に現れません。8進エスケープ($'\123'
値123 8の ASCII文字を表す)を展開すると、次のようになります。
zsh -c 'for v in {#..\}};{ fgrep -q $v '$0'||<<<$v;}'
eval ':;:&&exit'
最初の行は、プログラムで使用されるすべての文字をループし、独自のソースコード($0
実行中のスクリプトのファイル名)で各文字を検索し、見つからない文字を出力します。
2行目は少し奇妙に見え、exit
多数のnops を使用した場合と同じことをしているように見えます。ただし、exit
8進数として直接エンコードすると$'\145\170\151\164'
、2
またはが含まれないとなります3
。実際には、これを削除に対して回復力の低いものにする必要があります。これは'\014567v
、最初の行を壊していずれかが削除されると、2番目の行も壊れて、残りのコードを実行できるようになるためです。ただし、3行目と4行目を実行できるように、2
または3
削除された場合は、ブレークする必要もあります。これは、それぞれ8進数表現で2と3をもつ:
およびのシューホーンによって達成され;
ます。
2行目の終わりのジャンクは、すべての印刷可能なASCII文字が少なくとも1回出現することを確認するためだけにあります。
exit
最初のセクションで呼び出されなかった場合(つまり、の1つを削除することでマングルされた場合'\01234567v
)、2番目のセクションに進み、これらの文字を使用せずに同じことを実行する必要があります。最後の行はデコードされた最初の行に似ていますが、ループの範囲を縮小して数バイトを節約できる点が異なり'\01234567v
ます。また、持っている0# $#
、それをコメントアウトしている場合余分な出力を生成するのを防止する、その前0
または$
削除されました。