概念
プログラミング言語でコードを出力するプログラムを作成します。そのコードは、実行時に元のプログラムを出力する必要があります。
ルール
- これは不正行為であるため、元のソースコードを読むことができます。
- 最初の出力プログラムは、元のプログラムと同じ言語である必要があります。
- 通常のクインを出力することはできません。2つのプログラムは異なっていなければなりません。
- 標準の抜け穴が適用されます。
- これはコードゴルフなので、最短の回答が勝ちますが、選択されません。
プログラミング言語でコードを出力するプログラムを作成します。そのコードは、実行時に元のプログラムを出力する必要があります。
回答:
2番目のプログラムは
1
最初のプログラムは、空の入力で空のパターンの一致の数をカウントします(実際には領域0がありますが、パターンは常に空の入力で印刷するものを決定できるようにするためのハックとして少なくとも1回実行されます)。2番目のプログラムは、({1}
正規表現のように)量指定子で始まり、解析エラーが発生します。プログラムは正常に解析されないため、STDOUTは空の文字列です。
7は3ビット文字セットを使用しますが、入力をバイトにパックします(メタによれば、サブバイト文字セットの言語はディスク上のファイルのバイトを使用してカウントされます)。ここだxxd
プログラムのダンプは:
00000000: 4cf4 L.
このファイルを7インタープリターに渡すと、次のプログラムが出力されます。
00000000: 4fa6 7f O..
その後、元のプログラムが再び出力されます。
ここで何が起きているのでしょうか?関係するソースの読み取りはありません(実際、7でソースを読み取ることは不可能だと思います)。どう考えているか教えてください。プログラムの仕組みは次のとおりです。(各7コマンドには2つのバリアントがあり、そのいくつかは名前がなく元のプログラムに表示されないことに注意してください。合計12のコマンドがあり、6ペアです。コマンド、およびアクティブコマンドに名前がない場合には、私はそれに対応する受動的なコマンドと同じ名前を与えていると区別するために大胆に頼る。例えば、両方が命名されている場合、7
の活性な変異体です1
、各コマンドには独自の名前が付けられ、太字は単なる構文強調表示です。
231 7 23 8進数に解凍された元のプログラム 231 237をスタックにプッシュします 23 23をスタックにプッシュします (暗黙)スタックの最上部のコピーをプログラムに追加します 2 スタックの最上部を複製(現在23) 3 スタックの最上部を出力、2番目のスタック要素をポップ
この時点で、7インタープリターは、スタックの最上部に表現できないコマンド(2
および3
)が含まれているため、スタックの最上部をエスケープして723
(つまり)生成します。最初のコマンド出力では、出力形式が選択されます。この場合、フォーマット7、「プログラムと同じ方法で出力をフォーマットする」です。したがって、コマンドは出力をバイトにパックします。その後、プログラムは続行します。
231 7 23 23 (暗黙)スタックの最上部のコピーをプログラムに追加します 2 スタックの最上部を複製(現在237) 3 スタックの最上部を出力、2番目のスタック要素をポップ 7 空の要素をスタックにプッシュ
この時点で、スタックには空のスタック要素しかないため、プログラムは終了します。23
先に出力しました。エスケープする237
(そして、表現できないコマンドが含まれているためにエスケープする必要がある)場合、を取得し7231
ます。それは出力を直接取得し、プログラムの最終出力を作成します237231
(プログラムと同じ形式、つまりバイトにパックされます)。それがあります4fa67f
。(1
出力に影響を与えるという点では、これはまったく無意味であったことに注意してください。2つのプログラムを異なるものにすることが唯一の理由です。)
実行237231
はほぼ同じ方法で進行します。違いは1
、最初の印刷の直後に無駄な実行が行われることです(そして、プログラムの現在の終了に2回目に空の要素が暗黙的に削除されます)。ここでも、231
自分自身を出力するまでの端は、23
自身の出力をアップ両端がが先行し7
、そして我々が得る231723
、元のプログラム。
観察者は、2つのプログラムは、言語の「ネイティブ」8進数の長さが同じであるにもかかわらず、ディスク上の長さが異なることに気付くかもしれません。これは、7プログラムに任意の数の1ビットを埋め込むことができ、パック形式では末尾の埋め込みが破棄されるためです。エンコードは次のように行われます。
2 3 1 7 2 3
010011001111010011(1...)
4 c f 4 padding
つまり、4C
F4
プログラムを表すには2バイトで十分なので、これですべてです。
非不正行為:
A=''';print(("A="+("'"*3+A)*2).translate({65:66,66:65}))''';print(("A="+("'"*3+A)*2).translate({65:66,66:65}))
これは印刷します:
B=''';print(("B="+("'"*3+B)*2).translate({65:66,66:65}))''';print(("B="+("'"*3+B)*2).translate({65:66,66:65}))
実行すると、元のプログラムが印刷されます。
コミュニティは、この種のことを不正行為と見なしているようです。
1
2
末尾に改行があります。
これは印刷します
2
1
最初のコードを出力する末尾の改行を使用します。
RProgNはスタックのポップを上から下へと表示します。
1\n1\n
はRProgNでは1のそれぞれがお互いを印刷するため(そして、各1がそれ自体を印刷する場合にのみ不正と見なされるため)不正ではないことを暗示しています。これは、クインの不正行為を定義するのが難しい場合があることをほのめかしています。(ただし、質問は実際に
1\n
として、技術的には有効なクインです。1
1
1q_a_q
実行すると、次が出力されます。
q_a_q1
順番に出力します1q_a_q
。
1q_a_q
1 the digit one (ignored)
q the source code (ignored)
q the source code
_ reversed
a and outputted
_ and reversed (ignored)
q_a_q1
q the source code (ignored)
1 the digit one (ignored)
q the source code
_ reversed
a and outputted
_ and reversed (ignored)
(_0=_=>console.log(`(_0=${_0})()`.replace(/0/g,n=>+!+n)))()
出力:
(_1=_=>console.log(`(_1=${_1})()`.replace(/1/g,n=>+!+n)))()
-1バイト(@ETHProductions):\ dの代わりに正規表現で0を使用
n=>1-n
代わりに試してくださいn=>+!+n
。
1
最終的には正規表現に置き換えられます。
rev $0 # 0$ ver
-3 @izaberaに感謝
Bash
、Tac
`改訂、と?
rev $0 # 0$<space><space>ver
私はコメントに二つのスペースを置くことはできませんいくつかの理由のために
tac
rev
-edはcat
です。
"$r00gol?!;50.01
出力
"$r00gol?!;50.10