Untitled

 avatar
unknown
c_cpp
a year ago
8.0 kB
12
Indexable
struct User {
    int capacity;
    int used;
    User(){}
    User(int capacity) : capacity(capacity), used(0) {}

    bool canAddFile(int fileSize) {
        return used + fileSize <= capacity;
    }

    void addFile(int fileSize) {
        used += fileSize;
    }

    void removeFile(int fileSize) {
        used -= fileSize;
    }

    int remainingCapacity() {
        return capacity - used;
    }
};

struct CloudStorage {
    std::unordered_map<std::string, int> files; // File name to size mapping
    std::unordered_map<std::string, std::string> fileOwners; // File name to owner mapping
    std::unordered_map<std::string, User> users; // User ID to User object mapping
    std::map<int, std::set<std::string>, std::greater<int>> sizeToFileNames; // Size to file names mapping
    std::unordered_map<std::string, std::vector<std::pair<std::string, int>>> backups;

    CloudStorage() {
        // Adding an admin user with unlimited capacity
        users["admin"] = User(INT_MAX);
    }

    std::string addUser(const std::string& userId, int capacity) {
        if (users.find(userId) != users.end()) {
            return "false";
        }
        users[userId] = User(capacity);
        //cout << users[userId].capacity << '\n';
        return "true";
    }

    std::string addFileBy(const std::string& userId, const std::string& fileName, int size) {
        if (files.find(fileName) != files.end() || users.find(userId) == users.end() || !users[userId].canAddFile(size)) {
            return "";
        }
        files[fileName] = size;
        fileOwners[fileName] = userId;
        sizeToFileNames[size].insert(fileName);
        users[userId].addFile(size);
        cout << users[userId].capacity << '\n';
        return std::to_string(users[userId].remainingCapacity());
    }

    std::string mergeUsers(const std::string& userId1, const std::string& userId2) {
        if (userId1 == userId2 || users.find(userId1) == users.end() || users.find(userId2) == users.end()) {
            return "";
        }
        users[userId1].capacity += users[userId2].capacity;
        for (const auto& [fileName, size] : files) {
            if (fileOwners[fileName] == userId2) {
                fileOwners[fileName] = userId1;
                users[userId1].addFile(size);
                users[userId2].removeFile(size);
            }
        }
        
        int remainingCapacity = users[userId1].remainingCapacity();
        users.erase(userId2);
        return std::to_string(remainingCapacity);
    }

std::string addFile(const std::string& name, int size) {
    if (files.find(name) != files.end()) {
        return "false";
    }

    files[name] = size;
    fileOwners[name] = "admin";  // Associate the file with the admin user
    sizeToFileNames[size].insert(name);

    // No need to update the admin's used capacity since it's unlimited
    return "true";
}


    std::string getFileSize(const std::string& name) {
        auto it = files.find(name);
        if (it != files.end()) {
            return std::to_string(it->second);
        }
        return "";
    }

std::string deleteFile(const std::string& name) {
    auto it = files.find(name);
    if (it != files.end()) {
        int fileSize = it->second;
        std::string size = std::to_string(fileSize);
        sizeToFileNames[fileSize].erase(name);
        if (sizeToFileNames[fileSize].empty()) {
            sizeToFileNames.erase(fileSize);
        }
        
        // Find the owner of the file and update their used storage
        auto ownerIt = fileOwners.find(name);
        if (ownerIt != fileOwners.end()) {
            std::string ownerId = ownerIt->second;
            if (users.find(ownerId) != users.end()) {
                users[ownerId].removeFile(fileSize);
            }
            fileOwners.erase(ownerIt);
        }

        files.erase(it);
        return size;
    }
    return "";
}

std::string getNLargestWithPrefix(const std::string& prefix, int n) {
        std::vector<std::pair<std::string, int>> matchingFiles;
        for (const auto& [size, names] : sizeToFileNames) {
            for (const auto& name : names) {
                if (name.substr(0, prefix.length()) == prefix) {
                    matchingFiles.emplace_back(name, size);
                    if (matchingFiles.size() == n) break;
                }
            }
            if (matchingFiles.size() == n) break;
        }

        std::sort(matchingFiles.begin(), matchingFiles.end(), [](const auto& a, const auto& b) {
            return a.second == b.second ? a.first < b.first : a.second > b.second;
        });

        std::string result;
        for (const auto& [name, size] : matchingFiles) {
            if (!result.empty()) result += ", ";
            result += name + "(" + std::to_string(size) + ")";
        }
        return result;
    }
    std::string backupUser(const std::string& userId) {
        if (users.find(userId) == users.end()) {
            return "";  // User does not exist
        }
        std::vector<std::pair<std::string, int>>& userBackup = backups[userId];
        userBackup.clear();  // Clear existing backup

        for (const auto& [fileName, owner] : fileOwners) {
            if (owner == userId) {
                userBackup.emplace_back(fileName, files[fileName]);
            }
        }

        return std::to_string(userBackup.size());
    }

    // RESTORE_USER implementation
    std::string restoreUser(const std::string& userId) {
    if (users.find(userId) == users.end()) {
        return "";  // User does not exist
    }

    // First, delete all current files owned by the user
    std::vector<std::string> filesToDelete;
    for (const auto& [fileName, owner] : fileOwners) {
        if (owner == userId) {
            filesToDelete.push_back(fileName);
        }
    }

    for (const auto& fileName : filesToDelete) {
        deleteFile(fileName);
    }

    // Now, proceed with the restoration from the backup
    if (backups.find(userId) == backups.end()) {
        return "0";  // No backup exists, so nothing is restored
    }

    int restoredFilesCount = 0;
    for (const auto& [fileName, size] : backups[userId]) {
        if (files.find(fileName) == files.end()) {
            // Restore file if it does not exist
            files[fileName] = size;
            fileOwners[fileName] = userId;
            sizeToFileNames[size].insert(fileName);
            users[userId].addFile(size);
            restoredFilesCount++;
        }
        // If file with same name exists, it's ignored
    }

    return std::to_string(restoredFilesCount);
}

};




vector<string> solution(vector<vector<string>> queries) {
    CloudStorage storage;
    vector<string>ans;
    for(auto q: queries){
        auto op = q[0];
        if(op == "ADD_FILE"){
            ans.push_back(storage.addFile(q[1], stoi(q[2])));
        }
        else if(op == "GET_FILE_SIZE"){
            ans.push_back(storage.getFileSize(q[1]));
        }
        else if(op == "GET_N_LARGEST"){
            ans.push_back(storage.getNLargestWithPrefix(q[1], stoi(q[2])));
        }
        else if(op == "ADD_USER"){
            ans.push_back(storage.addUser(q[1], stoi(q[2])));
        }
        else if(op == "ADD_FILE_BY"){
            ans.push_back(storage.addFileBy(q[1], q[2], stoi(q[3])));
        }
        else if(op == "MERGE_USER"){
            ans.push_back(storage.mergeUsers(q[1], q[2]));
        }
        else if(op == "BACKUP_USER"){
            ans.push_back(storage.backupUser(q[1]));
        }
        else if(op == "RESTORE_USER")
            ans.push_back(storage.restoreUser(q[1]));
        else{
            ans.push_back(storage.deleteFile(q[1]));
        }
    }
    return ans;
}
Editor is loading...
Leave a Comment