Brainfuckプログラムを確認する


17

さらに別のBrainfuck解析問題ですが、今回は...異なります。

あなたはさまざまな興味深い問題を解決するためにBrainfuckプログラムを作っているInfinite Monkeys Incorporatedで働いています(偶然にも、結局のところ、会社はランダムなプログラムを作っています)。ただし、Brainfuckのみを実行する高速チューリングマシンには、構文エラーに関する小さくて高価な問題があるようです。1つを作成すると、コンピューターが爆発します。それはおそらく設計上の欠陥かもしれませんが、それがなぜ起こるのかわからない人はいませんでした。

チューリングマシン(特に高速なマシン)は高価なので(結局、無限のRAMが必要です)、コードを実行する前にプログラムに構文エラーがないことを確認した方が良いでしょう。会社は大量のコードを実行するため、手動検証は機能しません。BrainfuckコードのSTDINを読み取るプログラムを作成し、プログラムに構文エラーがある場合(たとえば、]一致しないため構文エラーである場合)、終了ステータスを0(エラー)以外に設定して終了します[。プログラムが完全に正常であれば、終了ステータスを0に設定して終了します。

プログラムがを含む間違いを正しく認識していることを確認してください[]。別のコンピューターを爆発させたくないでしょうか?ああ、それができる限り短いことを確認してください-あなたのボスは短いプログラムの代金を払っています(彼は彼らが速いか何かを考えているからです)。ああ、Brainfuckでコーディングする必要はありません(実際、Brainfuckは終了コードをサポートしていないため、できません)-コードは通常のコンピューターで実行されます。

したがって、ご覧のとおり、あなたの仕事はBrainfuckプログラムが「有効」である(ペアの[]シンボルがある)かどうかを確認することです。Brainfuckプログラムには以外の文字を使用できる[]ため、他のコマンドがあるという理由だけでプログラムを拒否しないでください。最小のコードが勝ちますが、おそらくあなたはとにかくupvotesにもっと関心があるでしょう。


1
プロセス終了コードの設定を許可しない言語はどうですか?
ケンドールフレイ14年

1
@KendallFrey:シンプル、他のものを使用してください。または、GolfScriptにRubyコードを埋め込みます。おそらく、このブロックいくつかの難解なプログラミング言語を、しかし、よく...
コンラッド・ボロウスキ

1
失敗した場合、エラーコードを1以外に設定してもかまいません(もちろん0でない限り)。
マリヌス14年

@marinus:なぜそれが必要なのかわかりませんが、大丈夫だと思います。
コンラッドボロスキー14年

@GlitchMr:そのため、のGCD(a,b)代わりに使用できます0 != a || b
マリヌス14年

回答:


6

GolfScript、18文字

.{[]`?)},~](`91?./

このコードは、入力の角括弧のバランスが取れている場合、終了コード0で正常に実行されます(標準出力にゴミが出力されます)。そうでない場合、ゼロ以外の終了コードで失敗し、エラーメッセージをstderrに出力します。例:

(eval):2:in `/': divided by 0 (ZeroDivisionError)

または

(eval):1:in `initialize': undefined method `ginspect' for nil:NilClass (NoMethodError)

チャレンジではstdout / stderrへの出力については何も言わなかったので、これで十分だと思います。いずれの場合でも、これらをいつでもリダイレクトできます/dev/null

説明:

コード{[]`?)},は、入力から角括弧以外のすべて~を取り除き、結果をGolfScriptコードとして評価します。トリッキーな部分は、不均衡なブラケットがGolfScriptで完全に合法であることです(そして実際、私のコードには1つが含まれています!)ので、コードをクラッシュさせる他の方法が必要です。

私が使用しているトリックは、スタックの一番下に入力のコピーを残し、スタック全体を配列に収集し(不均衡を使用して])、最初の要素をオフにシフトすることです。この時点で、次の3つのことが起こります。

  • 入力が閉じられていない状態[で終了した場合、空の配列から要素をシフトしようとすると、インタープリターがクラッシュします(この場合、これはまさに必要なものです!)
  • 入力内のブラケットがバランスが取れている場合、シフトされた要素は元の入力文字列になります。
  • それ以外の場合(入力が開かれてい]ないか閉じられていない場合[)、配列になります。

元の14文字のエントリは、シフトされた値を文字列と比較しました。ネストされた配列の場合、クラッシュします。残念ながら、フラット(または特に空の)配列と文字列を比較することもGolfScriptで有効であることが判明したため、タックを切り替える必要がありました。

私の現在の提出は、代わりに、文字列から配列を伝えるために非常に強引な方法を使用します:それを無効にして、[(ASCIIコード91)の最初の出現を見つけようとします。変数は配列でした。その場合、ゼロをそれ自体で除算すると、目的のクラッシュがトリガーされます。

追伸 他の2つの18文字ソリューションは次のとおりです。

.{[]`?)},{.}%~](n<

そして

.{[]`?)},~]([n]+n<

残念ながら、「空の配列の問題」を解決する簡単な方法はまだ見つかりませんでした。


これはバランスがとれて][いますか?
ジャスティン14年

@Quincunx:失敗するはずです。
イルマリカロネン14年

しかし、受け入れられることが判明しました[[]。4文字のコストで修正したので、すべてのテストに合格しました。
イルマリカロネン14年

私があなたを正しく理解していれば、配列が空の場合にのみ文字列と配列を区別できない14文字のソリューションがありました。1+空の配列を空でない配列に、空でない配列を空でない配列に、文字列を文字列に変換します。
ピーターテイラー14年

@PeterTaylor:はい、そうでした.{[]`?)},~](n<。私はあなたを試してみました1+が、配列が何か含まれている必要があると思わ他の数(おそらくそれは、再帰的配列/文字列で文字を比較しようとすると、インタプリタがクラッシュすること)より。を使用n+しても機能しません。配列を文字列に強制するためです。[n]+ 動作しますが、それでも18文字になります。
イルマリカロネン14年

17

Brainfuck 76バイト

>>+[<+++++++++[->---------<]+>-[--[[-]<->]<[<[->-]>[<+]<]>]<[-<+>]+>,]<<[<+]

これは、角括弧のバランスが崩れてbfインタープリター/コンパイラーがランタイムに失敗し、それらの一部がそれを反映する終了コードを持っている場合に、結合から外れます。

eof = 0、ラッピング値、finitセル数が必要

Ubuntuでは、インタープリターbfsudo apt-get install bf)を使用できます

% echo '[[[]' | bf -n bf_matching.bf
Error: Out of range! Youwanted to '<' below the first cell.
To solve, add some '>'s at the beginning, for example.
an error occured
% echo $? 
5
% bf -n bf_matching.bf < bf_matching.bf
% echo $?
0

5
質問では不可能だと言われたが、Brainfuckの使い方が好きだ。
ライキン14年

ああすごい。正直驚いた。私はそれが不可能だと思いましたが、そうではありません。
コンラッドボロウスキ14年

1
@xfix:Brainfuckはチューリング完全なので、何でもできます(I / Oの制約が与えられます。)
マリナス14年

2
@marinusチューリングの完全性とは、すべての計算を実行できることを意味します。Brainfuck計算を計算するプログラムを実行し、実行後にメモリを検査することで結果を確認できるため、I / Oなしでチューリングが完了します。I / Oを使用しないBFは、ユーティリティを作成するのが難しいため、人々の興味を低下させます。例えば、私は自分のLispインタープリターを作ることはできなかったでしょう。
シルウェスター14年

14

Befunge 98 - 26の 31 20 19文字

~:']-!\'[-!-+:0`j#q

いくつかの大規模な条件を取り除きました。これで、プログラムは次のように機能します。

~:   read an input char and duplicate it

']-! push a 1 if the char is the ] char, 0 otherwise

\    swap the comparison value for the duplicated input char

'[-! push a 1 if the char is the [ char, 0 otherwise

-    subtract the two comparison values. If the second one is 1, the first is 0, 
     so the result is -1. Else if the second one is 0, the first is 1 and the result is
     1. Else, the first and the second are both 0 and the result is 0

+    Add the number to the counter (which is 0 if there is none already)

:0`  test if the counter is positive (that'd mean an invalid program). Pushes a 1 if 
     positive, 0 otherwise.

j#q  if the counter is positive, then this jumps to the q. Otherwise, it skips the q 
     and continues to the ~ at the beginning of the line. If there are no more chars in
     the input, then the IP will be sent back to the q. 

qプログラムを終了し、エラー値としてトップ値をポップします。エラー値は、が多すぎる場合は-1 1、]バランスが取れている場合は0、が多すぎる場合は正の負になり[ます。番号がある場合は、正、負、その後、多くのことを、その数の絶対値]のは、プログラムのバランスをとるために必要とされています。

編集:インクリメントとデクリメントを切り替えました。[カウンタをインクリメントするために]使用され、カウンタをデクリメントするために使用されます。それを切り替えることで、1文字を節約します。終了条件については、カウンターが負ではなく正であるかどうかを確認するだけでよいためです。


古いバージョン

~:'[-!j;\1+\#;']-!j;1-#;:0\`j#q

このコードは次のように機能します。

~    read one char of input
:    duplicate it
'[-! push 1 if the character is [, 0 otherwise
j    jump that number of characters
;    skip until next ;
\1+\ increment counter

similarily for ].

#q when end of input is reached, ~ reflects the IP back. q ends the program with the error value on the stack.

編集:これは][、のような入力を受け入れ、カウントが負になると終了するようになりました

:0\`j


距離間使用して、かなりいいです@JoKing []の両方との比較を行うと。
ジャスティン

6

J(38 35)

exit({:+.<./)+/\+/1 _1*'[]'=/1!:1[3

説明:

  • 1!:1[3:標準入力を読む
  • '[]'=/:最初の行が[入力のsのビットマスクであり、2番目の行がsである行列を作成します]
  • 1 _1*:最初の行に1を掛け、2番目の行に-1を掛けます。
  • +/:行列の列を合計し、文字ごとにデルタインデントを与えます
  • +/\:これらの合計を作成し、各キャラクターにインデントレベルを与えます
  • ({:+.<./):最終要素({:)および最小要素(<./)のGCDを返します。すべての中括弧が一致する場合、これらの両方が一致するはずな0ので、これはを返し0ます。中括弧が一致しない場合、ゼロ以外の値を返します。
  • exit:終了値をそれに設定して終了します。

ニースの内訳...
クリスCashwell

6

ルビー(64)

exit $<.read.tr('^[]','').tap{|x|0while x.gsub!('[]','')}.empty?

以前(68)は:

exit ARGF.read.tr('^[]','').tap{|x| 0 while x.gsub!('[]','')}.empty?

別の同等のソリューションは

exit $<.read.tr('^[]','').tap{|x|0while x.gsub!('[]','')}.size>0

size不均衡なブラケットの総数が256の倍数である場合、偽陰性(!!!)が発生するため、単独では使用できません。


これはcodegolfです。ここで空白を削除できると確信しています。Rubyはやや空白に敏感ですが、多くの場合それを無視します。まず、=演算子の近くの空白は必要ありません。
コンラッドボロスキー14年

より良いバージョン(sed + trソリューションに多少触発されています)。これよりずっと良くなるかどうかはわかりません。少なくとも4つの空白があります!
書き換え

1
それでも、それらのうち2つを削除できます。
コンラッドボロスキー14年

2
私は周りのスペース0が行くことができると思います。
マリヌス14年

素晴らしいスペーストリック、ありがとう!
書き直さ

5

Perl、30文字

あなたの基本的なPerl再帰的正規表現:

perl -0ne 'exit!/^(([^][]|\[(?1)\])*)$/'

ここで使用されるコマンドライン引数に不慣れな-0人のために:ファイル入力の目的で行末文字を設定することを許可します。-0引数なしで使用すると、行末文字がEOFに設定されます。-n入力(この場合はファイル全体)を$_事前に自動的に読み取ります。

正規表現が一致する場合は、真の値を返しますが、終了コードでは0に否定されます。それ以外の場合、falseの戻り値は終了コード1を生成します。


この30文字のソリューションに勝つためには、私の答えをよりよくゴルフしなければならないと思います。
ジャスティン14年

そこ。私のソリューションは、以前よりもはるかに短くなりました。いい解決策。+1
ジャスティン14年

4

bash(tr + sed)-42

[ -z `tr -Cd []|sed ":a;s/\[\]//g;t a"` ]

あなたがエラーメッセージを気にしないなら、あなたは間の最後のスペースを削除することができます`し、]長さ41を取得します。


私が何かを見逃さない限り、あなたは無用にcatandを使用します$()(また、と"[]"書くこともできます[])。私はこの答えを受け入れましたが、長さが改善されるまで、これを賛成するつもりはありません。短い間はbashの方がずっと短いかもしれません。
コンラッドボロスキー14年

実際、シェルスクリプトの作成方法はよくわかりません。これらのほとんどを機能させることはできません。$()バッククティックに置き換えて、"[]"-> []提案を行いました。
塩奈14年


1
私はこれを試して失敗した剣を持っている可能性がありますが、私は間違っていました。
潮ona 14年

3

Perl(56文字)

$/=0;$r=qr/[^][]*(\[(??{$r})\])*[^][]*/;<>=~m/^$r$/||die

明らかなPerlソリューション:再帰的正規表現。残念ながら、かなり冗長な構造です。


3

ハスケル(143)

import System.Exit
f=exitFailure
v c []|c==0=exitSuccess|True=f
v c (s:t)|c<0=f|s=='['=v(c+1)t|s==']'=v(c-1)t|True=v c t
main=getContents>>=v 0

to jgon:2つのガードを使用すると、if-then-elseよりも密度が高いようです。また、括弧が正しい順序であるかどうかをチェックするとは思わない( "] ["が合格)


このコメントは、今日指摘されたときにのみ見られました。コードを修正しましたが、うん、ガードは密度が高いようです(+1)。
jgon

3

C、73 64文字

breadboxからの提案に感謝します(ただし、これにはおそらくリトルエンディアンが必要です)。

i;main(c){while(read(0,&c,1)*(i+1))i+=(c==91)-(c==93);return i;}

使い方:

  • 暗黙的なintグローバルiは0に初期化されます
  • c取得する暗黙のintになりますargc(1に初期化されますが、上位ビットが設定されていない限り、気にしません)
  • read(0,&c,1)単一の文字をcの下位バイトに読み込み(リトルエンディアンアーキテクチャ上)、EOFで0を返します。i+1 != 0釣り合った括弧の引用が-1にならない限り、それらを一緒に乗算すると、(安全な)ブール型ANDとして機能します。&&
  • c==911と評価さ'['れ、c==931に評価']'。(少し厄介なビットをいじるトリックがあるかもしれませんが、それはもっと小さくなりますが、何も考えられません。)
  • return iバランスが取れている場合はステータスコード0で終了し、バランスが取れていない場合はゼロ以外で終了します。-1を返すことは技術的にPOSIXに違反しますが、実際には誰も気にしません。

前のバージョン:

main(i){char c;i=0;while(read(0,&c,1)*(i+1))i+=(c==91)-(c==93);return i;}

getchar()読み取りの代わりに使用すると、コードが短縮され、変数のint代わりに(暗黙)を使用できるようになりますchar。また、グローバルは自動的にゼロに初期化されることに注意してください。
パンボックス14年

おかげで、getchar()を忘れてしまいました。ただし、グローバルinitがどのように役立つかはわかりません。グローバルint iを定義すると、暗黙的なargcを使用するよりも多くの文字が必要になります。
ふわふわ14年

1
グローバルは暗黙的でもあります。関数の外側c;は、グローバルintを定義します。
パンボックス14年

一方、getchar(c)は、少なくともこのアプローチを使用して短くなることはありません。何らかの方法で> = 0をテストする必要があり、read()に渡されるcの暗黙のintは保証されないためです。エンディアンのために動作します。
ふわふわ14年

