Skip to content

Instantly share code, notes, and snippets.

@oisincar
Last active November 11, 2016 13:03
Show Gist options
  • Select an option

  • Save oisincar/3547e033f3ff46b6f4a82b5b2bea7a26 to your computer and use it in GitHub Desktop.

Select an option

Save oisincar/3547e033f3ff46b6f4a82b5b2bea7a26 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <fstream>
#include <sstream>
#include <streambuf>
using namespace std;
// TODO: Make dataIx a char*
// see: https://en.wikipedia.org/wiki/Brainfuck
// int dataIx;
char *dataPtr;
char tape[10000];
class Operator {
public:
int times_;
virtual void Execute(){ }
};
class GreaterThan : public Operator { public: GreaterThan(int t){times_ = t;} void Execute(){ dataPtr+=times_; } };
class Plus : public Operator { public: Plus (int t){times_ = t;} void Execute(){ (*dataPtr)+=times_; } };
class Dot : public Operator { public: void Execute(){ putchar(*dataPtr); } };
// class Dot : public Operator { public: void Execute(){ } };
class Comma : public Operator { public: void Execute(){ cin >> *dataPtr; } };
class ResetReg : public Operator { public: void Execute(){ (*dataPtr) = 0; } }; // a loop which looks like [-] or [+]
class Multiply : public Operator { // loops which start and end on the same point in the ticker.. Eg [>++<-] which kinda multiplies the current buffer by 2
private:
map<int, int> pairs_;
public:
Multiply(map<int, int> pairs){
pairs_ = pairs;
// cout << "MulNode" << endl;
// for(auto elem : pairs_)
// std::cout << elem.first << " " << elem.second << " " << endl;
}
void Execute(){
int baseOffset = pairs_[0];
if (*dataPtr == 0) return; // Continue if we start at 0.
// TODO: Handle complex case, where the base offset isn't 1 or -1. Note this is currently filtered upstream..
// number of times the 'loop' would go.
int loop_t = (baseOffset > 0) ? 256-(*dataPtr) : *dataPtr;
for(auto elem : pairs_)
*(dataPtr + elem.first) += (elem.second * loop_t);
}
};
class Grouping : public Operator {
private:
vector<Operator*> operators_;
bool isHead_;
public:
Grouping(vector<char> operators, bool isHead){ // Bool is true if this is the head node (ie the base program);
isHead_ = isHead;
int i = 0;
while (i < operators.size()) {
char c = operators[i];
i++;
if (c == '.') operators_.push_back(new Dot());
else if (c == ',') operators_.push_back(new Comma());
else if (c == '[') {
int bracketLvl = 1;
vector<char> subOperators;
while (bracketLvl != 0){
subOperators.push_back(operators[i]);
if (operators[i] == '[') bracketLvl++;
else if (operators[i] == ']') bracketLvl--;
i++;
}
// check if we're at a loop which looks like [-] or [+] (ResetReg)
if (subOperators.size() == 2 && (subOperators[0] == '-' || subOperators[0] == '+'))
operators_.push_back(new ResetReg());
else{
// check if we're at a 'multiply' node.. (Multiply)
int diffBr = 0;
for(char const& o : subOperators){
if (o == '<') diffBr++;
else if (o == '>') diffBr--;
else if (o != '-' && o != '+' && o != ']') { // Loop must only contain non-special chars
diffBr = 2;
break;
}
}
if (diffBr == 0){
// map offset to change at that point. [>>>>+<<<<-] is {(4,1),(0,-1)}
map<int, int> pairs;
int offset = 0;
for(char const& o : subOperators) {
if (o == ']') continue;
else if (o == '>') offset++;
else if (o == '<') offset--;
else {
int times = 0;//(o == '+') ? 1 : -1;
if (o == '+') times = 1;
else if (o == '-') times = -1;
pairs[offset] += times; // Auto creates elements.
}
}
// Filter out complex case for now.
// if (false){
if (pairs[0] == -1 || pairs[0] == 1){
operators_.push_back(new Multiply(pairs));
}
else{
operators_.push_back(new Grouping(subOperators, false));
}
}
else {
operators_.push_back(new Grouping(subOperators, false));
}
}
}
else {
int count = 1;
// possible bug reaching outside index here vv
while (operators[i] == c) {count++; i++;}
if (c == '>') operators_.push_back(new GreaterThan(count));
else if (c == '<') operators_.push_back(new GreaterThan(-count));
else if (c == '+') operators_.push_back(new Plus(count));
else if (c == '-') operators_.push_back(new Plus(-count));
}
}
}
void RunOperators(){
for(auto const& o : operators_) o->Execute();
}
void Execute(){
if (isHead_) RunOperators();
else
while (*dataPtr != 0)
RunOperators();
}
};
// -- Running --
bool isNotBFChar(char c){
return !(c == '>' || c == '<' || c == '.' || c == ',' || c == '+' || c == '-' || c == '[' || c == ']');
}
int main() {
dataPtr = &tape[0];
ifstream t("hanoi.bf");
stringstream str;
str << t.rdbuf();
string r_prog = str.str();
// string r_prog = "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.";
// Strip non brainfuck chars, possibly rewrite code above to ignore weird chars.. Idk.
r_prog.erase(std::remove_if(r_prog.begin(), r_prog.end(), isNotBFChar), r_prog.end());
vector<char> p_vector(r_prog.begin(), r_prog.end());
Operator *head = new Grouping(p_vector, true);
head->Execute();
cout << endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment