Advent-of-Code/2022/7/main.cpp

171 lines
3.9 KiB
C++
Raw Permalink Normal View History

#include "Folder.h"
#include "SplitStr.h"
2022-12-08 22:39:30 -05:00
#include <algorithm>
#include <fstream>
#include <iostream>
#include <stack>
#include <string>
#include <vector>
2022-12-08 22:52:31 -05:00
void DebugOutput(File *file)
{
static int indent = -1;
++indent;
for(auto i = 0; i < indent; ++i)
std::cout << " ";
Folder *folder = dynamic_cast<Folder*>(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<Folder*>(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<Folder*>(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)
2022-12-08 22:39:30 -05:00
{
std::ifstream ifs("data.txt");
if(!ifs.is_open())
{
std::cerr << "Missing data.txt." << std::endl;
exit(-1);
2022-12-08 22:39:30 -05:00
}
std::stack<Folder*> dir_stack;
dir_stack.push(&root);
2022-12-08 22:52:31 -05:00
// Step 1: Parse:
2022-12-08 22:39:30 -05:00
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<Folder*>(*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);
2022-12-08 22:39:30 -05:00
2022-12-08 22:52:31 -05:00
// 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;
2022-12-08 22:52:31 -05:00
2022-12-08 22:39:30 -05:00
return 0;
}