どう][?バランスが取れていないと思います。少なくとも1回はマイナスになるかどうかを追跡する必要はありませんか?
VSZ

2

ルア、56

os.exit(("["..io.read"*a".."]"):match"^%b[]$"and 0 or 1)

"^%b[]$"これは何ですか?説明できる?確かに、これは正規表現ではありませんか?
ランチャー14年

@Cruncher:そうではありません。これは正規表現ではなくLuaパターンです(Luaパターンは正規表現に似ていますが、そうではありません)。この場合、文字列の始まり(^)、バランスのとれたセット、[および]その間にあるもの(%b[])、および文字列の終わり()に一致し$ます。
コンラッドボロスキー14年

1

GTB、55

0→O:0→X[`I@I="[":X+1→X@I="]":X-1→X@X<0:1→O@!!Ig;e]l;e~O

ミス []

使用する 0停止ためにします。


1

MATHEMATICA、88文字

s = "[ [ my crazy code ] [ don't explode please! [] [ :)Ahh) ]  [] []]]";

r=StringReplace;
StringLength@FixedPoint[r[#,"[]"-> ""]&,r[s,Except@Characters["[]"]-> ""]]

関数s name like RegularExpression`を使用するとStringLength、Mathematicaでテキストコードのゴルフコンテキストを獲得することはできません!:)
ムルタ14年

あなたが言っていることを知っています:) ToCharacterCodeそれよりもはるかに長いordです... PS:終了コードの設定はどうですか?
アジャシャ

Length[StringCases[s,"["|"]"]//.{x___,"[","]",y___}:>{x,y}]
alephalpha

1

ルビー、 59 58

開始ブラケットと終了ブラケットをスキャンし[、1および]-1としてカウントし、カウントが0を下回ると終了します。

b=0
$<.read.scan(/\]|\[/){exit 1if(b+=92-$&.ord)<0}
exit b

1
投票して、1文字短くしました(要求に応じて空白を削除しexit 1ました)。
コンラッドボロスキー14年

1

Hassium、104バイト

func main(){l=0;r=0;b=input();foreach (c in b){if(c=="[")l++;if(c=="]")r++;}if(!(r==l))exit(1);exit(0);}

フル(無効になりますが(入力としてオンラインインタプリタでは動作しません))拡張し、ここで


1

チューリング機械コード、286 276バイト

繰り返しますが、ここで定義したルールテーブルの構文を使用しています。

0 * * l 1
1 _ ! r Q
5 _ _ r 5
5 * * * W
W [ ! l E
W ] ! l T
W _ _ l I
W * ! r *
E ! ! l *
E * * * R
R _ [ r O
R * * l *
T ! ! l *
T * * * Y
Y _ _ r U
Y * * l *
U [ _ r O
U ! ! * halt-err
I ! ! l *
I _ _ r halt
I * * l halt-err
O ! ! r Q
O _ _ l I
O * * r *
Q ! ! r *
Q * * * W

halt入力を受け入れhalt-errて拒否する状態で終了します。


halt-errhalt*たとえば、より短くすることができます。
エリックアウトゴルファー


1

ハスケル(167、159

これは主に楽しみのためでしたが、短くする方法についての提案があれば、それらを聞いてうれしいです:)

import System.Exit
p x y b|b=x|True=y
main=getContents>>=(return.all (>=0).scanl (\v->p (v-1) (v+1).(==']')) 0.filter (`elem`"[]"))>>=p exitSuccess exitFailure

編集:コメントで指摘された問題を修正(11バイト追加)。

編集2: user13350に触発されたガードを使用して、8バイトを削除して、述語をテストするための補助関数を作成しました。



@ user202729それは素晴らしい点です、それは非常に不注意でした。それが今修正されていると確信しています。
jgon

1

スタックス14 11 文字

╬Äτ↔EªÉs «Ü

実行してデバッグする

-3バイトの@recursiveのクレジット。

同等のASCII:

.[]Y|&{yz|egp!

を除くすべての文字を[]削除[]し、文字列が変更されなくなるまで削除します。1最終文字列が空の場合に戻ります。


1
いいね を使用.[]|&して文字をフィルタリングし、11
再帰
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.