В духе Решить проблему остановки для Befinge , давайте определим еще один 2D-язык под названием Modilar SNISP . Modilar SNISP имеет следующие шесть инструкций:
\
направляет указатель инструкции следующим образом:- если приблизиться сверху, идите направо;
- если приблизиться справа, поднимитесь;
- если приблизиться снизу, идите налево;
- если подходить слева, спуститься вниз.
/
направляет указатель инструкции следующим образом:- если приблизиться сверху, идите налево;
- если приблизиться слева, поднимитесь;
- если приблизиться снизу, идите направо;
- если приблизиться справа, спускайтесь вниз.
!
пропускает следующую инструкцию@
выдвигает местоположение и направление IP на стек вызовов.#
извлекает IP-адрес и направление из стека вызовов и восстанавливает их, затем пропускает следующую инструкцию. Если стек вызовов пуст, выполнение останавливается..
ничего не делает.
Указатель инструкций начинается в верхнем левом углу и идет вправо. Если он когда-либо покидает игровое поле, выполнение останавливается.
Modilar SNISP не может быть более мощным, чем КПК , потому что его единственным источником неограниченного хранилища является стек (стек вызовов) с конечным алфавитом (набор всех пар IP (местоположение, направление)). Проблема остановки решаема для КПК , поэтому эта задача всегда должна быть возможной.
Соревнование
Ваша цель - написать программу, которая принимает матрицу символов, представляющих программу Modilar SNISP, и возвращает один из двух отдельных выходных данных в зависимости от того, останавливается она или нет.
Это код-гольф , поэтому самая короткая действительная программа (измеряется в байтах выигрывает ).
Характеристики
- Способ, которым вы берете матрицу символов, является гибким: допустимы строка, разделенная новой строкой, массив строк, массив массивов символов, двумерный массив символов, плоский массив символов с целым числом, представляющим ширину, и т. Д. Тестовые случаи выбирают первый из этих вариантов.
- Вы можете предположить, что входная матрица будет прямоугольной (поэтому вам не придется заполнять короткие строки) и будет иметь ненулевую длину и ширину.
- Вы можете выбрать любые два различных выхода, а не только правдивость / ложь.
- Можно предположить , что входная матрица будет состоять только из допустимых команд (
\
,/
,!
,@
,#
, и.
). - Когда команда говорит «пропустить следующую инструкцию», вы можете предположить, что будет следующая команда, которую нужно пропустить. В частности, его никогда не встретят в обстоятельствах, когда (1) он лежит на краю игрового поля и (2) IP движется перпендикулярно этому краю, так что «следующая инструкция» после него будет находиться за пределами игрового поля.
Тестовые случаи
Следующий фрагмент может быть использован для тестирования программ на языке. Обратите внимание, что он немного более разрешающий, чем фактическая спецификация, приведенная здесь (например, он допускает символы, отличные от .
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>
Негольфированную форму можно найти здесь .
запинающийся
.
Самая маленькая возможная программа. Выходит правильно
\\
\/
Обворачивается вокруг программы и выходит на вершину.
.\./.\
.\!/./
Идет в петле. Извилистая часть трассы в двух разных направлениях.
@\!/#
.\@/#
Использует все шесть команд.
@.@.@.@.@.@.@.@.@.#
Время выполнения этой программы экспоненциально по количеству повторений @.
, но оно все равно останавливается.
Non-Приостановление
!/\
.\/
Я считаю, что это самый короткий бесконечный цикл.
@!\\#/@\!\
//@//.#./.
.\#.!\./\.
#.\!@!\@//
/..@.@\/#!
\.@.#.\/@.
Это обматывает дорожку, порождая кадры стека, прежде чем в конечном итоге попасть в цикл, бесконечно генерирующий кадры стека. Не все команды на самом деле используются.
.!/@.@.@.@.@.\
/.@.@.@.@.@.@/
\@.@.@.@.@.@.\
/.@.@.@.@.@.@/
.@\@.@.@.@.@.\
\.@.@.@.@.@.@/
Создает стековые фреймы, но ни один из них не возвращается.