From 54900d5a3620a8ec004fe788200027b14e39a20b Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Wed, 7 Dec 2022 07:29:23 +0000 Subject: [PATCH] Add 2022 Day 7. --- 2022/puzzle-07-01.cc | 99 ++++++++++++++++++++++++++++++++++++++++ 2022/puzzle-07-02.cc | 106 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 205 insertions(+) create mode 100644 2022/puzzle-07-01.cc create mode 100644 2022/puzzle-07-02.cc diff --git a/2022/puzzle-07-01.cc b/2022/puzzle-07-01.cc new file mode 100644 index 0000000..57da6a7 --- /dev/null +++ b/2022/puzzle-07-01.cc @@ -0,0 +1,99 @@ +// +// Created by Matthew Gretton-Dann on 07/12/2022. +// + +#include +#include +#include +#include +#include +#include +#include + +using UInt = std::uint64_t; + +struct DirectoryInfo +{ + auto total_size() const noexcept -> UInt + { + UInt file_size{std::accumulate(files_.begin(), files_.end(), UInt{0}, + [](UInt a, auto const& b) { return a + b.second; })}; + UInt directory_size{ + std::accumulate(dirs_.begin(), dirs_.end(), UInt{0}, + [](UInt a, auto const& b) { return a + b.second.total_size(); })}; + return file_size + directory_size; + } + + auto find_dir(std::string const& name) + { + auto it{dirs_.find(name)}; + assert(it != dirs_.end()); + return it; + } + + auto add_dir(std::string const& name) { dirs_.insert({name, DirectoryInfo()}); } + + auto add_file(std::string const& name, UInt size) { files_.insert({name, size}); } + + std::map files_; + std::map dirs_; +}; + +using DirIt = std::map::iterator; + +auto count_dir_sizes(DirIt root, UInt max_size) -> UInt +{ + UInt result{0}; + auto root_size = root->second.total_size(); + if (root_size <= max_size) { + result += root_size; + } + for (auto it = root->second.dirs_.begin(); it != root->second.dirs_.end(); ++it) { + result += count_dir_sizes(it, max_size); + } + return result; +} + +auto main() -> int +{ + UInt const max_size{100000}; + std::string line; + + std::list its; + std::map dirs; + auto root{dirs.insert({"/", DirectoryInfo()}).first}; + while (std::getline(std::cin, line) && !line.empty()) { + if (line == "$ cd /") { + its.clear(); + its.push_back(root); + } + else if (line == "$ cd ..") { + assert(!its.empty()); + its.pop_back(); + } + else if (line == "$ ls") { + continue; + } + else if (line.substr(0, 5) == "$ cd ") { + auto sub_dir{line.substr(5)}; + assert(!its.empty()); + auto it{its.back()->second.find_dir(sub_dir)}; + its.push_back(it); + } + else if (line.substr(0, 4) == "dir ") { + its.back()->second.add_dir(line.substr(4)); + } + else { + static std::regex const re{R"((\d+) ([a-z]+))"}; + std::smatch m; + if (!std::regex_search(line, m, re)) { + std::cerr << "Unable to interpret: " << line << "\n"; + std::exit(1); + } + its.back()->second.add_file(m.str(2), std::stoul(m.str(1))); + } + } + + std::cout << "Total sizes: " << count_dir_sizes(root, max_size) << '\n'; + return 0; +} diff --git a/2022/puzzle-07-02.cc b/2022/puzzle-07-02.cc new file mode 100644 index 0000000..3a1c1b1 --- /dev/null +++ b/2022/puzzle-07-02.cc @@ -0,0 +1,106 @@ +// +// Created by Matthew Gretton-Dann on 07/12/2022. +// + +#include +#include +#include +#include +#include +#include +#include + +using UInt = std::uint64_t; + +struct DirectoryInfo +{ + auto total_size() const noexcept -> UInt + { + UInt file_size{std::accumulate(files_.begin(), files_.end(), UInt{0}, + [](UInt a, auto const& b) { return a + b.second; })}; + UInt directory_size{ + std::accumulate(dirs_.begin(), dirs_.end(), UInt{0}, + [](UInt a, auto const& b) { return a + b.second.total_size(); })}; + return file_size + directory_size; + } + + auto find_dir(std::string const& name) + { + auto it{dirs_.find(name)}; + assert(it != dirs_.end()); + return it; + } + + auto add_dir(std::string const& name) { dirs_.insert({name, DirectoryInfo()}); } + + auto add_file(std::string const& name, UInt size) { files_.insert({name, size}); } + + std::map files_; + std::map dirs_; +}; + +using DirIt = std::map::iterator; + +auto size_to_free(DirIt root, UInt min) -> UInt +{ + UInt result{std::numeric_limits::max()}; + + auto root_size = root->second.total_size(); + if (root_size >= min) { + result = std::min(result, root_size); + } + for (auto it = root->second.dirs_.begin(); it != root->second.dirs_.end(); ++it) { + auto t{size_to_free(it, min)}; + if (t >= min) { + result = std::min(result, t); + } + } + return result; +} + +auto main() -> int +{ + std::string line; + + std::list its; + std::map dirs; + auto root{dirs.insert({"/", DirectoryInfo()}).first}; + while (std::getline(std::cin, line) && !line.empty()) { + if (line == "$ cd /") { + its.clear(); + its.push_back(root); + } + else if (line == "$ cd ..") { + assert(!its.empty()); + its.pop_back(); + } + else if (line == "$ ls") { + continue; + } + else if (line.substr(0, 5) == "$ cd ") { + auto sub_dir{line.substr(5)}; + assert(!its.empty()); + auto it{its.back()->second.find_dir(sub_dir)}; + its.push_back(it); + } + else if (line.substr(0, 4) == "dir ") { + its.back()->second.add_dir(line.substr(4)); + } + else { + static std::regex const re{R"((\d+) ([a-z]+))"}; + std::smatch m; + if (!std::regex_search(line, m, re)) { + std::cerr << "Unable to interpret: " << line << "\n"; + return EXIT_FAILURE; + } + its.back()->second.add_file(m.str(2), std::stoul(m.str(1))); + } + } + + UInt constexpr disk_size{70000000}; + UInt constexpr needed_space{30000000}; + UInt current_space{disk_size - root->second.total_size()}; + UInt min_space_to_free(needed_space - current_space); + std::cout << "Size to free: " << size_to_free(root, min_space_to_free) << '\n'; + return 0; +}