Befinge için Durma Problemini Çöz ruhuyla, Modilar SNISP adlı başka bir 2D dil tanımlayalım . Modilar SNISP aşağıdaki altı talimatı içerir:
\
yönerge işaretçisini aşağıdaki gibi yönlendirir:- yukarıdan yaklaşılırsa, sağa gidin;
- sağdan yaklaşılırsa yukarı çıkın;
- alttan yaklaşılırsa sola gidin;
- soldan yaklaşırsa aşağı in.
/
yönerge işaretçisini aşağıdaki gibi yönlendirir:- yukarıdan yaklaşılırsa sola gidin;
- soldan yaklaşılırsa yukarı çıkın;
- aşağıdan yaklaşılırsa, sağa git;
- eğer sağdan yaklaşırsa aşağı in.
!
sonraki talimatı atlar.@
IP konumunu ve yönünü çağrı yığını üzerine iter.#
çağrı yığınından bir IP konumu ve yönü açar ve bunları geri yükler, ardından bir sonraki talimatın üzerinden atlar. Çağrı yığını boşsa, yürütme durur..
hiç birşey yapmıyor.
Talimat işaretçisi sol üst köşeden sağa doğru başlar. Oyun alanından ayrılırsa, yürütme durur.
Modilar SNISP bir daha güçlü olamaz PDA sınırsız depolama onun sadece kaynak sonlu alfabe (tüm IP (konum, yön) çiftler grubu) sahip bir istif (çağrı yığın) olduğu için,. Durma problemi PDA'lar için kararlıdır , bu nedenle bu zorluk her zaman mümkün olmalıdır.
Meydan okuma
Amacınız, bir Modilar SNISP programını temsil eden bir karakter matrisi alan ve durup durmadığına bağlı olarak iki ayrı çıktıdan birini döndüren bir program yazmaktır.
Bu kod golf , bu nedenle ( bayt cinsinden ölçülen ) en kısa geçerli program kazanır.
Özellikler
- Bir karakter matrisini alma şekliniz esnektir: satırsonu ile ayrılmış bir dize, dize dizisi, karakter dizisi, 2d karakter dizisi, genişliği temsil eden tamsayıya sahip düz karakter dizisi vb. Kabul edilebilir. Test senaryoları bu seçeneklerden ilkini tercih eder.
- Giriş matrisinin dikdörtgen olacağını (yani kısa satırları doldurmak zorunda kalmayacağınızı) ve sıfır olmayan uzunluk ve genişlikte olacağını varsayabilirsiniz.
- Sadece doğru / falsili değil, iki farklı çıktı da seçebilirsiniz.
- Sen girdi matrisi tek geçerli komutların oluşacaktır varsayabiliriz (
\
,/
,!
,@
,#
, ve.
). - Bir komutun "sonraki talimatı atlaması" söylendiğinde, atlanacak bir sonraki talimatın olacağını varsayabilirsiniz. Özellikle, (1) oyun alanının kenarında bulunduğu ve (2) IP'nin bu kenara dikey hareket ettiği durumlarda, bu oyun alanının dışında kalan “bir sonraki talimat” olacak şekilde karşılaşılmayacaktır.
Test Durumları
Aşağıdaki snippet, dildeki programları test etmek için kullanılabilir. Burada verilen gerçek spesifikasyondan biraz daha izin verici olduğunu unutmayın (örn .
. Op olmayanlar dışındaki karakterlere izin verir ).
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>
Solmamış form burada bulunabilir .
aksak
.
Mümkün olan en küçük program. Doğru dışarı çıkıyor.
\\
\/
Programın etrafında rüzgarlar ve zirveye çıkıyor.
.\./.\
.\!/./
Bir döngüye girer. İki farklı yöne pistin bir kısmı boyunca rüzgarlar.
@\!/#
.\@/#
Altı komutun tümünü kullanır.
@.@.@.@.@.@.@.@.@.#
Bu programın yürütme süresi, yineleme sayısında @.
üsteldir, ancak yine de durur.
Sigara durduruluyor
!/\
.\/
Bunun en kısa sonsuz döngü olduğuna inanıyorum.
@!\\#/@\!\
//@//.#./.
.\#.!\./\.
#.\!@!\@//
/..@.@\/#!
\.@.#.\/@.
Bu, sonunda sonsuz sayıda yığın çerçeveleri üreten bir döngüye yakalanmadan önce, zaman zaman yığın kareleri yumurtlayarak pistin etrafına sarılır. Tüm komutlar aslında kullanılmaz.
.!/@.@.@.@.@.\
/.@.@.@.@.@.@/
\@.@.@.@.@.@.\
/.@.@.@.@.@.@/
.@\@.@.@.@.@.\
\.@.@.@.@.@.@/
Yığın kareleri oluşturmaya devam eder, ancak hiçbiri geri dönmez.