#include <array>
#include <fstream>
#include <string_view>
#include <string>
#include <functional>

constexpr size_t nCol = 45;
constexpr size_t nStartCol = 3;

template <typename T>
auto makeHash(T const& v) {
    std::hash<T> hash;
    return hash(v);
}

struct Entry {
    std::string_view value;
    size_t hash;

    Entry() noexcept = default;

    template <typename It, typename End>
        Entry(It it, End end): value(it, end), hash(makeHash(value)) {}
};

bool operator==(Entry const& a, Entry const& b) noexcept {

    if(a.hash != b.hash) {
        return false;
    }

    if(a.value != b.value) {
        return false;
    }

    return true;
}

auto lineToEntries(std::string const& line) {

    std::array<Entry, nCol> entries;
    auto itr = line.begin();
    auto const end = line.end();

    for(size_t col = 0; col < nCol; ++col) {
        auto const tmp = itr;

        itr = std::find(tmp, end, ';');

        if(itr == end) {
            throw std::exception();
        }

        itr += 1;
        entries[col] = Entry(tmp, itr);
    }
    return entries;
}

int main() {

    std::ifstream inFile("list.txt");
    std::ofstream outFile("nodup.txt");
    std::ios_base::sync_with_stdio(false);

    if(!inFile.is_open()) {
        return -1;
    }

    std::string line(1000, '\0');
    while(std::getline(inFile, line)) {

        auto const entries = lineToEntries(line);

        for(auto const& entry: entries) {
            auto const itr = std::find(&entries[nStartCol], &entry, entry);

            if(itr == &entry) {
                outFile.write(entry.value.data(), entry.value.length());
            } else {
                outFile.put(';');
            }
        }
        outFile.put('\n');
    }
    return 0;
}
