自分の言語ではなく自分の言語を解釈しますか?


21

「Xを解釈する」という多くの課題があります。Xは単純な言語です。私の意見では、それはあまりにも退屈です。インターネット上のすべての先延ばしの人々に何か面白いことをするために、この挑戦​​を試みることができます:

チャレンジ

言語を選択してください$LANG$LANGチューリング完全プログラミング言語またはプログラミング言語のチューリング完全サブセットのいずれかです。あなたの言語の機能$LANGを解釈のために省略した場合、あなたの提出物もで書かなければならないので、あなた自身のプログラムにもそれを使用してはならないことに注意してください$LANG

$LANG書かれたコンパイラ/インタプリタを記述し$LANGます。evalこのコンパイラを作成するために使用できる言語のすべての機能(および友人を含む)を使用できます。タスクをより困難にするために、1つの制限があります。プログラムは$LANG、インタープリター/コンパイラー自体を除くすべての有効なプログラムを解釈/コンパイルできる必要があります。解釈/コンパイルされるプログラムがインタープリターまたはコンパイラー自体である場合(ファイル名に関係なく)、プログラムはインタープリターまたはコンパイラーの機能とはまったく関係のないこと(barfingや印刷など)を行う必要がありますHello, world!

このタスクをさらに複雑にするために、プログラムはコンパイルまたは解釈時に独自のソースを読み取ってはなりません。

仕様書

  • このタスクはコードゴルフです。正しい文字が最も少ない投稿が優先されます。同点の場合、最初に提出されたソリューションが勝ちます。
  • プログラム/スクリプトは、ファイルから解釈されるプログラムを読み取る必要があります。パスと名前をハードコーディングできます。ファイルが読み取られたら、ファイルを別のファイルにコンパイルするか(システムで実行可能である必要があります)、直接実行することができます。$LANGファイル読み取り機能が不足している場合は、に適合するコードを読み取る別の方法を選択できます$LANG$LANG別の言語のサブセットとして選択することはできませんが、ファイル読み取り機能は削除されます。
  • 通常のコードゴルフ規則が適用されます。つまり、この課題を解決するために作成した個人のペット言語は、ソリューションがそれを使用して簡単になった場合は禁止されています(ソリューションを正確に実装する単一文字プログラムを定義するなど)。ルールの乱用は奨励されます。

チューリングが完了している限り、この言語を定義できますか?
ランチャー

@Cruncherはい、そうです。詳細については、仕様の最後の箇条書きを参照してください。
FUZxxl

回答:


8

ルビー、63

b=$<.read
t="b=$<.read\nt=%p\nb!=t%%t&&eval(b)"
b!=t%t&&eval(b)

より小さな解決策がない限り、回答は受け入れられます。
FUZxxl

11

Perl、89文字、不正行為なし

$_=q($_=q(Q);s/Q/$_/;($q=join"",<>)eq$_?die:eval$q);s/Q/$_/;($q=join"",<>)eq$_?die:eval$q

このコードは、「それ自体」として数えるものについて非常にうるさいことに注意してください。特に、入力に後続の改行またはその他の余分な空白がある場合、それ自体を認識しません。テストするには、(たとえば)という名前のファイルに保存して、次の操作unquine.plを行います。

$ perl unquine.pl unquine.pl
Died at unquine.pl line 1, <> line 1.

unquine.plファイルの長さは正確に 89バイトである必要があります。他のPerlスクリプトを入力として実行すると、他のスクリプトが実行されます。

$ perl unquine.pl hello.pl
Hello, world!

名前が示すように、実装はクインに基づいています。具体的には、次のものです。

$_=q($_=q(Q);s/Q/$_/);s/Q/$_/

このコードは$_それ自体に等しいと設定します。プログラムの残りの部分(もちろん、内部で複製する必要があります$_)は、単に$_入力と比較し、一致する場合は死に、そうでない場合は入力を評価します。


その&&/ ;ペアを3進数(1文字がオフ、5倍に倍増)に置き換えることができます。素晴らしいアイデアと実装!
JB

@JB:良いキャッチ!現在89文字まで。
イルマリカロネン

5

GolfScript、30文字

