Dalam semangat Memecahkan Masalah Pemutusan untuk Befinge , mari kita mendefinisikan bahasa 2D lain yang disebut Modilar SNISP . Modilar SNISP memiliki enam instruksi berikut:
\
mengarahkan penunjuk instruksi sebagai berikut:- jika didekati dari atas, ke kanan;
- jika didekati dari kanan, naiklah;
- jika didekati dari bawah, ke kiri;
- jika didekati dari kiri, turunlah.
/
mengarahkan penunjuk instruksi sebagai berikut:- jika didekati dari atas, ke kiri;
- jika didekati dari kiri, naik;
- jika didekati dari bawah, ke kanan;
- jika didekati dari kanan, turunlah.
!
melompati instruksi selanjutnya.@
mendorong lokasi dan arah IP ke tumpukan panggilan.#
memunculkan lokasi dan arah IP dari tumpukan panggilan dan mengembalikannya, lalu melompati instruksi selanjutnya. Jika tumpukan panggilan kosong, eksekusi terhenti..
tidak melakukan apa-apa.
Penunjuk instruksi dimulai di sudut kiri atas ke kanan. Jika itu pernah meninggalkan playfield, eksekusi terhenti.
SNSP Modilar tidak bisa lebih kuat dari PDA , karena satu-satunya sumber penyimpanan tidak terbatas adalah tumpukan (panggilan stack) dengan alfabet terbatas (himpunan semua pasangan IP (lokasi, arah) pasangan). Masalah penghentian adalah decidable untuk PDA , jadi tantangan ini harus selalu dimungkinkan.
Tantangan
Tujuan Anda adalah untuk menulis sebuah program yang mengambil matriks karakter yang mewakili program SNISP Modilar dan mengembalikan salah satu dari dua output yang berbeda tergantung pada apakah itu berhenti atau tidak.
Ini adalah kode-golf , sehingga program terpendek yang valid (diukur dalam byte ) menang.
Spesifikasi
- Cara Anda mengambil matriks karakter fleksibel: string yang dipisahkan baris baru, array string, array array karakter, array karakter 2d, array karakter datar dengan integer yang mewakili lebar, dll. Semuanya dapat diterima. Kasing uji memilih yang pertama dari pilihan itu.
- Anda dapat mengasumsikan bahwa matriks input akan berbentuk persegi panjang (jadi Anda tidak perlu mengisi baris pendek) dan akan memiliki panjang dan lebar yang tidak nol.
- Anda dapat memilih dua output berbeda, bukan hanya kebenaran / kepalsuan.
- Anda dapat mengasumsikan bahwa matriks input akan hanya terdiri dari perintah yang sah (
\
,/
,!
,@
,#
, dan.
). - Ketika sebuah perintah dikatakan "lewati instruksi selanjutnya," Anda dapat mengasumsikan bahwa akan ada instruksi berikutnya untuk melewati. Secara khusus, itu tidak akan pernah ditemui dalam keadaan di mana (1) ia terletak di tepi playfield dan (2) IP bergerak tegak lurus ke tepi itu, sehingga "instruksi berikutnya" setelah itu akan berada di luar playfield.
Uji Kasus
Cuplikan berikut dapat digunakan untuk menguji program dalam bahasa. Perhatikan bahwa ini sedikit lebih permisif daripada spesifikasi sebenarnya yang diberikan di sini (mis. Itu memungkinkan karakter selain .
sebagai 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>
Bentuk tanpa ungolf dapat ditemukan di sini .
Berhenti
.
Program sekecil mungkin. Keluar benar.
\\
\/
Angin di sekitar program dan keluar di atas.
.\./.\
.\!/./
Berputar. Angin melalui bagian trek dalam dua arah yang berbeda.
@\!/#
.\@/#
Menggunakan semua enam perintah.
@.@.@.@.@.@.@.@.@.#
Waktu pelaksanaan program ini eksponensial dalam jumlah pengulangan @.
, tetapi masih terhenti.
Non-Berhenti
!/\
.\/
Saya percaya ini adalah loop tak terbatas terpendek.
@!\\#/@\!\
//@//.#./.
.\#.!\./\.
#.\!@!\@//
/..@.@\/#!
\.@.#.\/@.
Ini berputar di sekitar trek, memunculkan frame stack sesekali, sebelum akhirnya terjebak dalam siklus yang menghasilkan frame stack secara tak terbatas. Tidak semua perintah benar-benar digunakan.
.!/@.@.@.@.@.\
/.@.@.@.@.@.@/
\@.@.@.@.@.@.\
/.@.@.@.@.@.@/
.@\@.@.@.@.@.\
\.@.@.@.@.@.@/
Terus membuat bingkai tumpukan, tetapi tidak ada yang kembali.