Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // to help with debugging
- function unbleach (n) {
- if (n) return n.replace(/ /g, 's').replace(/\t/g, 't').replace(/\n/g, 'n');
- }
- var SPACE = ' ', TAB = '\t', LF = '\n';
- function readNumber(code, pos) {
- var sign, c;
- var result = "";
- if (code.charAt(pos) == SPACE) sign = 1;
- else if (code.charAt(pos) == TAB) sign = -1;
- while ((c = code.charAt(pos++)) != LF) {
- if (c == SPACE) result += "0";
- if (c == TAB) result += "1";
- }
- --pos;
- return sign * parseInt(result, 2);
- }
- var instructions = {
- stackManinpulation: {
- push: function(code, pos, stack) { stack.push(readNumber(code, pos)); },
- duplicate: function(stack) { stack.push(stack[stack.length - 1]); },
- swapTop: function(stack) {
- var temp = stack[stack.length - 1];
- stack[stack.length - 1] = stack[stack.length - 2];
- stack[stack.length - 2] = temp;
- },
- discard: function(stack) { stack.pop(); },
- },
- arithmetic: {
- add: function(stack) { stack.push(stack.pop() + stack.pop()); },
- subtract: function(stack) { stack.push(-stack.pop() + stack.pop()); },
- multiply: function(stack) { stack.push(stack.pop() * stack.pop()); },
- divide: function(stack) {
- var first = stack.pop(), second = stack.pop();
- stack.push(Math.floor(second / first));
- },
- mod: function(stack) {
- var first = stack.pop(), second = stack.pop();
- stack.push(second % first);
- },
- },
- heapAccess: {
- store: function(stack, memory) {
- var address = stack[stack.length - 2];
- var value = stack[stack.length - 1];
- memory[address] = value;
- },
- retrieve: function(stack, memory) {
- var address = stack[stack.length - 1];
- stack.push(memory[address]);
- }
- },
- flowControl: {
- markLocation: function(code, pos, location) { location[readNumber(code, pos)] = pos - 1; },
- callSubroutine: function(code, pos, location, endSub) {
- var locationName = readNumber(code, pos);
- endSub.push(pos);
- pos = location[locationName];
- },
- jumpAnyway: function(code, pos, location) { pos = location[readNumber(code, pos)]; },
- jumpIfZero: function(code, pos, stack, location) {
- var locationName = readNumber(code, pos);
- if (stack[stack.length - 1] == 0) pos = location[locationName];
- },
- jumpIfNegative: function(code, pos, stack, location) {
- var locationName = readNumber(code, pos);
- if (stack[stack.length - 1] < 0) pos = location[locationName];
- },
- endSubroutine: function(pos, endSub) { pos = endSub.pop(); }
- },
- inAndOut: {
- outputChar: function(stack, output) { output += String.fromCharCode(stack.pop()); },
- outputNum: function(stack, output) { output += stack.pop().toString(); },
- readChar: function(stack, input, memory) {
- memory[stack[stack.length - 1]] = input.charAt(0);
- input = input.substr(1);
- },
- readNum: function(stack, input, memory) {
- memory[stack[stack.length - 1]] = input.charCodeAt(0);
- input = input.substr(1);
- }
- }
- }
- // solution
- function whitespace(code, input) {
- console.log(print(code));
- code = code.replace(/[^\s\t\n]/g, '');
- var output = '', stack = [], heap = {};
- var location = {}, memory = {}, endSub = [];
- var pos = 0;
- while (pos < code.length) {
- console.log(stack);
- console.log(output + " pos " + pos);
- switch(code.charAt(pos++)) {
- case SPACE: {
- var stackManinpulation = instructions.stackManinpulation;
- switch(code.charAt(pos++)) {
- case SPACE:
- stackManinpulation.push(code, pos, stack);
- break;
- case LF:
- switch(code.charAt(pos++)) {
- case SPACE:
- stackManinpulation.duplicate(stack);
- break;
- case TAB:
- stackManinpulation.swapTop(stack);
- break;
- case LF:
- stackManinpulation.discard(stack);
- break;
- }
- break;
- }
- break;
- }
- case TAB: {
- switch(code.charAt(pos++)) {
- case SPACE: {
- var arithmetic = instructions.arithmetic;
- switch(code.substr(pos, 2)) {
- case (SPACE + SPACE):
- arithmetic.add(stack); break;
- case (SPACE + TAB):
- arithmetic.subtract(stack); break;
- case (SPACE + LF):
- arithmetic.multiply(stack); break;
- case (TAB + SPACE):
- arithmetic.divide(stack); break;
- case (TAB + TAB):
- arithmetic.mod(stack); break;
- }
- pos += 2;
- break;
- }
- case TAB: {
- var heapAccess = instructions.heapAccess;
- switch(code.charAt(pos++)) {
- case SPACE:
- heapAccess.store(stack, memory); break;
- case TAB:
- heapAccess.retrieve(stack, memory); break;
- }
- break;
- }
- case LF: {
- var inAndOut = instructions.inAndOut;
- switch(code.substr(pos, 2)) {
- case (SPACE + SPACE):
- inAndOut.outputChar(stack, ouput); break;
- case (SPACE + TAB):
- inAndOut.outputNum(stack, output); break;
- case (TAB + SPACE):
- inAndOut.readChar(stack, input, memory); break;
- case (TAB + TAB):
- inAndOut.readNum(stack, input, memory); break;
- }
- pos += 2;
- break;
- }
- }
- break;
- }
- case LF: {
- var flowControl = instructions.flowControl;
- switch(code.substr(pos, 2)) {
- case (SPACE + SPACE): {
- flowControl.markLocation(code, pos, location);
- break;
- }
- case (SPACE + TAB): {
- flowControl.callSubroutine(code, pos, location, endSub);
- break;
- }
- case (SPACE + LF): {
- flowControl.jumpAnyway(code, pos, location);
- break;
- }
- case (TAB + SPACE): {
- flowControl.jumpIfZero(code, pos, stack, location);
- break;
- }
- case (TAB + TAB): {
- flowControl.jumpIfNegative(code, pos, stack, location);
- break;
- }
- case (TAB + LF): {
- flowControl.endSubroutine(pos, endSub);
- break;
- }
- case (LF + LF): {
- pos = code.length + 1;
- break;
- }
- }
- pos += 2;
- }
- }
- }
- return output;
- };
- function print(code) {
- var output = "";
- for (var i = 0; i < code.length; ++i)
- switch(code.charAt(i)) {
- case SPACE: output += 's'; break;
- case TAB: output += 't'; break;
- case LF: output += 'n'; break;
- }
- return output;
- }
- console.log(whitespace(" \t\n\t\n \t\n\n\n"));
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement