Skip to content

Instantly share code, notes, and snippets.

@tuankiet65
Created December 16, 2016 08:34
Show Gist options
  • Save tuankiet65/23bf534e01782aa1ae5cd410bc578c28 to your computer and use it in GitHub Desktop.
Save tuankiet65/23bf534e01782aa1ae5cd410bc578c28 to your computer and use it in GitHub Desktop.
RLESTR
#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