Befingeの停止問題を解決する


29

単純な2D言語を定義してみましょう。信じられないほど元の名前befingeを与えます。Befingeには5つの指示があります。

  • <>^v、ほとんどの2Dエソランのように、それぞれの方向に命令ポインターをリダイレクトします。
  • . ノーオペレーションです。

命令ポインタは、左上隅から右に向かって始まります。命令ポインターが端に達すると、プログラムは停止します。すべてのBefingeプログラムは明らかに停止するか、何もしない無限ループに入ります。以下に2つの例を示します。

停止:

>.v
..<

ノンハルティング:

>....v
..v..<
..>v..
^..<..

停止の問題はチューリング完全言語では解決できませんが、この問題では解決できます。タスクは、befingeプログラムを表す文字列を入力として受け取り、停止するかどうかに応じてtrueまたはfalseの値を返すプログラム(または関数)を作成することです。

  • 入力はこれらの文字のみで構成され、スペースを埋めて長方形を形成すると想定できます。
  • 指示には5文字の任意のセットを使用できます(例:)adws

テストケース

停止:

.

v>
>^

....v....
....>...v
.^..<....
.......v<
.......v.
....^..<.

v<>v>v^
>v^>^>v
<>>^v<v
v^<>v^<

ノンハルティング:

>..v
^..<

>v<
v<.
>v.
v<.
>.^

>.>.>.v
.><.<.<

これはであるため、最短のプログラム(バイト単位)が優先されます。



すべての矢印がヒットするわけではない一部のテストケースが適切です。
xnor

チューリングは、ホールティングの問題はチューリング完全言語では解決できないことを証明したため、チューリング完全ではない偽の問題を作成する必要がありました。最終的に常に停止する言語は、チューリング完全ではありません。
エソランジングフルーツ

1
また、パスが>..>.やのような90度以外の方向に曲がる例もありません><
xnor

2
@PyRulez方向性のある動きを処理することがチャレンジの一部になりたかったからです。
エソランジングフルーツ

回答:


4

ES6(JavaScript)、 111、101バイト

編集:出力値をYおよびNの代わりにtrueおよびfalseに変更して、さらに10バイト削る

ゴルフ

F=(I,M=[...I],c=0,i)=>(i={j:v=I.search`\n`+1,k:-v,h:-1,l:1,q:i,0:0}[M[c]])?F(I,M,c+i+(M[c]=0),i):i!=0

テスト

F=(I,M=[...I],c=0,i)=>(i={j:v=I.search`\n`+1,k:-v,h:-1,l:1,q:i,0:0}[M[c]])?F(I,M,c+i+(M[c]=0),i):i!=0  

//Alphabet Map
tr={
'<':'h',
'>':'l',
'^':'k',
'v':'j',
'.':'q',
'\n':'\n'
};

//Test
T=(I,A)=>{
console.log({"Y":"#Halting","N":"#Non-Halting"}[A]);
console.log("I=\n",I,"\nF(I)=",O=F([...I].map(s=>tr[s]).join('')));
console.log('NY'[O*1] == A ? "OK !" : "NOT OK !");
}

//Halting
T(
`>.v
..<`
,'Y');

//Non-Halting
T(
`>....v
..v..<
..>v..
^..<..`
,'N');

//Halting
T(
`.`
,'Y')

//Halting
T(
`v>
>^`
,'Y');

//Halting
T(
`....v....
....>...v
.^..<....
.......v<
.......v.
....^..<.`
,'Y');

//Halting
T(
`v<>v>v^
>v^>^>v
<>>^v<v
v^<>v^<`
,'Y');

//Non-Halting
T(
`>..v
^..<`
,'N');

//Non-Halting
T(
`>v<
v<.
>v.
v<.
>.^`
,'N');

//Non-Halting
T(
`>.>.>.v
.><.<.<`
,'N');

サンプル出力

#Halting
I=
>.v
..< 
F(I)= true
OK !    

#Non-Halting
I=
>....v
..v..<
..>v..
^..<.. 
F(I)= false
OK !

#Halting
I=
 . 
F(I)= true
OK !

#Halting
I=
v>
>^ 
F(I)= true
OK !

#Halting
I=
....v....
....>...v
.^..<....
.......v<
.......v.
....^..<. 
F(I)= true
OK !

#Halting
I=
v<>v>v^
>v^>^>v
<>>^v<v
v^<>v^< 
F(I)= true
OK !

#Non-Halting
I=
>..v
^..< 
F(I)= false
OK !

#Non-Halting
I=
>v<
v<.
>v.
v<.
>.^ 
F(I)= false
OK !

#Non-Halting
I=
>.>.>.v
.><.<.< 
F(I)= false
OK !

あなただけ使用することはできませんYし、NJavaScriptでのように出力として、彼らは両方ともtruthyあります
ბიმო

3

パイソン2116の 105バイト

x=1
X=Y=y=0
H=[]
G=input()
while(X,Y,x,y)not in H:H+=[(X,Y,x,y)];C=ord(G[Y][X]);x=C%3-1;y=C%5-1;X+=x;Y+=y

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

課題は古いですが、これは最短のPythonなので、投稿します。入力は文字列のリストですが、使用される文字は珍しいです。

> G
< B
v C
^ F
. L

たとえば、3番目の停止例はに変わり['LLLLCLLLL', 'LLLLGLLLC', 'LFLLBLLLL', 'LLLLLLLCB', 'LLLLLLLCL', 'LLLLFLLBL']ます。出力は、終了コード、停止しない場合は0(成功)、停止する場合は1(エラー)を介して行われます。ヒントやコツをいただければ幸いです。


2

Befunge-98(PyFunge)217 209 200バイト

#v10dpf1dp12dp3dpk
 >#v~:a-#v_$10dp1dg1+1dp >
v  >10dp;>0dg1dgp0dg1+0dp^;f1dp
>0dg1dgg:'^-#v_n1-v
^<v01_v#!->':<
  <   >:'<-#v_01-0>   v
