How to resolve the algorithm Wasteful, equidigital and frugal numbers step by step in the C++ programming language
How to resolve the algorithm Wasteful, equidigital and frugal numbers step by step in the C++ programming language
Table of Contents
Problem Statement
Let n be a positive integer and l(n) be the number of its digits in base b. Express n as the product of its prime factors raised to the appropriate powers. Let D(n) be the total number of its base b digits in all its prime factors and in all their exponents that are greater than 1. Then n is defined to be:
- a wasteful (or extravagant) number if l(n) < D(n); or
- an equidigital number if l(n) = D(n); or
- a frugal (or economical) number if l(n) > D(n) in base b. By convention, the number 1 is considered to be an equidigital number in any base even though it has no prime factors. For the avoidance of any doubt, the number 0 is not a positive integer (and arguably not a natural number either) and so is excluded from all 3 categories. An economical number is sometimes defined as being one for which l(n) >= D(n) though this usage won't be followed here.
In base 10, the number 30 has a prime factorization of 2 x 3 x 5. The total number of digits is 3 (all exponents being 1) which is more than the 2 digits 30 has. So 30 is wasteful in base 10. In base 10, the number 49 has a prime factorization of 7². The total number of digits, including those of the exponent, is 2 which is the same as the 2 digits 49 has. So 49 is equidigital in base 10. In base 10, the number 125 has a prime factorization of 5³. The total number of digits, including those of the exponent, is 2 which is less than the 3 digits 125 has. So 125 is frugal in base 10. In base 2, the number 100000 (32 decimal) has a prime factorization of 10^101 (2^5 decimal). The total number of binary digits, including those of the exponent, is 5 which is less than the 6 binary digits 100000 has. So 32 is frugal in base 2 (but equidigital in base 10).
Compute and show here the first 50 and the 10,000th number in base 10 for each of the three categories of number defined above. Also compute and show how many numbers less than 1,000,000 fall into each of the three categories.
Do the same for base 11, but show the results in base 10.
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Wasteful, equidigital and frugal numbers step by step in the C++ programming language
This C++ program explores the concept of wasteful, equidigital, and frugal numbers in various bases. Here's a detailed explanation of the code:
-
Enumeration and Data Structures:
- The code defines an enumeration
Category
with valuesWASTEFUL
,EQUIDIGITAL
, andFRUGAL
. - It also defines a
std::vector<Category>
calledcategories
to hold these values.
- The code defines an enumeration
-
Struct and Variables:
- A
Count
struct is defined with twouint32_t
members:lower_count
andupper_count
. - Several global variables are declared to store data:
factors
: A vector of unordered maps that represent prime factorizations of numbers up to a specific limit.tiny_limit
: A constant representing the number of first wasteful, equidigital, and frugal numbers to display (currently set to 50).lower_limit
: A constant representing the threshold for printing the nth number in each category (currently set to 10,000).upper_limit
: A constant representing the limit up to which the program counts numbers (currently set to 1,000,000).
- A
-
Helper Functions:
to_string(Category& category)
: Converts aCategory
value to a string representation.digit_count(uint32_t number, const uint32_t& base)
: Calculates the number of digits innumber
when written inbase
.factor_count(const uint32_t& number, const uint32_t& base)
: Calculates the total number of digits in the prime factorization ofnumber
when written inbase
.
-
category(const uint32_t& number, const uint32_t& base)
:- This function determines the category of a number
number
based on its digit count (digit
) and factor count (factor
) when written inbase
. - It returns
WASTEFUL
ifdigit
is less thanfactor
,FRUGAL
ifdigit
is greater thanfactor
, andEQUIDIGITAL
if they are equal.
- This function determines the category of a number
-
create_factors(const uint32_t& limit)
:- Calculates prime factorizations for numbers from 1 to
limit
- 1. - It initializes the
factors
vector and populates it with factorizations for each number.
- Calculates prime factorizations for numbers from 1 to
-
main()
Function:-
Initializes
factors
for numbers up to 2,700,000. -
Loops over two bases: 10 and 11.
-
For each base, it initializes
counts
andlists
maps to track the counts and lists of wasteful, equidigital, and frugal numbers. -
It iterates through numbers starting from 1 until the lower count for any category reaches
lower_limit
. -
For each
number
, it calculates its category and updates counts and lists accordingly. -
It prints the first
tiny_limit
numbers in each category, the nth number in each category (where n =lower_limit
), and the breakdown of numbers belowupper_limit
into wasteful, equidigital, and frugal categories.
-
Source code in the cpp programming language
#include <algorithm>
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
enum Category { WASTEFUL, EQUIDIGITAL, FRUGAL };
const std::vector<Category> categories = { Category::WASTEFUL, Category::EQUIDIGITAL, Category::FRUGAL };
struct Count {
uint32_t lower_count;
uint32_t upper_count;
};
std::vector<std::unordered_map<uint32_t,uint32_t>> factors;
std::string to_string(const Category& category) {
std::string result;
switch ( category ) {
case Category::WASTEFUL : result = "wasteful"; break;
case Category::EQUIDIGITAL : result = "equidigital"; break;
case Category::FRUGAL : result = "frugal"; break;
}
return result;
}
/**
* Return the number of digits in the given number written in the given base
*/
uint32_t digit_count(uint32_t number, const uint32_t& base) {
uint32_t result = 0;
while ( number != 0 ) {
result++;
number /= base;
}
return result;
}
/**
* Return the total number of digits used in the prime factorisation
* of the given number written in the given base
*/
uint32_t factor_count(const uint32_t& number, const uint32_t& base) {
uint32_t result = 0;
for ( const auto& [key, value] : factors[number] ) {
result += digit_count(key, base);
if ( value > 1 ) {
result += digit_count(value, base);
}
}
return result;
}
/**
* Return the category of the given number written in the given base
*/
Category category(const uint32_t& number, const uint32_t& base) {
const uint32_t digit = digit_count(number, base);
const uint32_t factor = factor_count(number, base);
return ( digit < factor ) ? Category::WASTEFUL :
( digit > factor ) ? Category::FRUGAL : Category::EQUIDIGITAL;
}
/**
* Factorise the numbers from 1 (inclusive) to limit (exclusive)
*/
void create_factors(const uint32_t& limit) {
factors.assign(limit, std::unordered_map<uint32_t, uint32_t>());
factors[1].emplace(1, 1);
for ( uint32_t n = 1; n < limit; ++n ) {
if ( factors[n].empty() ) {
uint64_t n_copy = n;
while ( n_copy < limit ) {
for ( uint64_t i = n_copy; i < limit; i += n_copy ) {
if ( factors[i].find(n) == factors[i].end() ) {
factors[i].emplace(n, 1);
} else {
factors[i][n]++;
}
}
n_copy *= n;
}
}
}
}
int main() {
create_factors(2'700'000);
const uint32_t tiny_limit = 50;
const uint32_t lower_limit = 10'000;
const uint32_t upper_limit = 1'000'000;
for ( uint32_t base : { 10, 11 } ) {
std::unordered_map<Category, Count> counts = { { Category::WASTEFUL, Count(0, 0) },
{ Category::EQUIDIGITAL, Count(0, 0) }, { Category::FRUGAL, Count(0,0) } };
std::unordered_map<Category, std::vector<uint32_t>> lists = { { Category::WASTEFUL, std::vector<uint32_t>() },
{ Category::EQUIDIGITAL, std::vector<uint32_t>() }, { Category::FRUGAL, std::vector<uint32_t>() } };
uint32_t number = 1;
std::cout << "FOR BASE " << base << ":" << std::endl << std::endl;
while ( std::any_of(counts.begin(), counts.end(),
[](const std::pair<Category, Count>& pair) { return pair.second.lower_count < lower_limit; }) ) {
Category cat = category(number, base);
if ( counts[cat].lower_count < tiny_limit || counts[cat].lower_count == lower_limit - 1 ) {
lists[cat].emplace_back(number);
}
counts[cat].lower_count++;
if ( number < upper_limit ) {
counts[cat].upper_count++;
}
number++;
}
for ( const Category& category : categories ) {
std::cout << "First " << tiny_limit << " " + to_string(category) << " numbers:" << std::endl;
for ( uint32_t i = 0; i < tiny_limit; ++i ) {
std::cout << std::setw(4) << lists[category][i] << ( i % 10 == 9 ? "\n" : " " );
}
std::cout << std::endl;
std::cout << lower_limit << "th " << to_string(category) << " number: "
<< lists[category][tiny_limit] << std::endl << std::endl;
}
std::cout << "For natural numbers less than " << upper_limit << ", the breakdown is as follows:" << std::endl;
std::cout << " Wasteful numbers : " << counts[Category::WASTEFUL].upper_count << std::endl;
std::cout << " Equidigital numbers : " << counts[Category::EQUIDIGITAL].upper_count << std::endl;
std::cout << " Frugal numbers : " << counts[Category::FRUGAL].upper_count << std::endl << std::endl;
}
}
You may also check:How to resolve the algorithm Averages/Mode step by step in the Euphoria programming language
You may also check:How to resolve the algorithm Colour pinstripe/Display step by step in the Phix programming language
You may also check:How to resolve the algorithm Draw a sphere step by step in the Phix programming language
You may also check:How to resolve the algorithm Create a file step by step in the Nanoquery programming language
You may also check:How to resolve the algorithm Nonoblock step by step in the Perl programming language