From 9cc732f746b9af6d5fac63d2e06835cddad58842 Mon Sep 17 00:00:00 2001 From: Benjamin Kraft Date: Wed, 7 Dec 2022 09:19:04 +0100 Subject: [PATCH] Day07 --- src/days/07/Day07.cpp | 128 +++++++++++++++++++++++++++++++++++++++++- src/days/07/Day07.h | 28 +++++++++ 2 files changed, 153 insertions(+), 3 deletions(-) diff --git a/src/days/07/Day07.cpp b/src/days/07/Day07.cpp index d89165a..0d252f4 100644 --- a/src/days/07/Day07.cpp +++ b/src/days/07/Day07.cpp @@ -1,9 +1,131 @@ #include "Day07.h" Result Day07::Task1() { - return Day::Task1(); + Dir* tree = parseTree(); + + set dirsBelow = tree->getAllDirsBelowSize(100000); + uint64_t sum = accumulate(dirsBelow.begin(), dirsBelow.end(), 0, [](uint64_t s, Dir* dir){ + return s + dir->getSize(); + }); + + delete tree; + return to_string(sum); } Result Day07::Task2() { - return Day::Task2(); -} \ No newline at end of file + Dir* tree = parseTree(); + + uint64_t toBeFreed = 30000000 - (70000000 - tree->getSize()); + + set dirsAbove = tree->getAllDirsAboveSize(toBeFreed); + set sizes; + std::transform(dirsAbove.begin(), dirsAbove.end(), inserter(sizes, sizes.begin()), [](Dir* dir){ + return dir->getSize(); + }); + uint64_t result = *std::min_element(sizes.begin(), sizes.end()); + + delete tree; + return to_string(result); +} + +Dir* Day07::parseTree() { + Dir* tree = new Dir("/", nullptr); + Dir* cwd = tree; + + auto pos = input.begin() + 1; + while (pos < input.end()){ + if (pos->starts_with('$')){ + if (pos->substr(2, 2) == "ls"){ + pos++; + while (pos < input.end() && !pos->starts_with('$')){ + if (pos->starts_with("dir")){ + string name = pos->substr(4); + cwd->items.insert(new Dir(name, cwd)); + } else { + size_t ws = pos->find(' '); + uint64_t size = stoi(pos->substr(0, ws)); + string name = pos->substr(ws + 1); + cwd->items.insert(new File(name, cwd, size)); + } + pos++; + } + continue; + } + if (pos->substr(2, 2) == "cd"){ + string name = pos->substr(5); + if (name == ".."){ + cwd = cwd->parent; + } else if (name == "/"){ + cwd = cwd->findRoot(); + } else { + for (Item* item : cwd->items){ + if (item->name == name){ + if (Dir* d = dynamic_cast(item)){ + cwd = d; + break; + } + } + } + } + pos++; + } + } + } + + return tree; +} + +Dir *Dir::findRoot() { + if (name == "/") + return this; + return parent->findRoot(); +} + +uint64_t Dir::getSize() { + return accumulate(items.begin(), items.end(), 0, [](uint64_t s, Item* item){ + return s + item->getSize(); + }); +} + +set Dir::getDirs() { + set dirs; + for (Item* item : items){ + if (Dir* d = dynamic_cast(item)) + dirs.insert(d); + } + return dirs; +} + +set Dir::getAllDirsBelowSize(uint64_t maxSize) { + set result; + + for (Dir* dir : getDirs()){ + if (dir->getSize() <= maxSize) + result.insert(dir); + set sub = dir->getAllDirsBelowSize(maxSize); + result.insert(sub.begin(), sub.end()); + } + + return result; +} + +set Dir::getAllDirsAboveSize(uint64_t minSize) { + set result; + + for (Dir* dir : getDirs()){ + if (dir->getSize() >= minSize) + result.insert(dir); + set sub = dir->getAllDirsAboveSize(minSize); + result.insert(sub.begin(), sub.end()); + } + + return result; +} + +uint64_t File::getSize() { + return size; +} + +uint64_t Item::getSize() { + return 0; +} diff --git a/src/days/07/Day07.h b/src/days/07/Day07.h index 39f98fe..4bb7457 100644 --- a/src/days/07/Day07.h +++ b/src/days/07/Day07.h @@ -2,9 +2,37 @@ #include "../../Day.h" +struct Dir; + +struct Item { + Item(string name, Dir* parent) : name(name), parent(parent){}; + string name; + Dir* parent; + virtual uint64_t getSize(); +}; + +struct Dir : Item { + Dir(string name, Dir* parent) : Item(name, parent) {} + set items; + Dir* findRoot(); + uint64_t getSize(); + set getDirs(); + set getAllDirsBelowSize(uint64_t maxSize); + set getAllDirsAboveSize(uint64_t minSize); +}; + +struct File : Item { + File(string name, Dir* parent, uint64_t size) : Item(name, parent), size(size) {} + uint64_t size; + uint64_t getSize(); +}; + class Day07 : public Day { protected: + Result Task1() override; Result Task2() override; + + Dir* parseTree(); }; \ No newline at end of file