#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cstdint>
// ------------------------------------------------------------
// LZW Compression (12‑bit codes, stored as 16‑bit values)
// ------------------------------------------------------------
void compress(const std::string& inFile, const std::string& outFile) {
std::ifstream in(inFile, std::ios::binary);
if (!in) {
std::cerr << "Error: cannot open input file " << inFile << std::endl;
return;
std::ofstream out(outFile, std::ios::binary);
if (!out) {
std::cerr << "Error: cannot create output file " << outFile << std::endl;
return;
// Initial dictionary: all single bytes (0..255)
std::unordered_map<std::string, uint16_t> dict;
for (int i = 0; i < 256; ++i)
dict[std::string(1, static_cast<char>(i))] = static_cast<uint16_t>(i);
uint16_t nextCode = 256; // next available code
const uint16_t MAX_CODE = 4096; // 12‑bit limit
std::string w; // current sequence
char c;
while ([Link](c)) { // read one byte
std::string wc = w + c;
if ([Link](wc) != [Link]()) {
w = wc; // sequence exists → extend
} else {
// output code for w
uint16_t code = dict[w];
[Link](reinterpret_cast<const char*>(&code), sizeof(code));
// add wc to dictionary if space permits
if (nextCode < MAX_CODE) {
dict[wc] = nextCode++;
w = c; // start new sequence with current byte
}
}
// output code for the last sequence
if (![Link]()) {
uint16_t code = dict[w];
[Link](reinterpret_cast<const char*>(&code), sizeof(code));
std::cout << "Compression complete. Output written to " << outFile << std::endl;
// ------------------------------------------------------------
// LZW Decompression
// ------------------------------------------------------------
void decompress(const std::string& inFile, const std::string& outFile) {
std::ifstream in(inFile, std::ios::binary);
if (!in) {
std::cerr << "Error: cannot open input file " << inFile << std::endl;
return;
std::ofstream out(outFile, std::ios::binary);
if (!out) {
std::cerr << "Error: cannot create output file " << outFile << std::endl;
return;
// Initial dictionary: codes 0..255 map to single bytes
std::unordered_map<uint16_t, std::string> dict;
for (int i = 0; i < 256; ++i)
dict[static_cast<uint16_t>(i)] = std::string(1, static_cast<char>(i));
uint16_t nextCode = 256;
const uint16_t MAX_CODE = 4096;
uint16_t prevCode;
if (, sizeof(prevCode))) {
std::cerr << "Error: empty or invalid compressed file" << std::endl;
return;
// Write first sequence
std::string entry = dict[prevCode];
[Link]([Link](), [Link]());
uint16_t currCode;
while ([Link](reinterpret_cast<char*>(&currCode), sizeof(currCode))) {
std::string currEntry;
if ([Link](currCode) != [Link]()) {
currEntry = dict[currCode];
} else if (currCode == nextCode) {
// Special case: code not yet in dictionary (occurs when sequence is
// formed by previous entry + first char of previous entry)
currEntry = dict[prevCode] + dict[prevCode][0];
} else {
std::cerr << "Error: invalid code " << currCode << " encountered" << std::endl;
return;
[Link]([Link](), [Link]());
// Add new sequence: previous entry + first char of current entry
if (nextCode < MAX_CODE) {
dict[nextCode++] = dict[prevCode] + currEntry[0];
prevCode = currCode;
std::cout << "Decompression complete. Output written to " << outFile << std::endl;
// ------------------------------------------------------------
// Main: parse command line and call appropriate function
// ------------------------------------------------------------
int main(int argc, char* argv[]) {
if (argc != 4) {
std::cerr << "Usage: " << argv[0] << " <c|d> <input_file> <output_file>\n"
<< " c - compress\n"
<< " d - decompress\n";
return 1;
std::string mode = argv[1];
std::string input = argv[2];
std::string output = argv[3];
if (mode == "c") {
compress(input, output);
} else if (mode == "d") {
decompress(input, output);
} else {
std::cerr << "Error: mode must be 'c' or 'd'" << std::endl;
return 1;
return 0;