ऑरोबोरोस एक एसोलैंग है जिसे मैंने इस सप्ताह डिज़ाइन किया है। स्पिन के लिए इसे लेने का समय!
i.1+!57*(\m1(M\1).96>.@32*-.80=\.78=3*\.66=3*\.82=5*\81=9*++++\2*1\-*+
)L!4*(4Sn1(
सिंगल-चार कमांड्स 1 की प्रत्येक पंक्ति एक ऑउबोरोस सांप का प्रतिनिधित्व करती है, जिसमें निष्पादन सिर (शुरू) से पूंछ (अंत) तक होता है और वापस सिर पर छोरों। (
और )
आदेशों आप पूंछ का हिस्सा खाने या यह वमन करते हैं, इस प्रकार बदल रहा है क्या आदेशों निष्पादित हो। यदि निर्देश सूचक को कभी भी निगल लिया जाता है, तो सांप मर जाता है (निष्पादित करना बंद कर देता है)। एक ऑरोबोरोस कार्यक्रम में एक या अधिक सांप होते हैं जो समानांतर में निष्पादित होते हैं। प्रत्येक सांप का अपना एक ढेर होता है, और एक साझा ढेर भी होता है।
1 एक अपवाद, जो कई 2 डी भाषाओं से ऑरोबोरोस को अलग करता है: बहु अंकों को सीधे गणित लिखे बिना या 0 को धक्का दिए बिना लिखा जा सकता है।
साँप १
पहला साँप एक चरित्र पढ़ता है ( i
) और जाँचता है कि क्या यह -1 / EOF ( .1+!
) है। यदि हां, तो यह M
( 57*(
) और ( सहित ) अपनी अधिकांश पूंछ खाती है ।
साँप तब टैली के साथ वर्ण कोड को स्वैप करता है जो स्टैक पर उसके ऊपर होता है ( \
), टैली को साझा स्टैक ( m
) में ले जाता है, और दूसरे वर्ण ( 1(
) को निगलता है । यदि यह पहले से ही एक गुच्छा निगल गया था, तो इसका मतलब है कि यह निगलता है (
कि आईपी वर्तमान में चालू है और मर जाता है। अन्यथा, निष्पादन 1 के ढेर पर वापस जाने के लिए टैली को आगे बढ़ाता है, इसे चार कोड के साथ स्वैप करता है, और उस चरित्र को पुन: उत्पन्न करता है जिसे पहले निगल लिया गया था ( M\1)
)।
फिर हम चरित्र के लिए उचित स्कोर उत्पन्न करने के लिए गणित और स्टैक ऑपरेशन का उपयोग करते हैं। .96>
परीक्षण है कि यह लोअरकेस है या नहीं; बाद 32*-
में अपरकेस में परिवर्तित हो जाता है। तब से लंबा खिंचाव .80=
के 81=9*++++
नक्शे P
-> 1
, N
-> 3
, आदि अंत में, \2*1\-*
स्कोर अगर पत्र लोअरकेस था नकारता है, और +
चल रहा है मिलान करने के लिए यह कहते हैं। सांप फिर लूप करता है और दूसरे किरदार को पढ़ता है।
साँप २
दूसरा सांप एक regurgitation ऑपरेशन ( )
) के साथ शुरू होता है , जो पहली बार कुछ भी नहीं करता है (क्योंकि कुछ भी नहीं निगल लिया गया है, और तब से जब एक खाली स्टैक देता है 0
)। इसके बाद, यह साझा स्टैक की लंबाई को अपने स्वयं के स्टैक पर धकेलता है और तार्किक रूप से नकारात्मक करता है ( L!
)। यह देता है 1
अगर स्टैक खाली है, 0
अन्यथा। सांप 4 से गुणा करता है और कई पात्रों ( 4*(
) को खाता है ।
यदि साझा स्टैक खाली था, तो इसका मतलब है कि सांप अब से पहले समाप्त हो गया है S
। यह 4
पीछे की ओर धकेलता और ढलता है )
, जहाँ यह पात्रों को पुन: निगल लेता है और फिर से निगल जाता है।
यदि साझा स्टैक पर एक मूल्य था, हालांकि, कोई वर्ण निगल नहीं है और निष्पादन जारी है। सांप साझा ढेर पर स्विच करता है और वहां संख्या को आउटपुट करता है ( Sn
); तब यह अपने अंतिम चरित्र को निगल जाता है और मर जाता है ( 1(
)।
तादात्म्य
दो सांपों को सावधानी से सिंक्रनाइज़ किया जाना चाहिए ताकि सांप के अंत तक पहुंचने पर सांप 2 अपनी जांच करता है, जब साझा स्टैक पर कोई मूल्य नहीं होता है। स्नेक 1 साझा लूप पर प्रत्येक लूप के माध्यम से प्रत्येक पास पर एक मूल्य रखता है। इस प्रकार, साँप 2 के L
आदेश कभी नहीं के बीच निष्पादित किया जाना चाहिए m
और M
साँप 1. सौभाग्य में आदेश, सांप बहुत अच्छी तरह से लाइन अप। महत्वपूर्ण रूप से, सांप 1 के लूप की लंबाई (70 निर्देश) सांप 2 के लूप (7 निर्देश) का एक गुण है, इसलिए दोनों कभी भी सिंक से बाहर नहीं निकलेंगे:
i.1+!57*(\m1(M\1).96>.@32*-.80=\.78=3*\.66=3*\.82=5*\81=9*++++\2*1\-*+
)L!5*(5)L!5*(5)L!5*(5)L!5*(5)L!5*(5)L!5*(5)L!5*(5)L!5*(5)L!5*(5)L!5*(5
|__|
Danger zone
यदि संख्याओं ने इतनी अच्छी तरह से काम नहीं किया होता, तो मुझे रिक्त स्थान के साथ एक या दोनों साँपों को आवश्यकतानुसार संरेखित करने के लिए गद्देदार करना होता।
यह सब बहुत अच्छा है, लेकिन मैं इसे कार्रवाई में देखना चाहता हूं!
यहां स्टैक स्निपेट के माध्यम से उपरोक्त कार्यक्रम है। यहां तक कि प्रति सेकंड 1000 ऑपरेशनों पर, नमूना इनपुट के लिए उत्तर को थूकने में लगभग 10 सेकंड लगते हैं - लेकिन यह वहां हो जाता है!
// Define Stack class
function Stack() {
this.stack = [];
this.length = 0;
}
Stack.prototype.push = function(item) {
this.stack.push(item);
this.length++;
}
Stack.prototype.pop = function() {
var result = 0;
if (this.length > 0) {
result = this.stack.pop();
this.length--;
}
return result;
}
Stack.prototype.top = function() {
var result = 0;
if (this.length > 0) {
result = this.stack[this.length - 1];
}
return result;
}
Stack.prototype.toString = function() {
return "" + this.stack;
}
// Define Snake class
function Snake(code) {
this.code = code;
this.length = this.code.length;
this.ip = 0;
this.ownStack = new Stack();
this.currStack = this.ownStack;
this.alive = true;
this.wait = 0;
this.partialString = this.partialNumber = null;
}
Snake.prototype.step = function() {
if (!this.alive) {
return null;
}
if (this.wait > 0) {
this.wait--;
return null;
}
var instruction = this.code.charAt(this.ip);
var output = null;
if (this.partialString !== null) {
// We're in the middle of a double-quoted string
if (instruction == '"') {
// Close the string and push its character codes in reverse order
for (var i = this.partialString.length - 1; i >= 0; i--) {
this.currStack.push(this.partialString.charCodeAt(i));
}
this.partialString = null;
} else {
this.partialString += instruction;
}
} else if (instruction == '"') {
this.partialString = "";
} else if ("0" <= instruction && instruction <= "9") {
if (this.partialNumber !== null) {
this.partialNumber = this.partialNumber + instruction; // NB: concatenation!
} else {
this.partialNumber = instruction;
}
next = this.code.charAt((this.ip + 1) % this.length);
if (next < "0" || "9" < next) {
// Next instruction is non-numeric, so end number and push it
this.currStack.push(+this.partialNumber);
this.partialNumber = null;
}
} else if ("a" <= instruction && instruction <= "f") {
// a-f push numbers 10 through 15
var value = instruction.charCodeAt(0) - 87;
this.currStack.push(value);
} else if (instruction == "$") {
// Toggle the current stack
if (this.currStack === this.ownStack) {
this.currStack = this.program.sharedStack;
} else {
this.currStack = this.ownStack;
}
} else if (instruction == "s") {
this.currStack = this.ownStack;
} else if (instruction == "S") {
this.currStack = this.program.sharedStack;
} else if (instruction == "l") {
this.currStack.push(this.ownStack.length);
} else if (instruction == "L") {
this.currStack.push(this.program.sharedStack.length);
} else if (instruction == ".") {
var item = this.currStack.pop();
this.currStack.push(item);
this.currStack.push(item);
} else if (instruction == "m") {
var item = this.ownStack.pop();
this.program.sharedStack.push(item);
} else if (instruction == "M") {
var item = this.program.sharedStack.pop();
this.ownStack.push(item);
} else if (instruction == "y") {
var item = this.ownStack.top();
this.program.sharedStack.push(item);
} else if (instruction == "Y") {
var item = this.program.sharedStack.top();
this.ownStack.push(item);
} else if (instruction == "\\") {
var top = this.currStack.pop();
var next = this.currStack.pop()
this.currStack.push(top);
this.currStack.push(next);
} else if (instruction == "@") {
var c = this.currStack.pop();
var b = this.currStack.pop();
var a = this.currStack.pop();
this.currStack.push(c);
this.currStack.push(a);
this.currStack.push(b);
} else if (instruction == ";") {
this.currStack.pop();
} else if (instruction == "+") {
var b = this.currStack.pop();
var a = this.currStack.pop();
this.currStack.push(a + b);
} else if (instruction == "-") {
var b = this.currStack.pop();
var a = this.currStack.pop();
this.currStack.push(a - b);
} else if (instruction == "*") {
var b = this.currStack.pop();
var a = this.currStack.pop();
this.currStack.push(a * b);
} else if (instruction == "/") {
var b = this.currStack.pop();
var a = this.currStack.pop();
this.currStack.push(a / b);
} else if (instruction == "%") {
var b = this.currStack.pop();
var a = this.currStack.pop();
this.currStack.push(a % b);
} else if (instruction == "_") {
this.currStack.push(-this.currStack.pop());
} else if (instruction == "I") {
var value = this.currStack.pop();
if (value < 0) {
this.currStack.push(Math.ceil(value));
} else {
this.currStack.push(Math.floor(value));
}
} else if (instruction == ">") {
var b = this.currStack.pop();
var a = this.currStack.pop();
this.currStack.push(+(a > b));
} else if (instruction == "<") {
var b = this.currStack.pop();
var a = this.currStack.pop();
this.currStack.push(+(a < b));
} else if (instruction == "=") {
var b = this.currStack.pop();
var a = this.currStack.pop();
this.currStack.push(+(a == b));
} else if (instruction == "!") {
this.currStack.push(+!this.currStack.pop());
} else if (instruction == "?") {
this.currStack.push(Math.random());
} else if (instruction == "n") {
output = "" + this.currStack.pop();
} else if (instruction == "o") {
output = String.fromCharCode(this.currStack.pop());
} else if (instruction == "r") {
var input = this.program.io.getNumber();
this.currStack.push(input);
} else if (instruction == "i") {
var input = this.program.io.getChar();
this.currStack.push(input);
} else if (instruction == "(") {
this.length -= Math.floor(this.currStack.pop());
this.length = Math.max(this.length, 0);
} else if (instruction == ")") {
this.length += Math.floor(this.currStack.pop());
this.length = Math.min(this.length, this.code.length);
} else if (instruction == "w") {
this.wait = this.currStack.pop();
}
// Any instruction not covered by the above cases is ignored
if (this.ip >= this.length) {
// We've swallowed the IP, so this snake dies
this.alive = false;
this.program.snakesLiving--;
} else {
// Increment IP and loop if appropriate
this.ip = (this.ip + 1) % this.length;
}
return output;
}
// Define Program class
function Program(source, speed, io) {
this.sharedStack = new Stack();
this.snakes = source.split(/\r?\n/).map(function(snakeCode) {
var snake = new Snake(snakeCode);
snake.program = this;
snake.sharedStack = this.sharedStack;
return snake;
}.bind(this));
this.snakesLiving = this.snakes.length;
this.io = io;
this.speed = speed || 10;
this.halting = false;
}
Program.prototype.run = function() {
if (this.snakesLiving) {
this.step();
this.timeout = window.setTimeout(this.run.bind(this), 1000 / this.speed);
}
}
Program.prototype.step = function() {
for (var s = 0; s < this.snakes.length; s++) {
var output = this.snakes[s].step();
if (output) {
this.io.print(output);
}
}
}
Program.prototype.halt = function() {
window.clearTimeout(this.timeout);
}
var ioFunctions = {
print: function(item) {
var stdout = document.getElementById('stdout');
stdout.value += "" + item;
},
getChar: function() {
if (inputData) {
var inputChar = inputData[0];
inputData = inputData.slice(1);
return inputChar.charCodeAt(0);
} else {
return -1;
}
},
getNumber: function() {
while (inputData && (inputData[0] < "0" || "9" < inputData[0])) {
inputData = inputData.slice(1);
}
if (inputData) {
var inputNumber = inputData.match(/\d+/)[0];
inputData = inputData.slice(inputNumber.length);
return +inputNumber;
} else {
return -1;
}
}
};
var program = null;
var inputData = null;
function resetProgram() {
var stdout = document.getElementById('stdout');
stdout.value = null;
if (program !== null) {
program.halt();
}
program = null;
inputData = null;
}
function initProgram() {
var source = document.getElementById('source'),
stepsPerSecond = document.getElementById('steps-per-second'),
stdin = document.getElementById('stdin');
program = new Program(source.value, +stepsPerSecond.innerHTML, ioFunctions);
inputData = stdin.value;
}
function runBtnClick() {
if (program === null || program.snakesLiving == 0) {
resetProgram();
initProgram();
} else {
program.halt();
var stepsPerSecond = document.getElementById('steps-per-second');
program.speed = +stepsPerSecond.innerHTML;
}
program.run();
}
function stepBtnClick() {
if (program === null) {
initProgram();
} else {
program.halt();
}
program.step();
}
.container {
width: 100%;
}
.so-box {
font-family: 'Helvetica Neue', Arial, sans-serif;
font-weight: bold;
color: #fff;
text-align: center;
padding: .3em .7em;
font-size: 1em;
line-height: 1.1;
border: 1px solid #c47b07;
-webkit-box-shadow: 0 2px 2px rgba(0, 0, 0, 0.3), 0 2px 0 rgba(255, 255, 255, 0.15) inset;
text-shadow: 0 0 2px rgba(0, 0, 0, 0.5);
background: #f88912;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.3), 0 2px 0 rgba(255, 255, 255, 0.15) inset;
}
.control {
display: inline-block;
border-radius: 6px;
float: left;
margin-right: 25px;
cursor: pointer;
}
.option {
padding: 10px 20px;
margin-right: 25px;
float: left;
}
h1 {
text-align: center;
font-family: Georgia, 'Times New Roman', serif;
}
a {
text-decoration: none;
}
input,
textarea {
box-sizing: border-box;
}
textarea {
display: block;
white-space: pre;
overflow: auto;
height: 40px;
width: 100%;
max-width: 100%;
min-height: 25px;
}
span[contenteditable] {
padding: 2px 6px;
background: #cc7801;
color: #fff;
}
#stdout-container,
#stdin-container {
height: auto;
padding: 6px 0;
}
#reset {
float: right;
}
#source-display-wrapper {
display: none;
width: 100%;
height: 100%;
overflow: auto;
border: 1px solid black;
box-sizing: border-box;
}
#source-display {
font-family: monospace;
white-space: pre;
padding: 2px;
}
.activeToken {
background: #f88912;
}
.clearfix:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
.clearfix {
display: inline-block;
}
* html .clearfix {
height: 1%;
}
.clearfix {
display: block;
}
<!--
Designed and written 2015 by D. Loscutoff
Much of the HTML and CSS was taken from this Befunge interpreter by Ingo Bürk: http://codegolf.stackexchange.com/a/40331/16766
-->
<div class="container">
<textarea id="source" placeholder="Enter your program here" wrap="off">i.1+!57*(\m1(M\1).96>.@32*-.80=\.78=3*\.66=3*\.82=5*\81=9*++++\2*1\-*+
)L!4*(4Sn1(</textarea>
<div id="source-display-wrapper">
<div id="source-display"></div>
</div>
</div>
<div id="stdin-container" class="container">
<textarea id="stdin" placeholder="Input" wrap="off">5k2/ppp5/4P3/3R3p/6P1/1K2Nr2/PP3P2/8</textarea>
</div>
<div id="controls-container" class="container clearfix">
<input type="button" id="run" class="control so-box" value="Run" onclick="runBtnClick()" />
<input type="button" id="pause" class="control so-box" value="Pause" onclick="program.halt()" />
<input type="button" id="step" class="control so-box" value="Step" onclick="stepBtnClick()" />
<input type="button" id="reset" class="control so-box" value="Reset" onclick="resetProgram()" />
</div>
<div id="stdout-container" class="container">
<textarea id="stdout" placeholder="Output" wrap="off" readonly></textarea>
</div>
<div id="options-container" class="container">
<div class="option so-box">Steps per Second: <span id="steps-per-second" contenteditable>1000</span>
</div>
</div>