Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <unordered_map>
- #include <cstdio>
- #include <string>
- #include <vector>
- #include <cstring>
- #include <utility>
- using std::pair;
- using std::unordered_map;
- using std::string;
- using std::vector;
- const char code_path[20] = "sub_1.txt"; //code file
- const char grid_path[20] = "grid_1.txt"; //grid file
- const uint32_t gridN = 256; // grid size
- bool print_grid = true; //print final grid
- char code[1048571];
- struct error {
- error() {}
- error(uint32_t a, uint32_t b, string c) : error_no(a), line(b), str(c) {}
- uint32_t error_no, line;
- string str;
- };
- const uint32_t maxpeb = 15;
- uint8_t grid[gridN][gridN], grid_init[gridN][gridN];
- uint32_t lines, tline;
- unordered_map<string, uint32_t> tag; //tag, line
- vector<pair<uint32_t, string>> totag; //line, tag
- vector<pair<uint32_t, uint32_t>> program; //mode, (toline)
- // 0: left, 1: right, 2: move, 3: get, 4: put, 5: halt, 6: jump, 7: border, 8: pebble
- void initialize() {
- freopen(grid_path, "r", stdin);
- memset(grid, 0x00, gridN * gridN);
- uint32_t x, y, t;
- while (~scanf("%u%u%u", &x, &y, &t)) {
- if (x >= gridN || x >= gridN || t > maxpeb) throw error(0, 0, ""); //invalid input
- grid[x][y] = t;
- }
- memcpy(grid_init, grid, gridN * gridN);
- lines = tline = 0;
- FILE* pFile = fopen(code_path, "r");
- size_t p = fread(code, 1, 1048571, pFile);
- code[p] = 0;
- }
- inline bool isg(char p) {
- return (p >= 'A' && p <= 'Z' || p >= 'a' && p <= 'z' || p >= '0' && p <= '9' || p == '_');
- }
- void compile_line(char* p, char* end) {
- tline++;
- string str[2];
- bool flag = false;
- int8_t cr = 0;
- while (p != end) {
- if (isg(*p)) {
- if (cr == 2 || flag) throw error(1, tline, ""); //word after tag or two words
- str[cr] += *p;
- if (str[cr].size() > 128) throw error(2, tline, ""); //too long
- }
- else if (*p == ' ') {
- if (str[cr].size()) cr++;
- }
- else if (*p == '#' || *p == '\n' || *p == '\r' || *p == '\0') {
- if (str[cr].size()) cr++;
- break;
- }
- else if (*p == ':') {
- if (!str[cr].size()) throw error(3, tline, ""); //empty tag
- cr++, flag = true;
- }
- else throw error(4, tline, string(1, *p)); //invalid character
- p++;
- }
- if (flag) {
- if (tag.count(str[0])) throw error(5, tline, str[0]); //same-name tag
- tag[str[0]] = lines--;
- }
- else if (str[0] == "left" && !str[1].size()) program.push_back(pair<uint32_t, uint32_t>(0, 0));
- else if (str[0] == "right" && !str[1].size()) program.push_back(pair<uint32_t, uint32_t>(1, 0));
- else if (str[0] == "move" && !str[1].size()) program.push_back(pair<uint32_t, uint32_t>(2, 0));
- else if (str[0] == "get" && !str[1].size()) program.push_back(pair<uint32_t, uint32_t>(3, 0));
- else if (str[0] == "put" && !str[1].size()) program.push_back(pair<uint32_t, uint32_t>(4, 0));
- else if (str[0] == "halt" && !str[1].size()) program.push_back(pair<uint32_t, uint32_t>(5, 0));
- else if (str[0] == "jump" && str[1].size()) {
- program.push_back(pair<uint32_t, uint32_t>(6, 0));
- totag.push_back(pair<uint32_t, string>(lines, str[1]));
- }
- else if (str[0] == "border" && str[1].size()) {
- program.push_back(pair<uint32_t, uint32_t>(7, 0));
- totag.push_back(pair<uint32_t, string>(lines, str[1]));
- }
- else if (str[0] == "pebble" && str[1].size()) {
- program.push_back(pair<uint32_t, uint32_t>(8, 0));
- totag.push_back(pair<uint32_t, string>(lines, str[1]));
- }
- else if (!str[0].size()) lines--;
- else throw error(6, tline, str[0] + ' ' + str[1]); //invalid command
- lines++;
- }
- void compile(char* p) {
- char *prev = p, *now = p;
- while (*now) {
- if (*now == '\n') {
- compile_line(prev, now + 1);
- prev = now + 1;
- }
- now++;
- }
- compile_line(prev, now + 1);
- unordered_map<string, uint32_t>::iterator it;
- for (auto& i : totag) {
- if ((it = tag.find(i.second)) != tag.end()) program[i.first].second = it->second;
- else throw error(7, 0, i.second); //undefined tag
- }
- }
- uint32_t tx, ty, dir;
- uint32_t nowline;
- uint32_t steps;
- const int32_t dy[4] = {0, -1, 0, 1}; //left++
- const int32_t dx[4] = {-1, 0, 1, 0};
- inline bool face_border() {
- return (!ty && dir == 1 || !tx && !dir || ty == 255 && dir == 3 || tx == 255 && dir == 2);
- }
- void execute() {
- nowline = steps = tx = ty = dir = 0;
- bool cont = true;
- while (cont && nowline < lines) {
- steps++;
- switch (program[nowline].first) {
- case 0: dir = (dir + 1) & 3; break;
- case 1: dir = (dir + 3) & 3; break;
- case 2: if (!face_border()) tx += dx[dir], ty += dy[dir]; break;
- case 3: if (grid[tx][ty]) grid[tx][ty]--; break;
- case 4: if (grid[tx][ty] != 15) grid[tx][ty]++; break;
- case 5: cont = false; break;
- case 6: nowline = program[nowline].second - 1; break;
- case 7: if (face_border()) nowline = program[nowline].second - 1; break;
- case 8: if (grid[tx][ty]) nowline = program[nowline].second - 1;
- }
- nowline++;
- }
- }
- int main()
- {
- try {
- initialize();
- compile(code);
- printf("Compiled. Commands: %u.\n", lines);
- execute();
- printf("Executed. Final position: (%u, %u). Steps: %u.\n", tx, ty, steps);
- if (print_grid) {
- for (uint32_t i = 0; i < gridN; i++) {
- for (uint32_t j = 0; j < gridN; j++) printf("%hhd ", grid[i][j]);
- putchar('\n');
- }
- }
- }
- catch (error e) {
- puts("Complication error.");
- switch (e.error_no) {
- case 0: puts("Invalid grid input."); break;
- case 1: printf("Line %u: Text after tag or too many arguments.", e.line); break;
- case 2: printf("Line %u: Identifier is too long.", e.line); break;
- case 3: printf("Line %u: Empty tag.", e.line); break;
- case 4: printf("Line %u: Invalid character \'%s\'.", e.line, e.str.c_str()); break;
- case 5: printf("Line %u: Redefinition of tag \'%s\'.", e.line, e.str.c_str()); break;
- case 6: printf("Line %u: Invalid command \'%s\'.", e.line, e.str.c_str()); break;
- case 7: printf("Undefined tag \'%s\'.", e.str.c_str());
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement