Вирішіть проблему зупинки для Befinge


29

Давайте визначимо просту 2D мову, якій ми дамо неймовірно оригінальну назву befinge . Befinge має 5 інструкцій:

  • <>^v, як у більшості 2D езоланг, перенаправляйте вказівник інструкцій у відповідних напрямках.
  • . є неоперативним.

Покажчик інструкцій починається у верхньому лівому куті, йдучи праворуч. Якщо вказівник інструкції потрапить на край, програма зупиняється. Кожна програма Befinge очевидно або зупиниться, або піде в нескінченний цикл, який нічого не робить. Ось два приклади:

Припинення:

>.v
..<

Неприпинення:

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

Проблема зупинки не вирішується для мови, що завершує Тьюрінга, але саме для цієї. Ваше завдання - написати програму (або функцію), яка приймає як вхід рядок, що представляє програму befinge і повертає значення truthy або falsey залежно від того, зупиняється вона чи ні.

  • Можна припустити, що вхід буде складатися лише з цих символів і буде прокладений пробілами, щоб утворити прямокутник.
  • Ви можете використовувати будь-який набір з п'яти символів для вказівок (наприклад adws ).

Випробування

Припинення:

.

v>
>^

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

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

Неприпинення:

>..v
^..<

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

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

Це , тому найкоротша програма (в байтах) виграє.



Деякі тестові випадки, коли не потрапила б кожна стрілка, було б добре.
xnor

Тьюрінг довів, що проблема Холтінга не вирішена для жодної мови Тьюрінга, тому мені довелося скласти підробку, яка не була Тюрінгом завершеною. Мова, яка в кінцевому підсумку завжди припиняється, не є Тюрінг повною.
Esolanging Fruit

1
Ми також не маємо прикладів, коли шлях робить поворот не на 90 градусів на кшталт >..>.або ><.
xnor

2
@PyRulez Оскільки я хотів, щоб обробка направленого руху була частиною завдання.
Esolanging Fruit

Відповіді:


4

ES6 (JavaScript), 111, 101 байт

EDIT: змінив вихідні значення на true та false , замість Y і N , щоб відхилити ще 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та Nвиводити, як у JavaScript, вони обидва є truthy .
ბიმო

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

Ця програма приймає введення-виведення по-різному: будь ласка, скасуйте кожен рядок пробілом, включаючи останній. 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 Ба, я це зробив ще раз, я включив f=у число байтів, але не код ...
Ніл

1

SmileBASIC, 158 145 байт

Якщо одна і та ж стрілка зустрічається не один раз, програма ніколи не зупиняється. Коли покажчик інструкції передає стрілку, він замінюється іншим символом, що призведе до повернення функції 0, якщо вона буде досягнута знову. Якщо ІР виходить за межі, він повертається 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>, 1, 2, 3, 4= ., >, <, 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та розмір одного рядка s. Повертається, 1якщо ми не виходили за межі в 10 ^ 9 кроків і в nilіншому випадку. Насправді скільки кроків нам потрібно перевірити, щоб бути впевненими (count %),? Я думаю, що це більше того, як той самий НОП може проходити по горизонталі та вертикалі.

Можна назвати так (приймає звичайні рядки як аргументи, 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

Спробуйте в Інтернеті!

Дає правильну відповідь за ["<>"]


Я вважаю, що ви можете зберегти кілька байтів, змінивши функцію на повну програму. Ви можете замінити def f(x):з x=input()з 0 різницею байт, а потім видалити додатковий відступ (-8 байт), а потім замінити return xз exit(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і опускати пробіл.
Esolanging Fruit

Ви також можете використовувати varв багатьох місцях, якщо використовуєте Java 10.
Esolanging Fruit

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.