#include "Folder.h" #include "SplitStr.h" #include #include #include #include #include #include void DebugOutput(File *file) { static int indent = -1; ++indent; for(auto i = 0; i < indent; ++i) std::cout << " "; Folder *folder = dynamic_cast(file); if(folder) { std::cout << "Contents of folder: " << folder->Filename() << ", size: " << folder->Size() << std::endl; for(File *file : folder->Files()) DebugOutput(file); } else std::cout << "- " << file->Filename() << ", size: " << file->Size() << std::endl; --indent; } unsigned long PartOne(File *file, unsigned long &grand_total) { unsigned long rtn = 0; Folder *folder = dynamic_cast(file); if(folder) { for(File *file : folder->Files()) rtn += PartOne(file, grand_total); if(rtn <= 100000) { grand_total += rtn; std::cout << "Folder \"" << folder->Filename() << "\" has a size of " << rtn << std::endl; } } else rtn += file->Size(); return rtn; } void PartTwo(File *file, unsigned long at_least, File *&smallest) { Folder *folder = dynamic_cast(file); if(folder) { if(folder->Size() >= at_least && folder->Size() < smallest->Size()) { std::cout << "New smallest size of " << folder->Size() << " by folder \"" << folder->Filename() << "\"." << std::endl; smallest = file; } for(File *file : folder->Files()) PartTwo(file, at_least, smallest); } return; } void Parse(Folder &root) { std::ifstream ifs("data.txt"); if(!ifs.is_open()) { std::cerr << "Missing data.txt." << std::endl; exit(-1); } std::stack dir_stack; dir_stack.push(&root); // Step 1: Parse: for(std::string line; std::getline(ifs, line); ) { if(line == "") continue; if(line.starts_with("$ ls")) continue; else if(line.starts_with("$ cd")) { auto to = line.substr(5); if(to == "/") { while(dir_stack.size() > 1) dir_stack.pop(); } else if(to == "..") { if(dir_stack.size() > 1) dir_stack.pop(); } else { auto existing = std::find_if(dir_stack.top()->Files().begin(), dir_stack.top()->Files().end(), [&to](const File *f){ return f->Filename() == to; }); if(existing != dir_stack.top()->Files().end()) // found! { // Check to see if it's a folder, first: Folder *folder = dynamic_cast(*existing); if(folder) dir_stack.push(folder); else { std::cerr << (*existing)->Filename() << " is a file, not a folder." << std::endl; exit(-3); } } else std::cerr << "could not navigate to \"" << to << "\" from \"" << dir_stack.top()->Filename() << "\"." << std::endl; } } else if(line.starts_with("dir ")) { dir_stack.top()->AddFolder(line.substr(4)); } else { auto values = SplitStr(line, " "); dir_stack.top()->AddFile(values[1], std::atol(values[0].c_str())); } } } int main() { Folder root("/"); Parse(root); // Step 1.5: Debug output: DebugOutput(&root); unsigned long grand_total = 0; PartOne(&root, grand_total); std::cout << "Grand Total (part 1): " << grand_total << std::endl; const unsigned long max_space = 70000000; const unsigned long space_needed = 30000000; const unsigned long currently_used = root.Size(); const unsigned long currently_unused = max_space - currently_used; const unsigned long amt_to_remove = space_needed - currently_unused; File *file_to_remove = &root; PartTwo(&root, amt_to_remove, file_to_remove); std::cout << "Remove \"" << file_to_remove->Filename() << "\" to free up " << file_to_remove->Size() << " which is the smallest amount >= " << amt_to_remove << " (part 2)." << std::endl; return 0; }