Advent of Code 2022 - 2nd attempt in c++
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

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);
}