Résoudre le problème de l'arrêt pour Befinge


29

Définissons un langage simple 2D, que nous allons donner le nom d' origine incroyablement befinge . Befinge a 5 instructions:

  • <>^v, comme dans la plupart des esolangs 2D, redirigez le pointeur d'instruction dans leurs directions respectives.
  • . est un no-op.

Le pointeur d'instructions commence dans le coin supérieur gauche en allant vers la droite. Si le pointeur d'instruction atteint un bord, le programme s'arrête. Chaque programme Befinge s'arrêtera évidemment ou entrera dans une boucle infinie qui ne fait rien. Voici deux exemples:

Arrêt:

>.v
..<

Sans interruption:

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

Le problème d'arrêt n'est pas résolu pour un langage complet de Turing, mais il l'est pour celui-ci. Votre tâche consiste à écrire un programme (ou une fonction) qui prend en entrée une chaîne représentant le programme befinge et renvoie une valeur true ou falsey selon qu'elle s'arrête ou non.

  • Vous pouvez supposer que l'entrée ne comprendra que ces caractères et sera complétée par des espaces pour former un rectangle.
  • Vous pouvez utiliser n'importe quel ensemble de cinq caractères pour les instructions (par exemple adws ).

Cas de test

Arrêt:

.

v>
>^

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

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

Sans interruption:

>..v
^..<

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

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

Il s'agit de , donc le programme le plus court (en octets) l'emporte.



Certains cas de test où toutes les flèches ne sont pas touchées seraient utiles.
xnor

Turing a prouvé que le problème de Halting n'est résolu pour aucun langage Turing-Complete, j'ai donc dû en inventer un faux qui n'était pas Turing complet. Un langage qui finira toujours par s'arrêter n'est pas Turing complet.
Esolanging Fruit

1
Nous n'avons pas non plus d'exemples où le chemin fait un virage de non-90 degrés comme >..>.ou ><.
xnor

2
@PyRulez Parce que je voulais que le traitement du mouvement directionnel fasse partie du défi.
Esolanging Fruit

Réponses:


4

ES6 (JavaScript), 111, 101 octets

EDIT: a changé les valeurs de sortie en vrai et faux , au lieu de Y et N , pour réduire de 10 octets de plus

Golfé

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

Tester

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

Exemple de sortie

#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 !

Vous ne pouvez pas simplement utiliser Yet Nen sortie comme en JavaScript, ils sont tous les deux véridiques .
ბიმო

3

Python 2 , 116 105 octets

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

Essayez-le en ligne!

Le défi est vieux, mais je me suis dit que comme c'est le Python le plus court, je le posterai. L'entrée est une liste de chaînes, mais les caractères utilisés sont inhabituels.

> G
< B
v C
^ F
. L

Par exemple, le troisième exemple d'arrêt se transforme en ['LLLLCLLLL', 'LLLLGLLLC', 'LFLLBLLLL', 'LLLLLLLCB', 'LLLLLLLCL', 'LLLLFLLBL']. La sortie se fait via le code de sortie, 0 (succès) pour la non-interruption et 1 (erreur) pour l'arrêt. Tous les trucs ou astuces sont appréciés.


2

Befunge-98 (PyFunge) , 217 209 200 octets

#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 ^ @.!;>:'.-#;_

Essayez-le en ligne!

Un problème d'arrêt de befinge a besoin d'une solution de befunge. Renvoie 0 pour véridique et 1 pour falsey. Place l'entrée sur la grille à partir de 1,15 puis se déplace en haut, en remplaçant les flèches par des zéros. Dès que nous atteignons un zéro, nous savons qu'il boucle. Autre chose que> <^ v. et zéro est considéré comme interrompant le programme, ce qui inclut la frontière des espaces que nous contournons en le plaçant sur la grille légèrement décalée.

Un moyen facile de raser quelques bouchées serait d'utiliser des nombres au lieu de> <^ v. mais je ne pense pas que cela en vaille la peine.


A befinge halting problem needs a befunge solution.Précisément. +1
Draco18s

1

Turtlèd , 146 octets

!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],

Ce programme prend les E / S différemment: veuillez terminer chaque ligne avec un espace, y compris le dernier. Turtlèd n'aime pas les nouvelles lignes, car il utilise une grille pour sa deuxième dimension de personnages.

Essayez-le en ligne!

0 pour les boucles pour toujours, 1 pour les arrêts.

Explication générale:

Il écrit l'entrée sur la grille, puis il suit en fait le chemin que les flèches font autour de la grille, remplaçant chaque flèche par un * au fur et à mesure, enregistrant également la direction dans la var char. S'il rencontre un *, une flèche qu'il a frappée auparavant, le programme ne s'arrêtera pas, il définit donc la variable char sur 0, quitte la boucle. Sinon, il atteindra la fin de la grille et quittera la boucle. Il écrira le char var. S'il atteint la fin de la grille, il utilise la direction stockée dans le var var pour revenir à la grille et définit le var var sur 1, pour les arrêts. Si le caractère var était en fait 0, pas une direction, il n'a pas besoin de revenir en arrière, car il est toujours là, et il le remet à 0. Il efface la grille, puis écrit le var var, 1pour les arrêts, sinon 0.



1

JavaScript (ES6), 158 127 octets

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

Prend l'entrée comme un tableau de caractères à deux dimensions et retourne truepour l'arrêt et falsepour une boucle infinie. Fonctionne en définissant les caractères de direction visités sur ~s lors de leur traversée récursive. Edit: économisé 31 octets en mettant à jour mon vecteur de direction avant de revenir.

Abuser des caractères d'instruction ( 1=^ 4=< 5=. 6=> 9=v) me ramène à 101 octets:

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

> Prend l'entrée comme un tableau de caractères bidimensionnel Une entrée de format différent est-elle autorisée? (passer d'une chaîne plate à un tableau prend aussi des octets).
zeppelin

@zeppelin Je crois que cela est autorisé. Voir par exemple meta.codegolf.stackexchange.com/q/2214/17602 .
Neil

ReferenceError: f n'est pas défini
l4m2

@ Bah l4m2, je l'ai encore fait, j'ai inclus le f=nombre d'octets mais pas le code ...
Neil

1

SmileBASIC, 158 145 octets

Si la même flèche est rencontrée plus d'une fois, le programme ne s'arrêtera jamais. Lorsque le pointeur d'instruction passe devant une flèche, il est remplacé par un symbole différent, ce qui fera que la fonction retournera 0 si elle est à nouveau atteinte. Si l'IP sort des limites, elle renvoie 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

Prend l'entrée comme un tableau de chaînes. <any non-digit chracter>, 1, 2, 3, 4= ., >, <, v,^


0

Python 2, 182 octets

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

Prend un tableau de chaînes en entrée. Je dois jouer davantage au golf, mais pour l'instant, il est temps de souligner les élections.

Non golfé:

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

Hé, que se passe-t-il si vous retirez l'essentiel de l'essai et ne mettez que le c = m [y] [x] dans un essai et sauf? cela vous permettrait également de remplacer break par 1/0, ainsi que de réduire les retraits.
Destructible Lemon

1
[-1,1][d=='v'] -> 2*(d>'>')-1et [-1,1][d=='>'] -> 2*(d>'<')-1enregistrez un total de 6 octets.
Kade

Mauvaise réponse pour["<>"]
feersum

0

Clojure, 143 octets

#((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))

Une fonction avec 4 arguments d'état: position p, vitesse v, index de pas iet taille d'une ligne s. Renvoie 1si nous ne sommes pas sortis des limites en 10 ^ 9 étapes et nilsinon. En fait, combien d'étapes devons-nous vérifier pour être sûr (count %)? Je pense que c'est plus que cela car le même NOP peut être traversé horizontalement et verticalement.

Peut être appelé comme ceci (prend des chaînes normales comme arguments, getretourne nilen dehors des limites):

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

Les transitions d'états (+1, -1, + s, -s) sont codées dans le dictionnaire {\> 1\< -1\^(- s)\. v\v s}.


4 fois le nombre de caractères de la grille devrait être suffisant: si le pointeur revient au même caractère avec la même direction entrante, alors il est dans une boucle infinie.
Greg Martin

0

Python 2/3, 201 192 octets

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

Essayez-le en ligne!

Donne la bonne réponse pour ["<>"]


Je pense que vous pouvez économiser plusieurs octets en passant d'une fonction à un programme complet. Vous pouvez remplacer def f(x):par une x=input()différence de 0 octet, puis supprimer l'indentation supplémentaire (-8 octets), puis remplacer return xpar exit(x)(autorisé par méta-consensus ), pour 2 autres octets. Quoi qu'il en soit, belle solution!
Amphibological

0

Java, 477

Je sais que ce n'est pas gagnant, n = et peut probablement être joué plus, mais cela implémente une méthode similaire à ce que les autres réponses utilisent, mais celle-ci utilise hashmap pour effectuer des recherches. L'entrée utilise les symboles> <^ v et tout autre chose que pour le no op. L'entrée provient d'arguments.

GOLFED

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

NON GOLFE

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

Explication à venir bientôt!


Une petite chose: vous pouvez changer String a[]à String[]aet omettre l'espace.
Esolanging Fruit

Vous pouvez également utiliser vardans de nombreux endroits si vous utilisez Java 10.
Esolanging Fruit

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.