How to resolve the algorithm Wasteful, equidigital and frugal numbers step by step in the Java programming language
How to resolve the algorithm Wasteful, equidigital and frugal numbers step by step in the Java 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 Java programming language
Java Program to Classify Numbers as Wasteful, Equidigital, or Frugal
This Java program classifies natural numbers into three categories based on the relationship between the number of digits in their base-10 representation and the number of digits in their prime factorization.
Enum Category:
- Wasteful: More digits in the base-10 representation than in the prime factorization.
- Equidigital: Equal number of digits in both the base-10 representation and the prime factorization.
- Frugal: Fewer digits in the base-10 representation than in the prime factorization.
Main Method:
- Initialization:
tinyLimit
: Set to 50, used to print the first 50 numbers of each category.lowerLimit
: Set to 10,000, used to find the first number in the range 10,000 to 1,000,000 for each category.upperLimit
: Set to 1,000,000, used to count the number of numbers in each category within this range.
- Two base values, 10 and 11, are considered.
- For each base:
- Initialize maps and lists to track counts and number lists for each category.
- Iterate through natural numbers, starting from 1.
- Determine the category of each number and increment the corresponding count.
- If the lower count for a category reaches
tinyLimit
or is close tolowerLimit
, add the number to the corresponding list. - Print the first
tinyLimit
numbers of each category. - Report the count of each category for numbers less than
upperLimit
.
Supporting Methods:
- createFactors: Pre-calculates the prime factorizations of numbers up to
limit
and stores them in a list of maps. - digitCount: Calculates the number of digits of an integer in a given base.
- factorCount: Calculates the total number of digits used in the prime factor factorization of an integer in a given base.
- category: Determines the category of an integer in a given base based on the digit count and factor count.
Output:
The program prints for each base the following information:
- The first 50 numbers of each category.
- The 10,000th number of each category.
- The count of each category for numbers less than 1,000,000.
Source code in the java programming language
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public final class WastefulEquidigitalAndFrugalNumbers {
public static void main(String[] args) {
createFactors(2_700_000);
final int tinyLimit = 50;
final int lowerLimit = 10_000;
final int upperLimit = 1_000_000;
for ( int base : List.of( 10, 11 ) ) {
Map<Category, Count> counts = Arrays.stream(Category.values())
.collect(Collectors.toMap( Function.identity(), value -> new Count(0, 0) ));
Map<Category, List<Integer>> lists = Arrays.stream(Category.values())
.collect(Collectors.toMap( Function.identity(), value -> new ArrayList<Integer>() ));
int number = 1;
System.out.println("FOR BASE " + base + ":" + System.lineSeparator());
while ( counts.values().stream().anyMatch( count -> count.lowerCount < lowerLimit ) ) {
Category category = category(number, base);
Count count = counts.get(category);
if ( count.lowerCount < tinyLimit || count.lowerCount == lowerLimit - 1 ) {
lists.get(category).add(number);
}
count.lowerCount += 1;
if ( number < upperLimit ) {
count.upperCount += 1;
}
number += 1;
}
for ( Category category : Category.values() ) {
System.out.println("First " + tinyLimit + " " + category + " numbers:");
for ( int i = 0; i < tinyLimit; i++ ) {
System.out.print(String.format("%4d%s", lists.get(category).get(i), (i % 10 == 9 ? "\n" : " ")));
}
System.out.println();
System.out.println(lowerLimit + "th " + category + " number: " + lists.get(category).get(tinyLimit));
System.out.println();
}
System.out.println("For natural numbers less than " + upperLimit + ", the breakdown is as follows:");
System.out.println(" Wasteful numbers : " + counts.get(Category.Wasteful).upperCount);
System.out.println(" Equidigital numbers : " + counts.get(Category.Equidigital).upperCount);
System.out.println(" Frugal numbers : " + counts.get(Category.Frugal).upperCount);
System.out.println();
}
}
private enum Category { Wasteful, Equidigital, Frugal }
/**
* Factorise the numbers from 1 (inclusive) to limit (exclusive)
*/
private static void createFactors(int limit) {
factors = IntStream.rangeClosed(0, limit).boxed()
.map( integer -> new HashMap<Integer, Integer>() ).collect(Collectors.toList());
factors.get(1).put(1, 1);
for ( int n = 1; n < limit; n++ ) {
if ( factors.get(n).isEmpty() ) {
long nCopy = n;
while ( nCopy < limit ) {
for ( long i = nCopy; i < limit; i += nCopy ) {
factors.get((int) i).merge(n, 1, Integer::sum);
}
nCopy *= n;
}
}
}
}
/**
* Return the number of digits in the given number written in the given base
*/
private static int digitCount(int number, int base) {
int result = 0;
while ( number != 0 ) {
result += 1;
number /= base;
}
return result;
}
/**
* Return the total number of digits used in the prime factorisation
* of the given number written in the given base
*/
private static int factorCount(int number, int base) {
int result = 0;
for ( Map.Entry<Integer, Integer> entry : factors.get(number).entrySet() ) {
result += digitCount(entry.getKey(), base);
if ( entry.getValue() > 1 ) {
result += digitCount(entry.getValue(), base);
}
}
return result;
}
/**
* Return the category of the given number written in the given base
*/
private static Category category(int number, int base) {
final int digitCount = digitCount(number, base);
final int factorCount = factorCount(number, base);
return ( digitCount < factorCount ) ? Category.Wasteful :
( digitCount > factorCount ) ? Category.Frugal : Category.Equidigital;
}
private static class Count {
public Count(int aLowerCount, int aUpperCount) {
lowerCount = aLowerCount; upperCount = aUpperCount;
}
private int lowerCount, upperCount;
}
private static List<Map<Integer, Integer>> factors;
}
You may also check:How to resolve the algorithm Exponentiation operator step by step in the Erlang programming language
You may also check:How to resolve the algorithm Date manipulation step by step in the PicoLisp programming language
You may also check:How to resolve the algorithm One-dimensional cellular automata step by step in the Red programming language
You may also check:How to resolve the algorithm Knuth's algorithm S step by step in the PHP programming language
You may also check:How to resolve the algorithm Permutations step by step in the AutoHotkey programming language