解决Befinge的暂停问题


29

让我们定义一种简单的2D语言,我们将使用难以置信的原始名称befinge。Befinge有5条指令:

  • <>^v与大多数2D esolang中一样,将指令指针重定向到各自的方向。
  • . 是无人操作。

指令指针从右上角的左上角开始。如果指令指针到达边缘,程序将暂停。每个Befinge程序显然都将停止或进入无能为力的无限循环。这是两个示例:

停止:

>.v
..<

非停止:

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

对于图灵完备的语言来说,停止问题无法解决,但对于这种语言来说,却是可以解决的。您的任务是编写一个程序(或函数),该程序将代表befinge程序的字符串作为输入,并根据是否停止而返回true或false值。

  • 您可以假设输入将仅包含这些字符,并用空格填充以形成一个矩形。
  • 您可以使用任意五个字符的集合作为说明(例如adws )。

测试用例

停止:

.

v>
>^

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

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

非停止:

>..v
^..<

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

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

这是,因此最短的程序(以字节为单位)获胜。



并非所有箭头都被击中的一些测试用例会很好。
xnor

Turing证明Halting问题对于任何一种Turing-Complete语言都无法解决,因此我不得不伪造一个图灵不完整的语言。最终将永远停下来的语言还不是图灵完整的。
硕果累累

1
我们也没有任何示例将路径非90度转弯,例如>..>.><
xnor

2
@PyRulez因为我希望处理定向运动成为挑战的一部分。
Esolanging Fruit '18

Answers:


4

ES6(JavaScript), 111,101字节

编辑:将输出值更改为truefalse,而不是YN,以减少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 !

您不仅可以像JavaScript那样使用YN作为输出,它们都是真实的
ბიმო

3

Python 2中116个 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

例如,第三个停止示例变为['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以外的任何内容。零被认为是暂停程序,其中包括通过将程序放置在稍微偏移的网格上而绕过程序的空间边界。

减少几分的一种简单方法是使用数字而不是> <^ v。但是我觉得那不值得。


A befinge halting problem needs a befunge solution.精确地 +1
Draco18s

1

Turtlèd,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不喜欢换行符,因为它使用网格作为字符的第二维。

在线尝试!

0表示永久循环,1表示暂停。

一般说明:

它将输入写在网格上,然后实际上遵循箭头围绕网格所做的路径,并用*替换每个箭头,同时还将方向保存在char var中。如果遇到一个*,即之前击中的箭头,该程序将不会停止,因此将char var设置为0,退出循环。否则,它将到达网格的末端并退出循环。它将写入char var。如果到达网格末尾,它将使用存储在char var中的方向返回到网格,并将char var设置为1,以暂停。如果char var实际上是0,而不是方向,则它不需要返回,因为它仍然存在,并将其设置为0。它清除网格,然后将char var写入,1以暂停,否则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

将输入作为二维字符数组,并返回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

>将输入视为二维字符数组是否允许使用格式不同的输入?(从平面字符串到数组也会占用字节)。
zeppelin

@zeppelin我的信念是允许这样做。例如,请参见meta.codegolf.stackexchange.com/q/2214/17602
尼尔

ReferenceError:未定义f
l4m2

@ l4m2 Bah,我又做了一次,f=将字节数包括在内,但不包括代码……
Neil

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替换break并减少缩进量。
破坏的柠檬

1
[-1,1][d=='v'] -> 2*(d>'>')-1[-1,1][d=='>'] -> 2*(d>'<')-1总共保存6个字节。
卡德

错误的答案["<>"]
feersum 2016年

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和一行的大小s。返回1如果我们没有超出10 ^ 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

蟒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

在线尝试!

给出正确的答案 ["<>"]


我相信您可以通过从功能更改为完整程序来节省几个字节。您可以替换def f(x):x=input()0字节的差异,然后删除多余的压痕(-8个字节),然后替换return xexit(x)(允许每间达成共识),另外2个字节。无论如何,不​​错的解决方案!
血液学

0

爪哇,477

我知道这并没有成功,n =并且可能打得更多,但是它实现了与其他答案使用的方法类似的方法,但是该方法使用哈希图执行查找。输入使用的符号> <^ v以及除no op以外的任何符号。输入来自args。

高尔夫

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);}}

放开

导入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);
    }
}

解释即将推出!


一件小事:你可以改变String a[],以String[]a和忽略的空间。
整理水果

你也可以用var在很多地方,如果你使用Java 10
Esolanging水果

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.