{`".~"+"#{$<.read}".@=!{~}*}.~

このプログラムは、コマンドラインで指定されたファイルの内容を読み取り、上記のコードと正確に一致しない場合は、GolfScriptとして解釈します。入力が上記のコードと正確に等しい場合、単に変更されずに出力されます(末尾に改行が追加されている場合を除く)。

これは、この自己識別プログラムのかなり単純な適応です。具体的には:

  • { } GolfScriptのコードブロックリテラルです。
  • .~、コードブロックに適用され、ブロックを複製してコピーを実行します。

コードブロック内:

  • ` コードブロックのコピーを文字列化します。
  • ".~"+文字.~を追加して、プログラムのソースコードを含む文字列を生成します。
  • "#{$<.read}"GolfScript内でRubyコードを実行できるようにする文書化されたハックです。この場合、Rubyステートメント$<.readLowjackerのRubyソリューションから恥知らずに盗まれた)を実行し、コマンドラインで指定されたファイルの内容を読み取り、返します。GolfScript自体には明示的なファイルI / O機能がないため、このハックが必要です。
  • .@ スタックの最上部の要素を複製およびシャッフルして、スタックにファイル内容のコピーが2つ含まれ、その後にこのプログラムのソースコードが続く
  • =! スタックの上位2つのアイテム(ファイルの内容とソース)を比較し、それらが異なる場合は1を返し、同じ場合は0を返します。
  • {~}*ファイルの内容の残りのコピーをGolfScriptコードとして評価しますが、比較の結果が1の場合のみです(技術的{~}には、スタック上の番号で指定された回数、つまり0回または1回コードブロックを実行します。ブロック~は、GolfScriptの評価演算子です。)

追伸 stdinから実行するコードの読み取りが許可されている場合、Rubyにシェルアウトすることなく21文字でこの課題を解決できます。

{`".~"+1$=!{""\~}*}.~

このプログラムは、stdinから入力文字列を読み取り、それが自身のソースと一致しない場合、それを(空の入力で)実行します。上記のプログラムと同様に、ソースに一致する入力は単にエコーバックされます。


良さそうに見えますが、ファイルから入力を読み取るようには見えません。
FUZxxl 2014

修正され、Lowjackerのソリューションのように(正確に)ファイルから読み取るようになりました。
イルマリカロネン

5

パイソン、167の 130 118バイト

これがゴルフの私の最初の試みなので、ここに行きます!それ以外のプログラムを解釈します

改善されたバージョン:

i=open(raw_input()).read();q='i=open(raw_input()).read();q=%s;i==q%%repr(q)and a;exec(i)\n';i==q%repr(q)and a;exec(i)

自身を取得すると、次のようにbarfsします。

Traceback (most recent call last):
  File "pygolf.py", line 1, in <module>
    i=open(raw_input()).read();q='i=open(raw_input()).read();q=%s;i==q%%repr(q)and a;exec(i)\n';i==q%repr(q)and a;exec(i)
NameError: name 'a' is not defined

このソリューションは、Ilmari Karonenのソリューションとほぼ同じように機能すると思います。基本的な考え方は次のようなものです。

input = read_some_file()
if input == some_quine()
    barf()
interpret(input)

私が使用したクインはこれに基づいていました:

(lambda x: x + repr((x,)))('(lambda x: x + repr((x,)))',)

しかし、私はずっと短いクインが次のことであることに気付いた:

q='q=%s;q%%repr(q)';q%repr(q)

インタラクティブなPythonシェルを許可すると、さらに短くなる可能性があります。

'%s;_%%repr(_)';_%repr(_)

pythonにはコマンドライン引数を取得する短い方法がないため、raw_input()を使用しました(これはまだかなり長いですが、

import sys;sys.argv[1]

使用法は次のとおりです。

echo "foobar.py" | python quinterpretter.py

または

python quinterpretter.py
<type filename and hit enter>

使用する短いクインを見つけましたが、これは私の古いバージョンです(後世のため):

i=open(raw_input()).read();a if i==(lambda x,y:x+repr((x,y))+y)('i=open(raw_input()).read();a if i==(lambda x,y:x+repr((x,y))+y)', ' else 1;exec(i)\n') else 1;exec(i)

%sを%rに置き換えて、reprを削除します。%rは生を意味し、基本的に彼は同じことです。
Loovjo

4

Javascriptを使用してファイルから正確に読み取ることはできません(HTML5 FileReaderを使用すると可能ですが、必要以上に複雑になります)。したがって、これはJavascriptプログラムを文字列として受け入れて実行する関数です。

これはおそらくゴルフほどではありませんが、とにかくここにあります:

Javascript、252

function c(p){q='\"';s='\\';a="function c(p){q='\"';s='\\';a=%;a=a.slice(0,17)+s+a.slice(17,24)+a[23]+a.slice(24);a=q+a.replace('%',q+a+q)+q;alert(a);}";a=a.slice(0,17)+s+a.slice(17,24)+a[23]+a.slice(24);a=a.replace('%',q+a+q);alert(a);if(p!=a)eval(p)}

Javascriptでクインを形成するためのより良いテクニックを知っている人がいれば教えてください。


1
あなたのコードと私のPerlソリューションに基づいて、135文字のJSソリューションを以下に投稿しました。インスピレーションのために+1!
イルマリカロネン

2
read p<p;read c<c;[ "$p" = "$c" ]||. ./c

45文字のsh(POSIXシェル)。実行するコードはファイル内にある必要があります./c

インタープリター自体のコードはファイル内にある必要がある./pため、チャレンジはそれを禁止しているようには見えませんが、私はちょっとごまかしたと思います。それとも、これは私の「言語」を「チューリング完全なプログラミング言語」としての資格を失いますか?

通常は外部実行可能ファイルですが、理論的にはシェルに組み込まれている可能性のあるツールを使用すると、コードを短縮できます。

cmp -s p c||. ./c

これは18文字です。この-sビットは、有効な(非自己)プログラムに対して常に印刷される行を抑制するためのものです。

そして、より簡潔な構文で上記を実行するシェル言語のバージョンをいつでも構築できます。

そして、入力が単一の「。」で構成される場合、いつでもプログラムをビルドできます。-または地獄、空の文字列-別のファイルの内容を通常のコードとして評価し、これをプログラミング言語と呼びます。したがって、空の文字列は、作成した言語での課題に対する解決策になります。実際、このような言語のインタープリターは次のとおりです。

read code; if [ "$code" ]; then eval "$code"; else . ./othercode; fi

上記のスクリプトが解釈する言語を使用すると、ソリューションは空の文字列になります。そして、コードの場所をハードコーディングする必要はもうありません。

問題?


2
チャレンジは、「あなたのプログラムはそれ自身のソースを読んではいけません」と言っています。
イルマリカロネン

Darnit、それからしばらく時間を無駄にしました。そして、私はあなたがあなたが除外する機能を使用してはならないと言っているのを見ます。これは、空の文字列機能に反します。この場合も、コンパイラ/インタープリター自体のコードが新しい言語で異なる動作を引き起こす場合、インタープリター機能を省略/変更する必要あります。いずれにせよ、私は誤fallを書くのが楽しかった。
TaylanUB

@TaylanUBまあ、実際には、インタープリター自体を除くすべての有効な$ langプログラムを解釈する必要があります。
FUZxxl

@FUZxxlはい、「sh + empty string」言語はsh(コードが空の文字列でない場合)と同等であり、それに記述された空の文字列プログラムもshコードを解釈し(これはに入れる必要があります./othercode)コードが空の文字列の場合は何もありません。ファイル./othercodeを呼び出すべきではありません。誤解を招きます。空の文字列言語で書かれたインタープリターが解釈するコードです。
タイランUB

2

JavaScript、135文字

function c(p){q='function c(p){q=%27Q%27;p!=unescape(q).replace(/Q/,q)?eval(p):alert()}';p!=unescape(q).replace(/Q/,q)?eval(p):alert()}

Peter OlsonのJavaScriptソリューションは、PerlソリューションをJSに移植しようとするきっかけになりました。彼のソリューションと同様に、このコードはc文字列を受け入れる関数を定義し、上記のコードと等しくない場合は評価します。

後知恵で明らかな解決策が見つかるまで、JavaScriptのバランスの取れた文字列区切り文字の欠如に対処するための良い方法を見つけるのに少し時間がかかりましたunescape()

便利なことに、私のコードにはバックスラッシュや二重引用符が含まれていないため、二重引用符で囲まれた文字列に安全に保存できます。これにより、テストが簡単になります。

e = "function c(p){q='function c(p){q=%27Q%27;p!=unescape(q).replace(/Q/,q)?eval(p):alert()}';p!=unescape(q).replace(/Q/,q)?eval(p):alert()}"
h = "alert('Hello, world!')"

eval(e)  // defines the function c()

c(h)     // evaluates h
c(e)     // does not evaluate e, alerts "undefined" instead

に置き換えalert()0、アラートの代わりに何もしないようにし、undefined13文字を節約できます。
ピーターオルソン

@PeterOlson:ええ、しかし、タスクは、それが自分自身を検出した場合、「あなたのプログラムは完全に無関係なことをすべきだ」と言っています。私はそれが何かをする必要があることを意味すると解釈します -できればユーザーに見えるものであると、私は推測します。それに、この方法のほうが好きです。:)(イェイ、外で雪が降っています!冬がついに来ました!)
イルマリカロネン

1
@Ilmari何もしないことは、Javascript IMHOの解釈とは無関係です。
FUZxxl

p=>...代わりに行くことができますfunction c(p)
-FireCubez

2

Common Lisp、59

#+~ #.(#:a)(defun L(p)(compile-file p))(push :~ *features*)
  • 新鮮なLisp REPLで、ファイルをコンパイルします(例sbcl --load
  • Lこれで、Common Lispファイルをコンパイルできる関数ができました
  • ただし、を呼び出すと(L <your file>)、ファイルの読み取り中にエラーが通知されます。

どうして?

なぜなら、初めて:~キーワードをにプッシュしたから*features*です。今、あなたの環境が知っている~機能で、リーダマクロは#+、評価時に~ 機能表現を、それは最初の時間をしたとして、それをスキップするのではなく、以下のフォームに成功し、読み込みます。あなたのファイルでは、次のような形式があり#.(#:a)、評価するように求められた(#:a)時に、リードタイムとコードが読み込まれると、結果の値を使用します。ただし(#:a)、インターンされていないsymbolに関連付けられている関数を呼び出します#:a。以来#:aインターンされ、それは任意の関数(すなわちないにバインドされていない新鮮なシンボルですfboundp)。エラー。


1

スキーム、48または51文字

Schemeは多くの異なる実装を備えた言語です。実装は最新のRnRSに準拠する必要がありますが、ミニマリズムが不足しているため、最新の作業標準(R6RS)は人気がありません。R7RSは、言語を2つに分割しながら、すぐに救済策としてリリースされる予定です。最初の言語は強力でミニマルで、2番目は実装間の相互運用性のための機能拡張を提供することを目的とした最初の言語のスーパーセットです。それまでは、SRFI(Scheme Requests For Implementation)に依存しています。SRFIは、一般的なタスクを移植可能な形で実行する手段を提供します(ホスト実装または手動(スキームで一般的)で実装される場合)。これはすべて、最初のコードスニペット(51文字)は、できる限り移植性を維持しながら、コマンドライン引数へのアクセスをSRFI-22(UNIXでスキームスクリプトを実行する)に依存していることを示しています。

(define(main x y)(case y(x => error)(else => load)))

またはもっと読みやすい:

(define (main current-file arg)
  (case arg
    [current-file => error]
    [else => load]))

2番目(48文字)は、(null環境で)評価できないファイルなしの解釈手段です。

(define(e)(write(eval(read)null-environment))(e))

またはもっと読みやすい:

(define (interpret)
  (write (eval (read) null-environment))
  (interpret))

インタープリターをコピーすると、コードは機能しません。
FUZxxl

1
ネストされた括弧を散文に含めるには、スキームの回答に任せてください。
チョイス

1

Groovy、13バイト

{Eval.me(it)}

これはGroovyのサブセットを解釈する必要があります。

テストケース:

p={Eval.me(it)}

p'''
    (0..37).each{println"1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU"[it..it+2]}
'''

p'''
    {Eval.me(it)}
'''

残念ながら、確かにbarfsしますが、完全にインタープリターのような方法でそうします。そして、かなり多くの入力に対して行います。


どの行で解釈するプログラムを読みますか?あなたのコードは興味深いですが、このタスクの有効な提出ではありません。
FUZxxl

私はエラーが「再帰制限を超えた」ようなものだと思いますか?
イルマリカロネン

1

Javascript ES6、45バイト

$=(_=prompt())=>eval(_==`$=${$};$()`?0:_);$()

まだ競争力がある!(thx @Downgoat)



ああ、私は標準のリリースをやめていました。2011年に実装が機能することは知りませんでした。回答テキストに説明とコミットへのリンクを含めることをお勧めします。
メゴ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.