清らかな世界をやめる


16

この挑戦はHelka Hombaの質問 " 原始世界のプログラミング "に基づいています。その質問から、初期のプログラムの定義は次のとおりです。

そのままのプログラムを、それ自体にエラーはないが、N文字の連続する部分文字列を削除して修正するとエラーになるプログラムとして定義してみましょう1 <= N < program length

たとえば、3文字のPython 2プログラム

`8`

長さ1の部分文字列を削除した結果、すべてのプログラムでエラーが発生するため(実際には構文エラーですが、あらゆるタイプのエラーが発生するため)、初期のプログラムありがとう、Spです。

8`
``
`8

また、長さ2の部分文字列を削除した結果、すべてのプログラムがエラーを引き起こします。

`
`

たとえば、エラーのない`8プログラムであった場合、部分文字列の削除の結果はすべてエラーになる必要がある`8`ため、初期状態ではありません。

ノート:

  • コンパイラの警告はエラーとしてカウントされません。
  • エラーが発生したサブプログラムは、最終的にはエラーにならない限り、入力を取得したり、出力したり、他のことを実行したりできます。

あなたの仕事は、独自のソースコードを正確に印刷し、適切なquineのルールに従い、初期状態である、長さがゼロでないプログラムを作成することです。

各言語のバイト単位の最短回答が優先されます。


エラーにならない言語は競争できないと思いますか?
アタコ

@ATaco残念ながらはい。Lispなどの他の言語では、便利な原始的なプログラムを作成できないような方法で構文が構成されています。
Shelvacu

RIP Actually / Seriously
ATaco

「各言語のバイト単位の最短回答が勝ちです。」手付かずのプログラムに最適な手段が短いかどうかはわかりません。
P.シール

@ P.Siehr代わりに何をお勧めしますか?
Shelvacu

回答:


6

Haskell、132バイト

q x=if length x==132then putStr x else fail[];main=q$(++)<*>show$"q x=if length x==132then putStr x else fail[];main=q$(++)<*>show$"

オンラインでお試しください!

これは、クインの拡張です

main=putStr$(++)<*>show$"main=putStr$(++)<*>show$"

これは、データ文字列を引用符付きのバージョンと連結し(を使用してshow)、結果を出力します。データ文字列内の任意の文字が失敗することなく取り外すことができ、また、しかし、これは自然のままではない$(++)<*>show$か、(++)<*>一部のプログラム破壊せずにドロップすることができました。

この問題を解決するには、カスタム印刷機能がq定義されているチェックし、指定した文字列との通話の長さfail、それはより短い132これ漁獲データ列から、任意の配列の除去とのまた削除かどう$(++)<*>show$かを(++)<*>結果として生じる両方のケースのように、渡される文字列qは短くなります。

q番号132に短縮することができ11332または2、それぞれの場合に再度fail呼び出されます。

私が知る限り、他の部分文字列を削除すると構文エラーまたは型エラーが発生するため、プログラムはそもそもコンパイルされません。(Haskellの厳密な型システムはここで役立ちます。)

編集:欠陥を指摘してくれたØrjanJohansenとShelvacuに感謝します!


fail[]|length x/=122削除できるのではないかと心配しています。fail[]:[putStr x|length x==122]うまくいくかもしれません。
Ørjanヨハンセン

ああ、いや、その後|length x==122削除することができます。if length x==122 then putStr x else fail[]たぶん?
Ørjanヨハンセン

@ØrjanJohansen良いキャッチ、私はif then else前に持っていたが、私はそれを短くできると思った。
ライコニ

2
putStr xなることができp x、私はそれを殺した前に、私は非常に長い時間のために私のシステムのRANにしようとしたそのとき、私はそれは無限ループですが、末尾呼び出しの再帰が最適化された疑いがあります。私はそれを修正する方法に関する提案をするのに十分なhaskellを知りません。
Shelvacu

@Shelvacuおっと。名前pを変更してq修正する必要があります。
Ørjanヨハンセン

4

Python 3、113バイト

for[]in{113:[]}[open(1,"w").write((lambda s:s%s)('for[]in{113:[]}[open(1,"w").write((lambda s:s%%s)(%r))]:a'))]:a

オンラインでお試しください!

使い方

2番目のステートメントは削除できるため、複数のステートメントを簡単に使用することはできません。したがって、単一式のクインから始めます。

print((lambda s:s%s)('print((lambda s:s%%s)(%r))'))

部分文字列の削除から保護するために、のopen(1,"w").write代わりに使用しますprint。Python 3ではwrite、書き込まれた文字の数を返します。これ113は、文字列の一部が削除されていないことを確認するためのものです。これを行うには、辞書{113:[]}で戻り値を検索し、結果をfor[]in…:aでループします。空のイテラブルが取得されなかった場合、またはforステートメントが削除された場合は失敗します。


1
あなたのコードがどのように機能するかについて説明していただけますか?
Shelvacu

@Shelvacuうん、追加した。
アンダースカセオルグ

3

ルビー、78バイト

eval(*[($>.write((s=%{eval(*[($>.write((s=%%{%s})%%s)-78).chr])})%s)-78).chr])

私は、それが可能であることを確認するための挑戦を考えたときにこれを書きました。元の原始的な課題に対する私の答えの1つと同じ「ラッパー」を使用します。

説明:

  • eval(*[ expr ])

    これは、Rubyプログラムとして返されるコードを評価します。これは、コードが返す文字列が有効なルビープログラムであることを効果的にテストします。便利なことに、ルビープログラムは空白にすることも、空白だけで構成することもできます。

    「splat」演算子*を使用すると、配列を関数の引数として使用できます。これevalは、削除された場合、結果のプログラムは(*[ expr ])であり、有効なルビーではないことも意味します。

  • ($>.write( str )-78).chr

    $> STDOUTの短い変数です。

    $>.write(foo) fooをSTDOUTに書き込み、このコードにとって重要なこととして、書き込まれたバイト数を返します。

    $>.write(foo)-7878これはプログラムの長さです。したがって、プログラムがマングルされていない場合は、書き込まれたバイト数にもなります。したがって、マングルされていない場合、これはゼロを返します。

    num.chr文字としてnumを返します。たとえば0.chr、単一のnullバイトを含む文字列を返します。符号化されていないプログラムでは、これは単一のnullバイトの文字列をに与えますeval。これは、no-opである有効なrubyプログラムです。

    また、プログラムは部分文字列を削除して、ちょうどeval(*[(78).chr])またはのようにすることeval(*[(8).chr])ができます。これは、数値定数が数字(0、4、9、10、11、12、13、26、32、35、48)で終了できないことを意味します、49、50、51、52、53、54、55、56、57、59、64、95)は、有効な単一文字ルビープログラムのASCIIコードであるためです。

  • %{ str }

    これは、ルビーの文字列リテラルのあまり知られていない構文です。ここで使用されている理由は{}、文字列内でのバランスの取れたペアを使用できるためです。つまり、この構文自体を含めることができます。たとえば%{foo{bar}}、はと同じ"foo{bar}"です。

  • (s=%{ データ })%s

    これは、sこのクインのデータである変数をprintf文字列として定義します。

    ルビーの割り当ては割り当てられたものを返すので、これは最初に割り当てsてから実行するのと同じですs%s

    %文字列上のsprintfに相当するルビーの合成糖です。%sデータ内のデータ自体は、組み込まれるべきである意味します。

    このコードは、クインのデータ部分を定義し、それをそれ自体に埋め込み、完全なコードを作成します。


3

標準ML(MLton) 204の 182 189バイト

val()=hd[(fn s=>let val$ =s^"\""^String.toString s^"\"]"val(189,%)=(size$,$)in print%end)"val()=hd[(fn s=>let val$ =s^\"\\\"\"^String.toString s^\"\\\")\"val(189,%)=(size$,$)in print%end)"]

オンラインでお試しください!

MLtonのために、完全なSMLプログラムのいずれかで区切られて終了式である;(例えばprint"Hello";print"World";付き)または宣言varし、funキーワード(例えばvar _=print"Hello"var _=print"World"_も任意の変数名に置き換えることができるワイルドカードですが。

最初のオプションは;、それ自体が有効なプログラムであるため、元のプログラミングには役に立ちません(これは何もしませんが、エラーも発生しません)。第二のアプローチに伴う問題は、そのような宣言var _=print"Hello"に短縮することができるだけvar _="Hello"(あるいはvar _=print)と宣言するのでvar、長い右側ほど作品が有効なSML式または値は、(機能ができるように、SMLは、関数型言語であります値としても使用されます)。

この時点で、私は偶然、私がつまずい不可能SMLで手付かずのプログラミングを宣言する準備ができていたパターンマッチングval-declarations。これは、宣言の構文ではないことが判明しval <variable_name> = <expression>たがval <pattern> = <expression>、パターンは変数名、定数およびコンストラクタで構成することができる場所。print機能が型を持ってstring -> unit、我々は上のパターンマッチを使用することができますunit-値()印刷機能は、実際に文字列に適用されることを強制するために:val()=print"Hey"。このアプローチでは、どちらprint"Hey"を削除するとPattern and expression disagreeエラーが発生します。

この手つかずの自然な印刷方法で、次のステップは、最終的にさらにいくつかの保存保護を追加する必要がある前に、クインを書くことです。以前は簡単なSMLクインテクニックを使用していました(改訂履歴を参照)が、Anders Kaseorgは、彼のケースでいくつかのバイトを節約できる別のアプローチを指摘しました。これは、内蔵使用String.toStringエスケープハンドル文字列に機能し、一般的な形式である<code>"<data>""<data>"のエスケープされた文字列であるcode前に:

val()=(fn s=>print(s^"\""^String.toString s^"\""))"val()=(fn s=>print(s^\"\\\"\"^String.toString s^\"\\\"\"))"

これは機能するクインですが、まだ初期の状態ではありません。まず、Anders Kaseorgは、MLtonが"エラーを生成せずに単一引用符をコードとして受け入れることを発見しました。つまり、上記のように引用符で終わるコードを持つことはできません。これを防ぐための最も簡単な方法val()=は、すべてを括弧で囲むことval()=()です。ただし、コードはに減らすことができます。私が見つけた2番目に短い方法は、を使用するval()=hd[ ... ]ことです。つまり、すべてをリストにラップし、その最初の要素を返して型チェッカーを幸せにします。

気付かれずにデータ文字列のどの部分も削除できないようにするには、val-declarationsのパターンマッチングが再び役立ちます。印刷される最終文字列の長さ(したがってプログラムの長さ)は195に等しくなければなりません。の代わりに抽象化let val t=... val 195=size t in print t endの本体に書き込むことができます。文字列の一部を削除すると、長さが189未満になり、例外がスローされます。fnprint(...)Bind

まだ問題が残っていval 195=size tます。チェック全体が単純に削除される可能性があります。これを防ぐには、チェックをval t=... val(216,u)=(n+size t,t)in print u end削除してtuple:に一致させ、チェックを削除するとバインドされていない変数が生成されるようにしますu

全体として、これにより次の195バイトのソリューションが得られます。

val()=hd[(fn s=>let val t=s^"\""^String.toString s^"\")"val(195,u)=(size t,t)in print u end)"val()=hd[(fn s=>let val t=s^\"\\\"\"^String.toString s^\"\\\")\"val(195,u)=(size t,t)in print u end)"]

!$およびの%代わりにntおよびのような演算子変数名を使用するゴルフトリックを適用して、u空白を節約する(このヒントを参照)と、最終的な182バイトバージョンになります。

説明で明示的に述べられていない場合、構文エラーまたは型エラーが発生するはずのその他のすべての部分文字列削除。

編集1: length(explode t)はただsize tです。
編集2: Anders Kaseorgに別の馬鹿げたアプローチと「脆弱性」を指摘してくれてありがとう。


"\""直接書き込みString.toString、エスケープに使用して、-2バイト
アンデルスカセオルグ

待ってください。これは恐ろしいことです。MLtonはプログラムを受け入れ、"空の出力(TIO)を生成するようです。
アンデルスカセオルグ

@AndersKaseorgええ、それは奇妙です。ただし、別のを使用してこの問題を修正することは可能let ... in ... endです。
ライコニ

@AndersKaseorgこの問題を修正しましたが、できれば新しい「脆弱性」を導入しないでください。
ライコニ

実際、私は"プログラムとして受け入れているMLtonを調査しましたが、このコミットでバグが修正されたようです。
アンデルスカセオルグ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.