From 1903f19b9645ff42e3c70652ab4cf646adaf7f4c Mon Sep 17 00:00:00 2001 From: Leonetienne Date: Sun, 27 Feb 2022 17:52:14 +0100 Subject: [PATCH] Abstracted BaseX_2_10 to work with arbitrary containers and digit-types --- Src/GeneralUtility.cpp | 30 ------------------------------ Src/GeneralUtility.h | 34 +++++++++++++++++++++++++++++++++- Test/BaseX_2_10.cpp | 22 +++++++++++++++++++++- 3 files changed, 54 insertions(+), 32 deletions(-) diff --git a/Src/GeneralUtility.cpp b/Src/GeneralUtility.cpp index d7c20f1..9ff92b3 100644 --- a/Src/GeneralUtility.cpp +++ b/Src/GeneralUtility.cpp @@ -3,36 +3,6 @@ #include #include -namespace { - // Fast 64-bit int power function - inline std::uint64_t Powuli(const std::uint64_t &b, const std::uint64_t &e) { - std::uint64_t buf = 1; - - for (std::uint64_t i = 0; i < e; i++) - buf *= b; - - return buf; - } -} - -std::uint64_t GeneralUtility::BaseX_2_10(const std::string& num, const std::string& set) { - // If base is 0, throw logic error - if (set.length() == 0) - throw std::logic_error("Can't convert from base0! Please supply a nonempty set!"); - - unsigned long long int buf = 0; - for (std::size_t i = 0; i < num.length(); i++) { - for (std::size_t j = 0; j < set.length(); j++) { - if (num[i] == set[j]) { - buf += Powuli((std::uint64_t)set.length(), (uint64_t)(num.length() - (i + 1))) * j; - break; - } - } - } - - return buf; -} - // Based on: https://www.geeksforgeeks.org/divide-large-number-represented-string/ std::pair GeneralUtility::StringDivision(const std::string& dividend, const unsigned int divisor, const std::string& set) { diff --git a/Src/GeneralUtility.h b/Src/GeneralUtility.h index bd1897d..9e53911 100644 --- a/Src/GeneralUtility.h +++ b/Src/GeneralUtility.h @@ -27,7 +27,8 @@ public: //! \param num A string representing the number //! \param set The set/base of the number //! \return A 64-bit integer representing the number - static std::uint64_t BaseX_2_10(const std::string& num, const std::string& set); + template + static std::uint64_t BaseX_2_10(const T_Container& num, const T_Container& set); //! Will convert a number to an arbitrary base. //! This just a wrapper for BaseX_2_Y. @@ -49,6 +50,37 @@ private: GeneralUtility(); }; +namespace { + // Fast 64-bit int power function + inline std::uint64_t Powuli(const std::uint64_t &b, const std::uint64_t &e) { + std::uint64_t buf = 1; + + for (std::uint64_t i = 0; i < e; i++) + buf *= b; + + return buf; + } +} + +template +std::uint64_t GeneralUtility::BaseX_2_10(const T_Container& num, const T_Container& set) { + // If base is 0, throw logic error + if (set.size() == 0) + throw std::logic_error("Can't convert from base0! Please supply a nonempty set!"); + + unsigned long long int buf = 0; + for (std::size_t i = 0; i < num.size(); i++) { + for (std::size_t j = 0; j < set.size(); j++) { + if (num[i] == set[j]) { + buf += Powuli((std::uint64_t)set.size(), (uint64_t)(num.size() - (i + 1))) * j; + break; + } + } + } + + return buf; +} + template int GeneralUtility::Ord(const T_Type& item, const T_Container& set) { const auto result = diff --git a/Test/BaseX_2_10.cpp b/Test/BaseX_2_10.cpp index cc90eec..ea99c04 100644 --- a/Test/BaseX_2_10.cpp +++ b/Test/BaseX_2_10.cpp @@ -65,6 +65,26 @@ TEST_CASE(__FILE__"/BaseFuckingBig_to_10", "[BaseX_2_10]") TEST_CASE(__FILE__"/NoSetSupplied", "[BaseX_2_10]") { REQUIRE_THROWS_AS( - GeneralUtility::BaseX_2_10("699", "") + GeneralUtility::BaseX_2_10("699", "") , std::logic_error); } + +// Tests that conversion with more complex 'digits' works. Weird-ass usecase +TEST_CASE(__FILE__"/BaseWeird_to_10", "[BaseX_2_10]") +{ + // Setup + + // Yes... That is actually our base... + const std::vector set = { "Banana", "Apple", "Peach", "Strawberry", "Tomato", "Cherry" }; + + // Yes, that is a fucking number. It's 69 in whatever the fuck that base is + const std::vector in = { "Apple", "Cherry", "Strawberry" }; + + const std::uint64_t expected_out = 69; + + // Exercise + const std::uint64_t out = GeneralUtility::BaseX_2_10(in, set); + + // Verify + REQUIRE(out == expected_out); +}