You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
163 lines
3.9 KiB
163 lines
3.9 KiB
2 years ago
|
#include <iostream>
|
||
|
#include <vector>
|
||
|
#include <map>
|
||
|
|
||
|
using namespace std;
|
||
|
|
||
|
enum FsNodeType {
|
||
|
NODE_DIR,
|
||
|
NODE_FILE
|
||
|
};
|
||
|
|
||
|
struct FsNode {
|
||
|
FsNodeType type;
|
||
|
string name;
|
||
|
unsigned size;
|
||
|
};
|
||
|
|
||
|
struct FsFile : FsNode {
|
||
|
};
|
||
|
|
||
|
struct FsDir : FsNode {
|
||
|
FsDir *parent;
|
||
|
map<string, FsNode *> entries;
|
||
|
};
|
||
|
|
||
|
void print_node(FsNode *node, unsigned depth = 0)
|
||
|
{
|
||
|
for (unsigned i = 0; i < depth; i++) clog << " ";
|
||
|
clog << "- " << node->name << " (";
|
||
|
switch (node->type) {
|
||
|
case NODE_DIR: clog << "dir"; break;
|
||
|
case NODE_FILE: clog << "file"; break;
|
||
|
}
|
||
|
clog << ", ";
|
||
|
clog << "size=" << node->size;
|
||
|
clog << ")" << endl;
|
||
|
|
||
|
if (node->type == NODE_DIR) {
|
||
|
FsDir *dir = (FsDir *)node;
|
||
|
for (auto e : dir->entries) print_node(e.second, depth + 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
unsigned calc_size(FsDir &dir)
|
||
|
{
|
||
|
unsigned size = 0;
|
||
|
for (auto e : dir.entries) {
|
||
|
FsNode *node = e.second;
|
||
|
|
||
|
if (!node->size && node->type == NODE_DIR) calc_size(*(FsDir *)node);
|
||
|
size += node->size;
|
||
|
}
|
||
|
dir.size = size;
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
FsDir parse()
|
||
|
{
|
||
|
FsDir root;
|
||
|
root.type = NODE_DIR;
|
||
|
root.name = "/";
|
||
|
root.parent = NULL;
|
||
|
|
||
|
FsDir *dir = &root;
|
||
|
for (string line; getline(cin, line);) {
|
||
|
if (line.at(0) != '$' || line.at(1) != ' ') {
|
||
|
unsigned split = line.find(' ');
|
||
|
string first = line.substr(0, split);
|
||
|
string name = line.substr(split + 1);
|
||
|
|
||
|
if (first == "dir") {
|
||
|
FsDir *newdir = new FsDir;
|
||
|
newdir->type = NODE_DIR;
|
||
|
newdir->name = name;
|
||
|
newdir->size = 0;
|
||
|
newdir->parent = dir;
|
||
|
dir->entries[name] = newdir;
|
||
|
} else {
|
||
|
unsigned size = stoi(first);
|
||
|
FsFile *newfile = new FsFile;
|
||
|
newfile->type = NODE_FILE;
|
||
|
newfile->name = name;
|
||
|
newfile->size = size;
|
||
|
dir->entries[name] = newfile;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (line.substr(2, 3) == "ls") {
|
||
|
// derp?
|
||
|
} else if (line.substr(2, 3) == "cd ") {
|
||
|
string name = line.substr(5);
|
||
|
if (name == "/") {
|
||
|
dir = &root;
|
||
|
} else if (name == "..") {
|
||
|
if (dir->parent) dir = dir->parent;
|
||
|
} else {
|
||
|
auto it = dir->entries.find(name);
|
||
|
if (it != dir->entries.end()) {
|
||
|
FsNode *node = it->second;
|
||
|
if (node->type == NODE_DIR) {
|
||
|
dir = (FsDir *)node;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
calc_size(root);
|
||
|
//print_node(&root);
|
||
|
return root;
|
||
|
}
|
||
|
|
||
|
unsigned p1(const FsDir &dir)
|
||
|
{
|
||
|
unsigned count = 0;
|
||
|
if (dir.size <= 100000) count += dir.size;
|
||
|
for (auto e : dir.entries) {
|
||
|
FsNode *node = e.second;
|
||
|
if (node->type == NODE_DIR) count += p1(*(FsDir *)node);
|
||
|
}
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
unsigned p2(const FsDir &dir, unsigned target = 0)
|
||
|
{
|
||
|
if (!target) target = dir.size - 40000000;
|
||
|
|
||
|
unsigned smallest = 30000000;
|
||
|
if (dir.size >= target && dir.size < smallest) smallest = dir.size;
|
||
|
|
||
|
for (auto e : dir.entries) {
|
||
|
FsNode *node = e.second;
|
||
|
if (node->type == NODE_DIR) {
|
||
|
unsigned size = p2(*(FsDir *)node, target);
|
||
|
if (size >= target && size < smallest) smallest = size;
|
||
|
}
|
||
|
}
|
||
|
return smallest;
|
||
|
}
|
||
|
|
||
|
void free_input(FsDir &dir)
|
||
|
{
|
||
|
for (auto e : dir.entries) {
|
||
|
FsNode *node = e.second;
|
||
|
if (node->type == NODE_DIR) {
|
||
|
FsDir *dir = (FsDir *)node;
|
||
|
free_input(*dir);
|
||
|
delete dir;
|
||
|
} else if (node->type == NODE_FILE) {
|
||
|
FsFile *file = (FsFile *)node;
|
||
|
delete file;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int main()
|
||
|
{
|
||
|
auto input = parse();
|
||
|
cout << p1(input) << endl;
|
||
|
cout << p2(input) << endl;
|
||
|
free_input(input);
|
||
|
}
|