Created
December 16, 2016 08:34
-
-
Save tuankiet65/23bf534e01782aa1ae5cd410bc578c28 to your computer and use it in GitHub Desktop.
RLESTR
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 <fstream> | |
#include <string> | |
#include <iostream> | |
#include <vector> | |
#include <utility> | |
#include <sstream> | |
#define in(x, y, z) (x <= y) && (y <= z) | |
std::ifstream in; | |
std::ofstream out; | |
std::string command_type, xe, ye; | |
unsigned i, p, c; | |
class RLEString{ | |
public: | |
std::vector<std::pair<char, int> > rle = {}; | |
bool is_digit(char c){ | |
return ((c >= '0') && (c <= '9')); | |
} | |
void init_from_str(std::string str){ | |
unsigned ptr = 0; | |
int char_count = 0; | |
char c; | |
rle.clear(); | |
while (ptr < str.length()){ | |
c = str[ptr]; | |
ptr++; | |
while (is_digit(str[ptr])){ | |
char_count = (char_count * 10) + (str[ptr] - 48); | |
ptr++; | |
if (ptr == str.length()){ | |
break; | |
} | |
} | |
rle.push_back({c, char_count}); | |
char_count = 0; | |
} | |
} | |
RLEString& operator+=(const RLEString& b){ | |
if (this->rle.back().first == b.rle.front().first){ | |
this->rle.back().second = this->rle.back().second + b.rle.front().second; | |
} else { | |
this->rle.push_back(b.rle.front()); | |
} | |
for (auto block = (b.rle.begin() + 1); block != (b.rle.end()); block++){ | |
this->rle.push_back(*block); | |
} | |
return *this; | |
} | |
operator std::string() const { | |
std::stringstream s; | |
for (auto block = this->rle.begin(); block != this->rle.end(); block++){ | |
s << block->first << block->second; | |
} | |
return s.str(); | |
} | |
void remove(unsigned p, unsigned c){ | |
unsigned len_from = 1, len_to, cut_from = p, cut_to = (p + c - 1); | |
for (auto block = this->rle.begin(); block != this->rle.end(); block++){ | |
len_to = len_from + block->second - 1; | |
//std::cout << "at block " << block->first << " " << block->second << " len_from " << len_from << " len_to " << len_to << " cut_from " << cut_from << " cut_to " << cut_to << std::endl; | |
// processing... | |
if (in(len_from, cut_from, len_to)){ | |
if (in(len_from, cut_to, len_to)){ | |
block->second -= (cut_to - cut_from + 1); | |
// the cut fits in a block so we can break here; | |
break; | |
} else { | |
// the cut overflows | |
// first we set the new length for this block | |
block->second -= (len_to - cut_from + 1); | |
// the entire block may be removed in case block.second == 0, so we remove it from the vector | |
if (block->second == 0){ | |
this->rle.erase(block); | |
} | |
// then we move the cut_from pointer up to the next block; | |
cut_from = len_to + 1; | |
} | |
} else if (cut_from > len_to){ | |
break; | |
} | |
len_from = len_to + 1; | |
} | |
} | |
RLEString copy(unsigned p, unsigned c){ | |
unsigned len_from = 1, len_to, cut_from = p, cut_to = (p + c - 1); | |
RLEString y; | |
for (auto block = this->rle.begin(); block != this->rle.end(); block++){ | |
len_to = len_from + block->second - 1; | |
// std::cout << "at block " << block->first << " " << block->second << " len_from " << len_from << " len_to " << len_to << " cut_from " << cut_from << " cut_to " << cut_to << std::endl; | |
// processing... | |
if (in(len_from, cut_from, len_to)){ | |
if (in(len_from, cut_to, len_to)){ | |
y.rle.push_back({block->first, cut_from - cut_to + 1}); | |
// the cut fits in a block so we can break here; | |
break; | |
} else { | |
// the cut overflows | |
// first we set the new length for this block | |
block->second = (len_to - cut_from + 1); | |
y.rle.push_back({block->first, block->second}); | |
// // the entire block may be removed in case block.second == 0, so we remove it from the vector | |
// if (block->second == 0){ | |
// x.rle.erase(block); | |
// } | |
// then we move the cut_from pointer up to the next block; | |
cut_from = len_to + 1; | |
} | |
} else if (cut_from > len_to){ | |
break; | |
} | |
len_from = len_to + 1; | |
} | |
return y; | |
} | |
RLEString append(RLEString &y, unsigned p){ | |
unsigned len_from = 1, len_to; | |
RLEString tmp; | |
for (auto block = this->rle.begin(); block != this->rle.end(); block++){ | |
len_to = len_from + block->second - 1; | |
std::cout << "at block " << block->first << " " << block->second << " len_from " << len_from << " len_to " << len_to << std::endl; | |
// processing... | |
if (in(len_from, p, len_to)){ | |
// first we cut the block into two parts | |
// block shall be the second part | |
// so we insert before block the first part | |
if (p - len_from != 0){ | |
tmp.rle.push_back({block->first, p - len_from}); | |
} | |
// then we copy all part from y to x | |
// join the first part and the first block of y | |
if (tmp.rle.back().first == y.rle.front().first){ | |
tmp.rle.back().second = tmp.rle.back().second + y.rle.front().second; | |
} else { | |
tmp.rle.push_back(y.rle.front()); | |
} | |
// copy the remaining | |
for (auto block2 = (y.rle.begin() + 1); block2 != y.rle.end(); block2++){ | |
tmp.rle.push_back(*block2); | |
} | |
// join the last block of y and the second part | |
block->second = len_to - p + 1; | |
if (tmp.rle.back().first == block->first){ | |
tmp.rle.back().second = tmp.rle.back().second + block->second; | |
} else { | |
tmp.rle.push_back(*block); | |
} | |
// join the remaining x | |
for (auto block2 = (block + 1); block2 != this->rle.end(); block2++){ | |
tmp.rle.push_back(*block2); | |
} | |
} else { | |
tmp.rle.push_back(*block); | |
} | |
len_from = len_to + 1; | |
} | |
for (auto block = tmp.rle.begin(); block != tmp.rle.end(); block++){ | |
std::cout << block->first << " " << block->second << std::endl; | |
} | |
return tmp; | |
} | |
}; | |
RLEString x, y; | |
int main(){ | |
in.open("RLESTR.INP"); | |
out.open("RLESTR.OUT"); | |
while (true){ | |
in >> command_type; | |
if (in.eof()){ | |
break; | |
} | |
in >> xe; | |
x.init_from_str(xe); | |
switch (command_type[1]){ | |
case '1': | |
in >> ye; | |
y.init_from_str(ye); | |
x += y; | |
out << "@1: " << (std::string)x; | |
break; | |
case '2': | |
in >> p >> c; | |
x.remove(p, c); | |
out << "@2: " << (std::string)x; | |
break; | |
case '3': | |
in >> p >> c; | |
out << "@3: " << (std::string)x.copy(p, c); | |
break; | |
case '4': | |
in >> ye; | |
in >> p; | |
y.init_from_str(ye); | |
out << "@4: " << (std::string)x.append(y, p); | |
break; | |
} | |
out << std::endl; | |
} | |
in.close(); | |
out.close(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment