Last active
November 11, 2016 13:03
-
-
Save oisincar/3547e033f3ff46b6f4a82b5b2bea7a26 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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