Im Sinne von Lösen des Halteproblems für Befinge definieren wir eine andere 2D-Sprache namens Modilar SNISP . Modilar SNISP hat die folgenden sechs Anweisungen:
\
lenkt den Befehlszeiger wie folgt:- Wenn Sie sich von oben nähern, gehen Sie nach rechts.
- Wenn Sie sich von rechts nähern, gehen Sie nach oben.
- Wenn Sie sich von unten nähern, gehen Sie nach links.
- Wenn Sie sich von links nähern, gehen Sie nach unten.
/
lenkt den Befehlszeiger wie folgt:- Wenn Sie sich von oben nähern, gehen Sie nach links.
- Wenn Sie sich von links nähern, gehen Sie nach oben.
- Wenn Sie sich von unten nähern, gehen Sie nach rechts.
- Wenn Sie sich von rechts nähern, gehen Sie nach unten.
!
überspringt die nächste Anweisung.@
schiebt den IP-Speicherort und die IP-Richtung auf den Aufrufstapel.#
Entfernt einen IP-Speicherort und eine IP-Richtung aus dem Aufrufstapel, stellt sie wieder her und überspringt dann die nächste Anweisung. Wenn der Aufrufstapel leer ist, wird die Ausführung angehalten..
tut nichts.
Der Anweisungszeiger beginnt in der oberen linken Ecke und geht nach rechts. Wenn es jemals das Spielfeld verlässt, wird die Ausführung angehalten.
Modilares SNISP kann nicht leistungsfähiger sein als ein PDA , da seine einzige Quelle für unbegrenzten Speicher ein Stapel (der Aufrufstapel) mit einem endlichen Alphabet (die Menge aller IP-Paare (Standort, Richtung)) ist. Das Problem des Anhaltens ist für PDAs entscheidbar , daher sollte diese Herausforderung immer möglich sein.
Die Herausforderung
Ihr Ziel ist es, ein Programm zu schreiben, das eine Zeichenmatrix verwendet, die ein Modilar-SNISP-Programm darstellt, und eine von zwei unterschiedlichen Ausgaben zurückgibt, je nachdem, ob es angehalten wird oder nicht.
Dies ist Code-Golf , also gewinnt das kürzeste gültige Programm (gemessen in Bytes ).
Spezifikationen
- Die Art und Weise, wie Sie eine Zeichenmatrix verwenden, ist flexibel: Eine durch Zeilenumbrüche getrennte Zeichenfolge, ein Zeichenfolgenarray, ein Array von Zeichenarrays, ein 2D-Zeichenarray, ein flaches Zeichenarray mit einer Ganzzahl, die die Breite darstellt usw. sind zulässig. Die Testfälle entscheiden sich für die erste dieser Optionen.
- Sie können davon ausgehen, dass die Eingabematrix rechteckig ist (Sie müssen also keine kurzen Zeilen auffüllen) und eine Länge und Breite ungleich Null hat.
- Sie können zwei verschiedene Ausgänge auswählen, nicht nur wahr / falsch.
- Sie können davon ausgehen , dass die Eingangsmatrix nur gültiger Befehle bestehen (
\
,/
,!
,@
,#
, und.
). - Wenn ein Befehl "die nächste Anweisung überspringen" soll, können Sie davon ausgehen, dass eine nächste Anweisung übersprungen werden muss. Insbesondere wird es niemals auftreten, wenn (1) es am Rand des Spielfelds liegt und (2) sich die IP senkrecht zu diesem Rand bewegt, so dass der "nächste Befehl" danach außerhalb des Spielfelds liegen würde.
Testfälle
Das folgende Snippet kann zum Testen von Programmen in der Sprache verwendet werden. Beachten Sie, dass es etwas freizügiger ist als die hier angegebene tatsächliche Spezifikation (z. B. erlaubt es andere Zeichen .
als No-Ops).
function htmlEscape(t){let i=document.createElement("span");return i.innerText=t,i.innerHTML}function tick(){snisp.tick(),snisp.update()}function run(){runButton.style.display="none",stopButton.style.display="",code.style.display="none",executionArea.style.display="",snisp.initialize(),intervalId=setInterval(tick,INTERVAL_MS)}function stop(){runButton.style.display="",stopButton.style.display="none",code.style.display="",executionArea.style.display="none",clearInterval(intervalId)}let TICKS_PER_SECOND=5,INTERVAL_MS=1e3/TICKS_PER_SECOND,runButton=document.getElementById("run-button"),stopButton=document.getElementById("stop-button"),code=document.getElementById("code"),executionArea=document.getElementById("execution-display"),intervalId,snisp={x:null,y:null,direction:null,callStack:null,stopped:null,playfield:null,padRows:function(){let t=Math.max(...this.playfield.map(t=>t.length));for(let i=0;i<this.playfield.length;i++)this.playfield[i]=this.playfield[i].padEnd(t,".")},initialize:function(){this.x=0,this.y=0,this.direction="right",this.callStack=[],this.stopped=!1,this.playfield=code.value.split("\n"),this.padRows(),this.update()},getCurrentChar:function(){let t=this.playfield[this.y];if(void 0!=t)return t[this.x]},backslashMirror:function(){let t={up:"left",right:"down",down:"right",left:"up"};this.direction=t[this.direction]},slashMirror:function(){let t={up:"right",right:"up",down:"left",left:"down"};this.direction=t[this.direction]},forward:function(){switch(this.direction){case"up":this.y-=1;break;case"down":this.y+=1;break;case"left":this.x-=1;break;case"right":this.x+=1;break;default:throw"direction is invalid"}},pushState:function(){this.callStack.push({x:this.x,y:this.y,direction:this.direction})},restoreState:function(){let t=this.callStack.pop();void 0!=t?(this.x=t.x,this.y=t.y,this.direction=t.direction):this.stopped=!0},tick:function(){if(this.stopped)return;let t=this.getCurrentChar();if(void 0!=t){switch(t){case"\\":this.backslashMirror();break;case"/":this.slashMirror();break;case"!":this.forward();break;case"@":this.pushState();break;case"#":this.restoreState(),this.forward()}this.forward()}else this.stopped=!0},generatePlayfieldHTML:function(t,i){let e=[];for(let n=0;n<this.playfield.length;n++){let s=[],l=this.playfield[n];for(let e=0;e<l.length;e++){let a=htmlEscape(l[e]);e==t&&n==i&&(a='<span class="highlight">'+a+"</span>"),s.push(a)}e.push(s.join(""))}return e.join("<br>")},update:function(){let t=[];for(let i=0;i<this.callStack.length;i++){let e=this.callStack[i];t.push(this.generatePlayfieldHTML(e.x,e.y))}t.push(this.generatePlayfieldHTML(this.x,this.y));let i=t.join("<br><br>");executionArea.innerHTML=i}};
#code{font-family:monospace;}#execution-display{font-family:monospace;white-space:pre;}.highlight{background-color:yellow;}
<b>Code:</b><br/><textarea id="code" width="300" height="300"></textarea><br/><button id="run-button" onclick="run()">Run</button><button id="stop-button" onclick="stop()" style="display: none;">Stop</button><br/><div id="execution-display"></div>
Die ungolfed Form finden Sie hier .
Anhalten
.
Das kleinstmögliche Programm. Geht rechts raus.
\\
\/
Windet sich um das Programm und geht nach oben.
.\./.\
.\!/./
Geht in einer Schleife. Windet sich durch einen Teil der Strecke in zwei verschiedene Richtungen.
@\!/#
.\@/#
Verwendet alle sechs Befehle.
@.@.@.@.@.@.@.@.@.#
Die Ausführungszeit dieses Programms ist exponentiell in der Anzahl der Wiederholungen von @.
, aber es wird immer noch angehalten.
Nicht anhalten
!/\
.\/
Ich glaube, dies ist die kürzeste Endlosschleife.
@!\\#/@\!\
//@//.#./.
.\#.!\./\.
#.\!@!\@//
/..@.@\/#!
\.@.#.\/@.
Dies windet sich um die Spur und erzeugt gelegentlich Stapelrahmen, bevor es schließlich in einen Zyklus gerät, der unendlich Stapelrahmen erzeugt. Nicht alle Befehle werden tatsächlich verwendet.
.!/@.@.@.@.@.\
/.@.@.@.@.@.@/
\@.@.@.@.@.@.\
/.@.@.@.@.@.@/
.@\@.@.@.@.@.\
\.@.@.@.@.@.@/
Erstellt weiterhin Stapelrahmen, aber keiner von ihnen kehrt jemals zurück.
quelle
Antworten:
Python 3 ,
639 Bytes,630 Bytes,593 BytesProbieren Sie es online aus!
Ich denke, dies ist eher eine minimale Quelle als Golf ... Ich bin sicher, es gibt einen besseren Weg, um dorthin zu gelangen.
Das Programm arbeitet als vollständiger Dolmetscher für die Sprache. Es hört entweder auf, wenn:
Die Schleifenerkennung ist etwas naiv (und speicherintensiv). Bevor wir jede Bewegung auswerten, werden unsere aktuellen Richtungen, Positionen und Stapel zwischengespeichert. Wenn wir sehen, dass wir an eine Position gekommen sind, an der wir zuvor waren, und uns in dieselbe Richtung bewegen, und unser aktueller Stapel eine Supermenge eines vorherigen Stapels an dieser Position + Richtung ist, dann wissen wir, dass wir uns in einer Schleife befinden und Der Stapel wächst entweder (oder bleibt konstant).
Edit 1 - Danke an Herman L für das Schneiden von "Pass". Schneiden Sie auch "True".
Edit 2 - Lambda-ified einige Funktionen. Reduzierte Anzahl von Retouren. Gibt "True" zum Beenden und "False" zum Nichtbeenden zurück. Nutzung der vorhandenen O-Klasse als Tracking-Objekt, sodass keine N-Klasse erforderlich ist.
quelle
class N():pass
mitclass N():0
unddef t():pass
mitdef t():0
scheint zu funktionierendef e(I)
mitI=input()
. Auf diese Weise können Sie alle Einrückungen entfernen. Diereturn x
Anweisungen können durch ersetzt werdenexit(x)
.def u():return len(O.S)==0 or y()
auch werdenu=lambda:len(O.S)==0or y()
. PS schöne Lösung!JavaScript (ES6),
258254 ByteErwartet ein nicht leeres Programm als Array von Zeichenfolgen, wobei jedes Element eine Zeile von Modilar SNISP darstellt. Ausgänge ,
1
wenn die gegebenen Programm hält, und aus0
anderen Gründen .Gleiche Logik wie die Antwort von @ machina.widmo . Ein paar fehlgeschlagene Versuche mit alternativen Methoden führten mich zu dem Schluss, dass sie sowieso längeren Code produzieren würden!
Probieren Sie es online aus!
Erläuterung
Ähnlich wie bei der anderen Antwort wird diese Funktion beendet mit:
1
wenn das Programm angehalten wird (z. B. wenn sich die IP vom Raster entfernt oder ein leerer Stapel platzt)0
Wenn die IP eine Position erreicht, die sie bereits besucht hat, bewegt sie sich in dieselbe Richtung und mit einer Obermenge des Stapels, die beim vorherigen Besuch vorhanden war.Warum die gleiche Richtung?
Das obige Programm wird angehalten, trifft jedoch dieselbe Position (Zeichen 1) mit einem identischen Stapel, jedoch aus einer anderen Richtung.
Warum eine Obermenge und nicht nur eine Stapelgröße?
Dies wird ebenfalls angehalten und die IP trifft viermal aus einer konsistenten Richtung auf Zeichen 4 mit den folgenden Stapelzuständen (
*
zeigt die Oberseite des Stapels an):Wie der Dolmetscher funktioniert
Anweisungen (
q
) werdenc
wie folgt in binär ( ) übersetzt (wobei alle anderen Zeichen.
oder auf andere Weise als Nops dienen):Direction (
d
) wird als Bitfeld dargestellt:Spiegel (
\/
) verändern die Richtung:\
: 6-> 9 9-> 6 4-> 1 1-> 4d/4 | 4*d&12
/
: 1-> 6 6-> 1 4-> 9 9-> 4(d+5) % 10
Neue Richtungen verändern die Position:
x += d>>2 - 1
y += d&3 - 1
Andere globale Variablen
x
,y
: IP-Positionr
: Hält den Wert vom Stapelk
: falsch, wenn die nächste Anweisung übersprungen wird (z. B. von!#
)s
: Stapelv
: Zwischenspeichert besuchte Positionen, Richtung, Momentaufnahme des Stapelsw
:[x, y, d]
, der Wert, der auf dem Stapel gespeichert und als Schlüsselwert für verwendet wirdv
e
: falsch, wenn das Programm aufgrund einer Cache-Übereinstimmung nicht angehalten wirdUngolfed
quelle