v^pd1+gd3gd1[:'v-#v_01>3dp2dpndg1dgp
>0dg2dg+0dp ^ @.!;>:'.-#;_

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

ベフィンジュ停止問題には、ベファンジソリューションが必要です。真実の場合は0、偽の場合は1を返します。入力をグリッドに1,15から配置し、次に上に移動して、矢印をゼロに置き換えます。ゼロになるとすぐにループすることがわかります。> <^ v以外のすべて。ゼロはプログラムを停止するものと見なされます。これには、プログラムをグリッド上にわずかにオフセットして配置することで、プログラムの周囲にあるスペースの境界が含まれます。

数バイトを削る簡単な方法の1つは、> <^ vの代わりに数字を使用することです。しかし、それだけの価値があるとは思わない。


A befinge halting problem needs a befunge solution.正確に。+1
Draco18s

1

タートルード、146バイト

!u[*.[ r+.]l[ l]dr_+]#*#[ u]d[ (.r)(>.r{.r}@>)(v.d{.d}@v)(<.l{.l}@<)(^.u{.u}@^)(*@0' )],@1(0@0)(v' d)(<' r)(>' l)(^' d)[ u]d[ l]r[ [ r]l[ ' l]dr],

このプログラムはI / Oを異なる方法で取ります。各行を最後の行も含めてスペースで終了してください。Turtlèdは、文字の2番目の次元にグリッドを使用するため、改行を好みません。

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

永久ループの場合は0、停止の場合は1。

一般的な説明:

入力をグリッドに書き込み、実際に矢印がグリッドの周りをたどるパスをたどり、各矢印を*に置き換えて、char変数に方向を保存します 前にヒットした矢印である*に遭遇した場合、プログラムは停止しないため、char varをに設定し0、ループを終了します。それ以外の場合は、グリッドの最後にヒットし、ループを終了します。char varを書き込みます。グリッドの最後に達した場合、char varに格納されている方向を使用してグリッドに戻り、char varをに設定し1て停止します。char varが実際には方向ではなく0だった場合、まだそこにあるので戻る必要はなく、に戻し0ます。グリッドをクリアしてから、1停止するためにchar varを書き込みます0



1

JavaScript(ES6)、158 127バイト

f=(a,x=0,y=0,d=1,e=0,c=a[y]&&a[y][x])=>c<'~'?(c>'.'&&(a[y][x]='~',d=(c=='>')-(c=='<'),e=(c=='v')-(c=='^')),f(a,x+d,y+e,d,e)):!c

入力を2次元の文字配列として受け取りtrue、停止falseして無限ループに戻ります。訪問した方向の文字を~再帰的にトラバースするときにsに設定することで機能します。編集:再帰する前に方向ベクトルを更新して31バイトを保存しました。

命令文字(1=^ 4=< 5=. 6=> 9=v)を乱用すると、101バイトになります。

f=(a,x=0,y=0,d=1,e=0,c=a[y]&&a[y][x])=>+c?(c-5&&(a[y][x]='0',d=~-c%4,e=~-(c>>2)),f(a,x+d,y+e,d,e)):!c

>入力を2次元文字配列として受け取ります。異なる形式の入力は許可されますか?(フラットな文字列から配列に移動すると、バイトもかかります)。
ツェッペリン

@zeppelin私の考えでは、これは許可されています。たとえばmeta.codegolf.stackexchange.com / q / 2214/17602を参照してください。
ニール

ReferenceError:fは定義されていません
l4m2

@ l4m2ああ、もう一度やっf=た、バイトカウントには含めたがコードは含めなかった...-
ニール

1

SmileBASIC、158 145バイト

同じ矢印に複数回遭遇した場合、プログラムは停止しません。命令ポインタが矢印を通過すると、別のシンボルに置き換えられます。これにより、関数は再び到達すると0を返します。IPが範囲外になると、1を返します。

DEF H P@L
C=VAL(P[Y][X])IF C>8THEN?0RETURN
IF C THEN D=C-1P[Y][X]="9
X=X+!D-(D==1)Y=Y+(D==2)-(D>2)IF X+1&&Y+1&&Y-LEN(P)&&X-LEN(P[0])GOTO@L
?1
END

入力を文字列の配列として受け取ります。<any non-digit chracter>1234= .><v^


0

Python 2、182バイト

m,v,d,x,y=input(),[],'>',0,0
try:
 while 1:
  if[x,y]in v:print 0;break
  c=m[y][x]
  if c!='.':d=c;v+=[[x,y]]
  if d in'><':x+=[-1,1][d=='>']
  else:y+=[-1,1][d=='v']
except:print 1

入力として文字列配列を受け取ります。私はこれをもっとゴルフしなければなりませんが、今は選挙を強調する時です。

ゴルフをしていない:

input = input()

visited = [  ] 

dir = ">"
x=0
y=0

try:
    while True:
        if[x,y]in visited:print False;break
        char=input[y][x]
        if char!=".":
            dir=char
            visited+=[[x,y]]

        if dir==">":
            x+=1
        if dir=="<":
            x-=1
        if dir=="v":
            y+=1
        if dir=="^":
            x-=1
except:
    print True

ちょっと、主な部分を試してみて、c = m [y] [x]だけを試してみるとどうなるでしょう?これにより、ブレークを1/0に置き換えたり、インデントを減らしたりすることもできます。
破壊可能なレモン

1
[-1,1][d=='v'] -> 2*(d>'>')-1[-1,1][d=='>'] -> 2*(d>'<')-1合計6バイトを節約します。
ケード

間違った回答["<>"]
feersum

0

Clojure、143バイト

#((fn[p v i s](if-let[v({\> 1\< -1\^(- s)\. v\v s}(get % p))](if(neg? i)1(recur(+ p v)v(dec i)s))))0 1 1e9(+(count(take-while(set"<>v^.")%))1))

4つの状態引数を持つ関数:位置p、速度v、ステップインデックスi、および1行のサイズs110 ^ 9ステップなどで範囲外に出なかった場合に戻りますnil。実際に、確認するためにチェックする必要があるステップ数は(count %)?同じNOPを水平および垂直にトラバースできるため、それ以上のものだと思います。

このように呼び出すことができます(通常の文字列を引数として受け取り、範囲外の場合にget戻りますnil):

(def f #( ... ))
(f ">....v\n..v..<\n..>v..\n^..<..")
(f "v>\n>^")
(f "....v....\n....>...v\n.^..<....\n.......v<\n.......v.\n....^..<.")

状態遷移(+ 1、-1、+ s、-s)は辞書にエンコードされ{\> 1\< -1\^(- s)\. v\v s}ます。


グリッド文字の数の4倍で十分です。ポインターが同じ入力方向で同じ文字に戻る場合、無限ループにあります。
グレッグマーティン

0

Python 2 / 3、201 192バイト

def f(x):
 X=Y=b=0;a=1;D={}
 while len(x)>Y>-1<X<len(x[Y]):
  try:
   a,b={'>':(1,0),'^':(0,-1),'<':(-1,0),'v':(0,1)}[x[Y][X]]
   if(X,Y)in D:return 0
  except:0
  D[X,Y]=0;X+=a;Y+=b
 return 1

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

の正解を与える ["<>"]


関数から完全なプログラムに変更することで、数バイトを節約できると思います。0バイトの差で置き換えdef f(x):x=input()から、余分なインデント(-8バイト)を削除し、さらに(メタコンセンサスごとに許可された)別の2バイトで置き換えることreturn xexit(x)できます。とにかく、素敵なソリューション!
Amphibological

0

Java、477

私はこれが勝っていないことを知っています、n =そしておそらくもっとゴルフすることができますが、他の答えが使用するものと同様の方法をインプリメントしますが、これはルックアップを実行するためにハッシュマップを使用します。入力は、シンボル> <^ vおよびno op以外のものを使用しています。入力は引数を介して送られます。

ゴルフド

import java.util.*;interface B{static void main(String[]a){HashMap<String,Byte>h=new HashMap<>();int x,y=0;for(String s:a){x=0;for(char c:s.toCharArray()){if("><^v".indexOf(c)>-1)h.put(x+","+y,(byte)c);x++;}y++;}x=0;y=0;int d=0;int D=0;while(x>-1&&x<a[0].length()&&y<a.length&&y>-1){Byte v=h.get(x+","+y);if(v!=null){if(v==0){System.out.print(0);return;}d=(v<85)?"<>".indexOf(v)*2-1:0;D=(v>84)?"^v".indexOf(v)*2-1:0;}h.replace(x+","+y,(byte)0);x+=d;y+=D;}System.out.print(1);}}

無形

import java.util。*;

interface B{
    static void main(String a[]) {
        HashMap<String, Byte> h = new HashMap<>();
        int x, y = 0;
        for(String s : a) {
            x = 0;
            for(char c : s.toCharArray()) {
                if ("><^v".indexOf(c) > -1) h.put(x + "," + y, (byte) c);
                x++;
            }
            y++;
        }
        x = 0;
        y = 0;
        int d = 0;
        int D = 0;
        while(x > -1 && x < a[0].length() && y < a.length && y > -1) {
            Byte v = h.get(x + "," + y);
            if(v != null) {
                if(v == 0) {System.out.print(0); return;}
                d = (v < 85) ? "<>".indexOf(v)*2-1 : 0;
                D = (v > 84) ? "^v".indexOf(v)*2-1 : 0;
            }
            h.replace(x + "," + y, (byte) 0);
            x += d;
            y += D;
        }
        System.out.print(1);
    }
}

説明はすぐに来ます!


1つの小さなこと:スペースに変更String a[]String[]aて省略できます。
エソランジングフルーツ

使用することもできvarますが、Javaの10を使用する場合多くの場所で
Esolangingフルーツ

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.