diff --git a/Utility/CMakeLists.txt b/Utility/CMakeLists.txt index e59a3c6..2c1bf06 100644 --- a/Utility/CMakeLists.txt +++ b/Utility/CMakeLists.txt @@ -3,3 +3,4 @@ target_sources( alepha PRIVATE ) add_subdirectory( derived_pointer_cast.test ) +add_subdirectory( print_number.test ) diff --git a/Utility/print_number.h b/Utility/print_number.h new file mode 100644 index 0000000..bebb7e2 --- /dev/null +++ b/Utility/print_number.h @@ -0,0 +1,115 @@ +static_assert( __cplusplus > 2020'99 ); + +#pragma once + +#include + +#include + +#include +#include +#include +#include + +namespace Alepha::Hydrogen::Utility ::detail:: print_number_m +{ + inline namespace exports + { + std::string formatPrint( std::uint64_t ); + } + + inline std::string + exports::formatPrint( std::uint64_t value ) + { + const std::map< int, std::string > names + { + { 1, "one" }, + { 2, "two" }, + { 3, "three" }, + { 4, "four" }, + { 5, "five" }, + { 6, "six" }, + { 7, "seven" }, + { 8, "eight" }, + { 9, "nine" }, + { 10, "ten" }, + { 11, "eleven" }, + { 12, "twelve" }, + { 13, "thirteen" }, + { 14, "fourteen" }, + { 15, "fifteen" }, + { 16, "sixteen" }, + { 17, "seventeen" }, + { 18, "eighteen" }, + { 19, "nineteen" }, + }; + + const std::map< int, std::string > tens + { + { 20, "twenty" }, + { 30, "thirty" }, + { 40, "forty" }, + { 50, "fifty" }, + { 60, "sixty" }, + { 70, "seventy" }, + { 80, "eighty" }, + { 90, "ninety" }, + }; + + // One Thousand to the N + const std::map< std::uint64_t, std::string > powers + { + { 0, "" }, + { 1, "thousand" }, + { 2, "million" }, + { 3, "billion" }, + { 4, "trillion" }, + { 5, "quadrillion" }, + { 6, "quintillion" }, + }; + + std::vector< std::string > parts; + + if( value == 0 ) return "zero"; + + for( int millennium= 0; value; ++millennium ) + { + auto remainder= value % 1000; + value/= 1000; + if( not remainder ) continue; + std::string next; + if( remainder >= 100 ) next+= names.at( remainder / 100 ) + " hundred "; + remainder%= 100; + if( remainder >= 20 ) + { + next+= tens.at( remainder - remainder % 10 ); + if( remainder % 10 ) next+= " " + names.at( remainder % 10 ); + } + else if( remainder ) + { + next+= names.at( remainder ); + } + next+= " " + powers.at( millennium ); + parts.push_back( std::move( next ) ); + } + + std::reverse( begin( parts ), end( parts ) ); + std::string rv; + bool first= true; + for( auto part: parts ) + { + while( part.back() == ' ' ) part.pop_back(); + while( part.front() == ' ' ) part= part.substr( 1 ); + if( not first ) rv+= ' '; + rv+= part; + first= false; + } + + return rv; + } +} + +namespace Alepha::Hydrogen::Utility::inline exports::inline print_number_m +{ + using namespace detail::print_number_m::exports; +} diff --git a/Utility/print_number.test/0.cc b/Utility/print_number.test/0.cc new file mode 100644 index 0000000..2549748 --- /dev/null +++ b/Utility/print_number.test/0.cc @@ -0,0 +1,39 @@ +static_assert( __cplusplus > 2020'99 ); + +#include "../print_number.h" + +#include +#include + +#include + +static auto init= Alepha::Utility::enroll <=[] +{ + using namespace Alepha::Testing::exports; + "Do simple numerical tests come out as we want?"_test + <=TableTest< Alepha::Utility::formatPrint >::Cases + { + { "zero", { 0 }, "zero" }, + { "one", { 1 }, "one" }, + { "seven hundred", { 700 }, "seven hundred" }, + { "one thousand twenty four", { 1024 }, "one thousand twenty four" }, + { "ten thousand two hundred forty", { 10240 }, "ten thousand two hundred forty" }, + { "1283721", { 1'283'721 }, "one million two hundred eighty three thousand seven hundred twenty one" }, + { "1000283000721", { 1'000'283'000'721 }, + "one trillion two hundred eighty three million seven hundred twenty one" }, + + { "1000283000000", { 1'000'283'000'000 }, + "one trillion two hundred eighty three million" }, + }; + + -"repl"_test <=[] + { + while( std::cin ) + { + std::uint64_t value; + std::cout << "input: " << std::flush; + std::cin >> value; + std::cout << Alepha::Utility::formatPrint( value ) << std::endl; + } + }; +}; diff --git a/Utility/print_number.test/CMakeLists.txt b/Utility/print_number.test/CMakeLists.txt new file mode 100644 index 0000000..b099603 --- /dev/null +++ b/Utility/print_number.test/CMakeLists.txt @@ -0,0 +1 @@ +unit_test( 0 )