/*
* This program decompresses a file produced by wordcomp. It takes as input
* a file produced by that program, and outputs the file wordcomp read.
*/
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <cctype>
using std::string;
const int CUTOFF = 3;
/*
* Read the next unit from standard input. Units are alnum, or non-alnum,
* or starting with one of the marker characters, @ or #.
*/
std::string read_next(std::istream &strm)
{
// Read the first character. If none, we're done.
char firstch;
if(!strm.get(firstch)) return "";
// Result string. Starts with that first character.
string ret;
ret.push_back(firstch);
// If we see an @, it is the first of pair which needs to be
// translated.
if(firstch == '@') {
// Read the second character. If it's not there, we'll call
// it over.
char secondch;
if(!strm.get(secondch)) return "";
ret.push_back(secondch);
return ret;
}
// If we see a #, we need to read the digits. We allow for the # to
// be the last character, which would be an error in the input.
if(firstch == '#') {
// What we got? Read digits
int nextch;
while((nextch = strm.peek()) != EOF) {
if(isdigit(nextch))
ret.push_back(strm.get());
else
break;
}
return ret.size() > 1 ? ret : "";
}
// Now, use the istream peek() method to add all immediately following
// characters of the same class, up to a marker character.
int nextch;
bool should_be_alnum = isalnum(firstch);
while((nextch = strm.peek()) != EOF) {
if(nextch == '@' || nextch == '#')
break;
else if(should_be_alnum == (bool)isalnum(nextch))
ret.push_back(strm.get());
else
break;
}
return ret;
}
int main()
{
// Numeric substitutions
std::vector<string> numsub;
// Letter substitutions
std::vector<string> charsub;
string word;
while((word = read_next(std::cin)) != "") {
if(word[0] == '@') {
// Translate.
std::cout << charsub[word[1] - '!'];
} else if(word[0] == '#') {
// Translate.
std::cout << numsub[std::stoi(word.substr(1))];
} else if(isalnum(word[0])) {
// Record.
if(word.length() > CUTOFF) {
// Record a long word with an integer.
numsub.push_back(word);
} else if(word.length() == CUTOFF) {
// Record a short word with a letter.
if('!' + charsub.size() <= '~') {
charsub.push_back(word);
}
}
std::cout << word;
} else {
// Output
std::cout << word;
}
}
}