#include <iostream>
#include <vector>
#include <map>
#include <cstdint>
#include <tuple>
#include <random>
#include <algorithm>
typedef std::vector<std::uint8_t> DType;
typedef std::vector<DType> Table;
typedef std::map<DType, bool> TableM;
typedef std::vector<std::size_t> CData;
typedef std::tuple<Table, CData> RType;
//LZW One of implimentation.
//working on VC12
//why not running??
DType MakeProblem(std::size_t N){
std::mt19937 mt;
std::uniform_int_distribution<> uid(0, 255);
DType D(N);
for (auto& o : D) o = uid(mt);
//std::sort(D.begin(), D.end());
return D;
}
RType EncodeLZW(DType& D){
Table Ta;
TableM M;
CData CD;
DType Sug;
bool F = false;
std::size_t C = 0;
for (auto& o : D){
Sug.push_back(o);
M[Sug] = true;
Sug.clear();
}
Sug.clear();
for (std::size_t i = 0; i < D.size(); i++){
Sug.push_back(D[i]);
if (M[Sug] == true){
continue;
}
M[Sug] = true;
i--;
Sug.clear();
}
M[Sug] = true;
Sug.clear();
for (std::size_t i = 0; i < D.size(); i++){
Sug.push_back(D[i]);
if (M.find(Sug) != M.end()) continue;
Sug.pop_back();
auto it = find(Ta.begin(), Ta.end(), Sug);
if (it == Ta.end()){
CD.push_back(Ta.size());
Ta.push_back(Sug);
}
else{
CD.push_back(std::distance(Ta.begin(), it));
}
i--;
Sug.clear();
}
auto it = find(Ta.begin(), Ta.end(), Sug);
if (it == Ta.end()){
CD.push_back(Ta.size());
Ta.push_back(Sug);
}
else{
CD.push_back(std::distance(Ta.begin(), it));
}
Sug.clear();
CD.push_back(Ta.size());
return std::make_tuple(Ta, CD);
}
DType DecodeLZW(RType& R){//手抜き
Table& T = std::get<0>(R);
CData& C = std::get<1>(R);
DType D;
for (auto& A : C){
for (auto& o : T[A]){
D.push_back(o);
}
}
return D;
}
int main(){
auto D = MakeProblem(10240);
auto En = EncodeLZW(D);
auto De = DecodeLZW(En);
auto& T = std::get<0>(En);
auto& C = std::get<1>(En);
if (D == De){
std::cout << "Match!" << std::endl;
}
else{
std::cout << "Miss Match!" << std::endl;
}
std::cout << "From " << D.size() << "Byte!" << std::endl;
std::cout << "Table = " << T.size() << "Count!" << std::endl;
std::cout << "Data = " << C.size() << "Count!" << std::endl;
return 0;
}