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)"]
!、$およびの%代わりにn、tおよびのような演算子変数名を使用するゴルフトリックを適用して、u空白を節約する(このヒントを参照)と、最終的な182バイトバージョンになります。
説明で明示的に述べられていない場合、構文エラーまたは型エラーが発生するはずのその他のすべての部分文字列削除。
編集1: length(explode t)はただsize tです。
編集2: Anders Kaseorgに別の馬鹿げたアプローチと「脆弱性」を指摘してくれてありがとう。