Wasteful, equidigital and frugal numbers: Difference between revisions

m
→‎{{header|Wren}}: Changed to Wren S/H
(→‎{{header|J}}: include base 11)
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(20 intermediate revisions by 11 users not shown)
Line 1:
{{draft task}}
;Definitions
Let '''n''' be a positive integer and '''l(n)''' be the number of its digits in base '''b'''.
Line 16:
 
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 [[wp:Natural_number|''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.
Line 47 ⟶ 49:
* [[oeis: A046759|OEIS: A046759 - Economical numbers]]
<br><br>
=={{header|C++}}==
<syntaxhighlight lang="c++">
#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;
}
}
</syntaxhighlight>
{{ out }}
<pre>
FOR BASE 10:
 
First 50 wasteful numbers:
4 6 8 9 12 18 20 22 24 26
28 30 33 34 36 38 39 40 42 44
45 46 48 50 51 52 54 55 56 57
58 60 62 63 65 66 68 69 70 72
74 75 76 77 78 80 82 84 85 86
 
10000th wasteful number: 14346
 
First 50 equidigital numbers:
1 2 3 5 7 10 11 13 14 15
16 17 19 21 23 25 27 29 31 32
35 37 41 43 47 49 53 59 61 64
67 71 73 79 81 83 89 97 101 103
105 106 107 109 111 112 113 115 118 119
 
10000th equidigital number: 33769
 
First 50 frugal numbers:
125 128 243 256 343 512 625 729 1024 1029
1215 1250 1280 1331 1369 1458 1536 1681 1701 1715
1792 1849 1875 2048 2187 2197 2209 2401 2560 2809
3125 3481 3584 3645 3721 4096 4374 4375 4489 4802
4913 5041 5103 5329 6241 6250 6561 6859 6889 7203
 
10000th frugal number: 1953125
 
For natural numbers less than 1000000, the breakdown is as follows:
Wasteful numbers : 831231
Equidigital numbers : 165645
Frugal numbers : 3123
 
FOR BASE 11:
 
First 50 wasteful numbers:
4 6 8 9 10 12 18 20 22 24
26 28 30 33 34 36 38 39 40 42
44 45 46 48 50 51 52 54 55 56
57 58 60 62 63 65 66 68 69 70
72 74 75 76 77 78 80 82 84 85
 
10000th wasteful number: 12890
 
First 50 equidigital numbers:
1 2 3 5 7 11 13 14 15 16
17 19 21 23 25 27 29 31 32 35
37 41 43 47 49 53 59 61 64 67
71 73 79 81 83 89 97 101 103 107
109 113 121 122 123 127 129 131 133 134
 
10000th equidigital number: 33203
 
First 50 frugal numbers:
125 128 243 256 343 512 625 729 1024 1331
1369 1458 1536 1681 1701 1715 1792 1849 1875 2048
2187 2197 2209 2401 2560 2809 3072 3125 3481 3584
3645 3721 4096 4374 4375 4489 4802 4913 5041 5103
5120 5329 6241 6250 6561 6859 6889 7168 7203 7921
 
10000th frugal number: 2659171
 
For natural numbers less than 1000000, the breakdown is as follows:
Wasteful numbers : 795861
Equidigital numbers : 200710
Frugal numbers : 3428
</pre>
 
=={{header|F_Sharp|F#}}==
<syntaxhighlight lang="fsharp">
// Frugal, equidigital, and wasteful numbers. Nigel Galloway: July 26th., 2022
let rec fG n g=match g/10L with 0L->n+1 |g->fG(n+1) g
let fN(g:int64)=Open.Numeric.Primes.Extensions.PrimeExtensions.PrimeFactors g|>Seq.skip 1|>Seq.countBy id|>Seq.sumBy(fun(n,g)->fG 0 n + if g<2 then 0 else fG 0 g)
let Frugal,Equidigital,Wasteful=let FEW n=Seq.initInfinite((+)2)|>Seq.filter(fun g->n(fG 0 g)(fN g)) in (("Frugal",FEW(>)),("Equidigital",seq{yield 1; yield! FEW(=)}),("Wasteful",FEW(<)))
[Frugal;Equidigital;Wasteful]|>List.iter(fun(n,g)->printf $"%s{n}: 10 thousandth is %d{Seq.item 9999 g}; There are %d{Seq.length (g|>Seq.takeWhile((>)1000000))} < 1 million\n First 50: "; g|>Seq.take 50|>Seq.iter(printf "%d "); printfn "")
</syntaxhighlight>
{{out}}
<pre>
Frugal: 10 thousandth is 1953125; There are 3123 < 1 million
First 50: 125 128 243 256 343 512 625 729 1024 1029 1215 1250 1280 1331 1369 1458 1536 1681 1701 1715 1792 1849 1875 2048 2187 2197 2209 2401 2560 2809 3125 3481 3584 3645 3721 4096 4374 4375 4489 4802 4913 5041 5103 5329 6241 6250 6561 6859 6889 7203
Equidigital: 10 thousandth is 33769; There are 165645 < 1 million
First 50: 1 2 3 5 7 10 11 13 14 15 16 17 19 21 23 25 27 29 31 32 35 37 41 43 47 49 53 59 61 64 67 71 73 79 81 83 89 97 101 103 105 106 107 109 111 112 113 115 118 119
Wasteful: 10 thousandth is 14346; There are 831231 < 1 million
First 50: 4 6 8 9 12 18 20 22 24 26 28 30 33 34 36 38 39 40 42 44 45 46 48 50 51 52 54 55 56 57 58 60 62 63 65 66 68 69 70 72 74 75 76 77 78 80 82 84 85 86
</pre>
 
=={{header|J}}==
 
Brute force implementation:<langsyntaxhighlight Jlang="j">I=: #@(#.inv)"0
D=: [ +/@:I __ (#~-.&1<])@,@q: ]
typ=: ~:&1@] * *@(I-D)"0 NB. _1: wasteful, 0: equidigital, 1: frugal</langsyntaxhighlight>
 
Task examples (base 10):<langsyntaxhighlight Jlang="j"> b10=: 10 typ(9999&{, 50&{.)1+iI.3e6_1=b10 NB. wasteful
14346 4 6 8 9 12 18 20 22 24 26 28 30 33 34 36 38 39 40 42 44 45 46 48 50 51 52 54 55 56 57 58 60 62 63 65 66 68 69 70 72 74 75 76 77 78 80 82 84 85 86
(9999 1e4&{, 50&{.)1+I._1=b10 NB. wasteful
(9999&{, 50&{.)1+I. 0=b10 NB. equidigital
14346 14348 4 6 8 9 12 18 20 22 24 26 28 30 33 34 36 38 39 40 42 44 45 46 48 50 51 52 54 55 56 57 58 60 62 63 65 66 68 69 70 72 74 75 76 77 78 80 82 84 85 86
33769 1 2 3 5 7 10 11 13 14 15 16 17 19 21 23 25 27 29 31 32 35 37 41 43 47 49 53 59 61 64 67 71 73 79 81 83 89 97 101 103 105 106 107 109 111 112 113 115 118 119
(9999 1e4&{, 50&{.)1+I. 0=b10 NB. equidigital
(9999&{, 50&{.)1+I. 1=b10 NB. frugal
33773 33777 2 3 5 7 10 11 13 14 15 16 17 19 21 23 25 27 29 31 32 35 37 41 43 47 49 53 59 61 64 67 71 73 79 81 83 89 97 101 103 105 106 107 109 111 112 113 115 118 119 121
1953125 125 128 243 256 343 512 625 729 1024 1029 1215 1250 1280 1331 1369 1458 1536 1681 1701 1715 1792 1849 1875 2048 2187 2197 2209 2401 2560 2809 3125 3481 3584 3645 3721 4096 4374 4375 4489 4802 4913 5041 5103 5329 6241 6250 6561 6859 6889 7203
(9999 1e4&{, 50&{.)1+I. 1=b10 NB. frugal
1953031 1953125 1 125 128 243 256 343 512 625 729 1024 1029 1215 1250 1280 1331 1369 1458 1536 1681 1701 1715 1792 1849 1875 2048 2187 2197 2209 2401 2560 2809 3125 3481 3584 3645 3721 4096 4374 4375 4489 4802 4913 5041 5103 5329 6241 6250 6561 6859 6889
+/1e6>1+I._1=b10 NB. wasteful
831231
+/1e6>1+I. 0=b10 NB. equidigital
165645
165644
+/1e6>1+I. 1=b10 NB. frugal
3123</syntaxhighlight>
3124</lang>
 
It was not clear to me whether the 10000th was supposed to be the real 10000th (index 9999 in J) or the number after that. So.. here I show both.
 
Task examples (base 11):<langsyntaxhighlight Jlang="j"> b11=: 11 typ(9999&{, 50&{.)1+iI.3e6_1=b11 NB. wasteful
12890 4 6 8 9 10 12 18 20 22 24 26 28 30 33 34 36 38 39 40 42 44 45 46 48 50 51 52 54 55 56 57 58 60 62 63 65 66 68 69 70 72 74 75 76 77 78 80 82 84 85
(9999 1e4&{, 50&{.)1+I._1=b11 NB. wasteful
(9999&{, 50&{.)1+I. 0=b11 NB. equidigital
12890 12891 4 6 8 9 10 12 18 20 22 24 26 28 30 33 34 36 38 39 40 42 44 45 46 48 50 51 52 54 55 56 57 58 60 62 63 65 66 68 69 70 72 74 75 76 77 78 80 82 84 85
33203 1 2 3 5 7 11 13 14 15 16 17 19 21 23 25 27 29 31 32 35 37 41 43 47 49 53 59 61 64 67 71 73 79 81 83 89 97 101 103 107 109 113 121 122 123 127 129 131 133 134
(9999 1e4&{, 50&{.)1+I. 0=b11 NB. equidigital
(9999&{, 50&{.)1+I. 1=b11 NB. frugal
33207 33211 2 3 5 7 11 13 14 15 16 17 19 21 23 25 27 29 31 32 35 37 41 43 47 49 53 59 61 64 67 71 73 79 81 83 89 97 101 103 107 109 113 121 122 123 127 129 131 133 134 135
2659171 125 128 243 256 343 512 625 729 1024 1331 1369 1458 1536 1681 1701 1715 1792 1849 1875 2048 2187 2197 2209 2401 2560 2809 3072 3125 3481 3584 3645 3721 4096 4374 4375 4489 4802 4913 5041 5103 5120 5329 6241 6250 6561 6859 6889 7168 7203 7921
(9999 1e4&{, 50&{.)1+I. 1=b11 NB. frugal
2658818 2659171 1 125 128 243 256 343 512 625 729 1024 1331 1369 1458 1536 1681 1701 1715 1792 1849 1875 2048 2187 2197 2209 2401 2560 2809 3072 3125 3481 3584 3645 3721 4096 4374 4375 4489 4802 4913 5041 5103 5120 5329 6241 6250 6561 6859 6889 7168 7203
+/1e6>1+I._1=b11 NB. wasteful
795861
+/1e6>1+I. 0=b11 NB. equidigital
200710
200709
+/1e6>1+I. 1=b11 NB. frugal
3428</syntaxhighlight>
3429</lang>
 
=={{header|Java}}==
<syntaxhighlight lang="java">
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;
 
}
</syntaxhighlight>
{{ out }}
<pre>
FOR BASE 10:
 
First 50 Wasteful numbers:
4 6 8 9 12 18 20 22 24 26
28 30 33 34 36 38 39 40 42 44
45 46 48 50 51 52 54 55 56 57
58 60 62 63 65 66 68 69 70 72
74 75 76 77 78 80 82 84 85 86
 
10000th Wasteful number: 14346
 
First 50 Equidigital numbers:
1 2 3 5 7 10 11 13 14 15
16 17 19 21 23 25 27 29 31 32
35 37 41 43 47 49 53 59 61 64
67 71 73 79 81 83 89 97 101 103
105 106 107 109 111 112 113 115 118 119
 
10000th Equidigital number: 33769
 
First 50 Frugal numbers:
125 128 243 256 343 512 625 729 1024 1029
1215 1250 1280 1331 1369 1458 1536 1681 1701 1715
1792 1849 1875 2048 2187 2197 2209 2401 2560 2809
3125 3481 3584 3645 3721 4096 4374 4375 4489 4802
4913 5041 5103 5329 6241 6250 6561 6859 6889 7203
 
10000th Frugal number: 1953125
 
For natural numbers less than 1000000, the breakdown is as follows:
Wasteful numbers : 831231
Equidigital numbers : 165645
Frugal numbers : 3123
 
FOR BASE 11:
 
First 50 Wasteful numbers:
4 6 8 9 10 12 18 20 22 24
26 28 30 33 34 36 38 39 40 42
44 45 46 48 50 51 52 54 55 56
57 58 60 62 63 65 66 68 69 70
72 74 75 76 77 78 80 82 84 85
 
10000th Wasteful number: 12890
 
First 50 Equidigital numbers:
1 2 3 5 7 11 13 14 15 16
17 19 21 23 25 27 29 31 32 35
37 41 43 47 49 53 59 61 64 67
71 73 79 81 83 89 97 101 103 107
109 113 121 122 123 127 129 131 133 134
 
10000th Equidigital number: 33203
 
First 50 Frugal numbers:
125 128 243 256 343 512 625 729 1024 1331
1369 1458 1536 1681 1701 1715 1792 1849 1875 2048
2187 2197 2209 2401 2560 2809 3072 3125 3481 3584
3645 3721 4096 4374 4375 4489 4802 4913 5041 5103
5120 5329 6241 6250 6561 6859 6889 7168 7203 7921
 
10000th Frugal number: 2659171
 
For natural numbers less than 1000000, the breakdown is as follows:
Wasteful numbers : 795861
Equidigital numbers : 200710
Frugal numbers : 3428
</pre>
 
=={{header|Julia}}==
<syntaxhighlight lang="julia">using Primes
 
"""
function wastefulness(n, base = 10)
calculate d1: the number of digits in base `base` required to write the factor expansion of
`n`, ie 12 -> 2^2 * 3^2 is 4 digits, 7 -> 7 is 1 digit, 20 -> 5 * 2^2 is 3 digits
 
calculate d2: the number of digits in base `base` to represent `n` itself
 
return -1 if frugal (d1 > d2), 0 if equidigital (d1 == d2), 1 if wasteful (d1 > d2)
"""
function wastefulness(n::Integer, base = 10)
@assert n > 0
return n == 1 ? 0 :
sign(sum(p -> ndigits(p[1], base=base) +
(p[2] == 1 ? 0 : ndigits(p[2], base=base)),
factor(n).pe) -
ndigits(n, base=base))
end
 
for b in [10, 11]
w50, e50, f50 = Int[], Int[], Int[]
w10k, e10k, f10k, wcount, ecount, fcount, wm, em, fm = 0, 0, 0, 0, 0, 0, 0, 0, 0
for n in 1:10_000_000
sgn = wastefulness(n, b)
if sgn < 0
fcount < 50 && push!(f50, n)
fcount += 1
fcount == 10000 &&(f10k = n)
n < 1_000_000 && (fm += 1)
elseif sgn == 0
ecount < 50 && push!(e50, n)
ecount += 1
ecount == 10000 && (e10k = n)
n < 1_000_000 && (em += 1)
else # sgn > 0
wcount < 50 && push!(w50, n)
wcount += 1
wcount == 10000 && (w10k = n)
n < 1_000_000 && (wm += 1)
end
if f10k > 0
println("FOR BASE $b:\n")
println("First 50 Wasteful numbers:")
foreach(p -> print(rpad(p[2], 5), p[1] % 10 == 0 ? "\n" : ""), pairs(w50))
println("\nFirst 50 Equidigital numbers:")
foreach(p -> print(rpad(p[2], 5), p[1] % 10 == 0 ? "\n" : ""), pairs(e50))
println("\nFirst 50 Frugal numbers:")
foreach(p -> print(rpad(p[2], 5), p[1] % 10 == 0 ? "\n" : ""), pairs(f50))
println("\n10,000th Wasteful number : $w10k")
println("10,000th Equidigital number : $e10k")
println("10,000th Frugal number : $f10k")
println("\nFor natural numbers < 1 million, the breakdown is as follows:")
println(" Wasteful numbers : $wm")
println(" Equidigital numbers : $em")
println(" Frugal numbers : $fm\n\n")
break
end
end
end
</syntaxhighlight>
Output is the same as Wren example.
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">ClearAll[FactorIntegerDigits, ID, Stats]
FactorIntegerDigits[n_] := Module[{},
fi = FactorInteger[n];
fi[[All, 1]] //= Map[IntegerLength];
fi[[All, 2]] //= Map[If[# == 1, 0, IntegerLength[#]] &];
Total[Flatten[fi]]
]
Stats[l_List] := Module[{},
Print["10000: ", l[[10^4]]];
Print["First 50: ", l[[;; 50]]];
Print["Below 10^6: ", Length[Select[l, LessThan[10^6]]]];
]
ID[n_] := {IntegerLength[n], FactorIntegerDigits[n]}
bla = {#, ID[#]} & /@ Range[2000000];
wasteful = Select[bla, #[[2, 1]] < #[[2, 2]] &][[All, 1]];
equidigital = Select[bla, #[[2, 1]] == #[[2, 2]] &][[All, 1]];
frugal = Select[bla, #[[2, 1]] > #[[2, 2]] &][[All, 1]];
Print["Wasteful"]
Stats[wasteful]
 
Print["Equidigital"]
Stats[equidigital]
 
Print["Frugal"]
Stats[frugal]</syntaxhighlight>
{{out}}
<pre>Wasteful
10000: 14346
First 50: {4,6,8,9,12,18,20,22,24,26,28,30,33,34,36,38,39,40,42,44,45,46,48,50,51,52,54,55,56,57,58,60,62,63,65,66,68,69,70,72,74,75,76,77,78,80,82,84,85,86}
Below 10^6: 831231
 
Equidigital
10000: 33769
First 50: {1,2,3,5,7,10,11,13,14,15,16,17,19,21,23,25,27,29,31,32,35,37,41,43,47,49,53,59,61,64,67,71,73,79,81,83,89,97,101,103,105,106,107,109,111,112,113,115,118,119}
Below 10^6: 165645
 
Frugal
10000: 1953125
First 50: {125,128,243,256,343,512,625,729,1024,1029,1215,1250,1280,1331,1369,1458,1536,1681,1701,1715,1792,1849,1875,2048,2187,2197,2209,2401,2560,2809,3125,3481,3584,3645,3721,4096,4374,4375,4489,4802,4913,5041,5103,5329,6241,6250,6561,6859,6889,7203}
Below 10^6: 3123</pre>
 
=={{header|Nim}}==
<syntaxhighlight lang="Nim">import std/[sequtils, strformat, tables]
 
# Sieve to find the decomposition in prime factors.
const N = 2_700_000
var factors: array[1..N, CountTable[int]]
factors[1].inc(1)
 
for n in 2..N:
if factors[n].len == 0: # "n" is prime.
var m = n # Powers of "n"
while m <= N:
for k in countup(m, N, m):
factors[k].inc(n)
m *= n
 
type Category {.pure.} = enum Wasteful = "wasteful"
Equidigital = "equidigital"
Frugal = "frugal"
 
func digitCount(n, base: Positive): int =
## Return the number of digits of the representation of "n" in given base.
var n = n.Natural
while n != 0:
inc result
n = n div base
 
proc d(n, base: Positive): int =
## Compute "D(n)" in given base.
for (p, e) in factors[n].pairs:
inc result, p.digitCount(base)
if e > 1: inc result, e.digitCount(base)
 
proc category(n, base: Positive): Category =
## Return the category of "n" in given base.
let i = n.digitCount(base)
let d = d(n, base)
result = if i < d: Wasteful elif i > d: Frugal else: Equidigital
 
 
const N1 = 50
const N2 = 10_000
const Limit = 1_000_000
 
for base in [10, 11]:
 
var counts1: array[Category, int] # Total counts.
var counts2: array[Category, int] # Counts for n < Limit.
var numbers1: array[Category, array[1..N1, int]] # First N1 numbers in each category.
var numbers2: array[Category, int] # Number at position N2 in each category.
 
echo &"For base {base}."
echo "===========\n"
var n = 1
while true:
if n == Limit:
counts2 = counts1
let cat = n.category(base)
inc counts1[cat]
let c = counts1[cat]
if c <= N1:
numbers1[cat][c] = n
elif c == N2:
numbers2[cat] = n
inc n
if allIt(counts1, it >= N2) and n >= Limit: break
 
for cat in Category.low..Category.high:
echo &"First {N1} {cat} numbers:"
for i, n in numbers1[cat]:
stdout.write &"{n:4}"
stdout.write if i mod 10 == 0: '\n' else: ' '
echo &"\nThe {N2}th {cat} number is {numbers2[cat]}.\n"
 
echo &"Among numbers less than {Limit}, there are:"
for cat in Category.low..Category.high:
echo &"- {counts2[cat]} {cat} numbers."
echo '\n'
</syntaxhighlight>
 
{{out}}
<pre>For base 10.
===========
 
First 50 wasteful numbers:
4 6 8 9 12 18 20 22 24 26
28 30 33 34 36 38 39 40 42 44
45 46 48 50 51 52 54 55 56 57
58 60 62 63 65 66 68 69 70 72
74 75 76 77 78 80 82 84 85 86
 
The 10000th wasteful number is 14346.
 
First 50 equidigital numbers:
1 2 3 5 7 10 11 13 14 15
16 17 19 21 23 25 27 29 31 32
35 37 41 43 47 49 53 59 61 64
67 71 73 79 81 83 89 97 101 103
105 106 107 109 111 112 113 115 118 119
 
The 10000th equidigital number is 33769.
 
First 50 frugal numbers:
125 128 243 256 343 512 625 729 1024 1029
1215 1250 1280 1331 1369 1458 1536 1681 1701 1715
1792 1849 1875 2048 2187 2197 2209 2401 2560 2809
3125 3481 3584 3645 3721 4096 4374 4375 4489 4802
4913 5041 5103 5329 6241 6250 6561 6859 6889 7203
 
The 10000th frugal number is 1953125.
 
Among numbers less than 1000000, there are:
- 831231 wasteful numbers.
- 165645 equidigital numbers.
- 3123 frugal numbers.
 
 
For base 11.
===========
 
First 50 wasteful numbers:
4 6 8 9 10 12 18 20 22 24
26 28 30 33 34 36 38 39 40 42
44 45 46 48 50 51 52 54 55 56
57 58 60 62 63 65 66 68 69 70
72 74 75 76 77 78 80 82 84 85
 
The 10000th wasteful number is 12890.
 
First 50 equidigital numbers:
1 2 3 5 7 11 13 14 15 16
17 19 21 23 25 27 29 31 32 35
37 41 43 47 49 53 59 61 64 67
71 73 79 81 83 89 97 101 103 107
109 113 121 122 123 127 129 131 133 134
 
The 10000th equidigital number is 33203.
 
First 50 frugal numbers:
125 128 243 256 343 512 625 729 1024 1331
1369 1458 1536 1681 1701 1715 1792 1849 1875 2048
2187 2197 2209 2401 2560 2809 3072 3125 3481 3584
3645 3721 4096 4374 4375 4489 4802 4913 5041 5103
5120 5329 6241 6250 6561 6859 6889 7168 7203 7921
 
The 10000th frugal number is 2659171.
 
Among numbers less than 1000000, there are:
- 795861 wasteful numbers.
- 200710 equidigital numbers.
- 3428 frugal numbers.</pre>
 
=={{header|Perl}}==
{{libheader|ntheory}}
<syntaxhighlight lang="perl">use v5.36;
use experimental 'for_list';
use ntheory <factor todigitstring>;
use List::Util <sum max min pairmap>;
 
sub table ($c, @V) { my $t = $c * (my $w = 6); ( sprintf( ('%'.$w.'d')x@V, @V) ) =~ s/.{1,$t}\K/\n/gr }
 
sub bag (@v) { my %h; $h{$_}++ for @v; %h }
 
for my $base (10, 11) {
my(@F,@E,@W,$n,$totals);
do {
my %F = bag factor ++$n;
my $s = sum pairmap { length(todigitstring($a,$base)) + ($b > 1 ? length(todigitstring($b,$base)) : 0) } %F;
my $l = length todigitstring($n,$base);
if ($n == 1 or $l == $s) { push @E, $n }
elsif ( $l < $s) { push @W, $n }
else { push @F, $n }
} until 10000 < min scalar @F, scalar @E, scalar @W;
 
say "In base $base:";
for my ($type, $values) ('Wasteful', \@W, 'Equidigital', \@E, 'Frugal', \@F) {
say "\n$type numbers:";
say table 10, @$values[0..49];
say "10,000th: $$values[9999]";
$totals .= sprintf "%11s: %d\n", $type, scalar grep { $_ < 1_000_000 } @$values
}
say "\nOf the positive integers up to one million:\n$totals";
}</syntaxhighlight>
{{out}}
<pre style="height:110ex">In base 10:
 
Wasteful numbers:
4 6 8 9 12 18 20 22 24 26
28 30 33 34 36 38 39 40 42 44
45 46 48 50 51 52 54 55 56 57
58 60 62 63 65 66 68 69 70 72
74 75 76 77 78 80 82 84 85 86
 
10,000th: 14346
 
Equidigital numbers:
1 2 3 5 7 10 11 13 14 15
16 17 19 21 23 25 27 29 31 32
35 37 41 43 47 49 53 59 61 64
67 71 73 79 81 83 89 97 101 103
105 106 107 109 111 112 113 115 118 119
 
10,000th: 33769
 
Frugal numbers:
125 128 243 256 343 512 625 729 1024 1029
1215 1250 1280 1331 1369 1458 1536 1681 1701 1715
1792 1849 1875 2048 2187 2197 2209 2401 2560 2809
3125 3481 3584 3645 3721 4096 4374 4375 4489 4802
4913 5041 5103 5329 6241 6250 6561 6859 6889 7203
 
10,000th: 1953125
 
Of the positive integers up to one million:
Wasteful: 831231
Equidigital: 165645
Frugal: 3123
 
In base 11:
 
Wasteful numbers:
4 6 8 9 10 12 18 20 22 24
26 28 30 33 34 36 38 39 40 42
44 45 46 48 50 51 52 54 55 56
57 58 60 62 63 65 66 68 69 70
72 74 75 76 77 78 80 82 84 85
 
10,000th: 12890
 
Equidigital numbers:
1 2 3 5 7 11 13 14 15 16
17 19 21 23 25 27 29 31 32 35
37 41 43 47 49 53 59 61 64 67
71 73 79 81 83 89 97 101 103 107
109 113 121 122 123 127 129 131 133 134
 
10,000th: 33203
 
Frugal numbers:
125 128 243 256 343 512 625 729 1024 1331
1369 1458 1536 1681 1701 1715 1792 1849 1875 2048
2187 2197 2209 2401 2560 2809 3072 3125 3481 3584
3645 3721 4096 4374 4375 4489 4802 4913 5041 5103
5120 5329 6241 6250 6561 6859 6889 7168 7203 7921
 
10,000th: 2659171
 
Of the positive integers up to one million:
Wasteful: 795861
Equidigital: 200710
Frugal: 3428</pre>
 
=={{header|Phix}}==
{{trans|Wren}}
<!--<langsyntaxhighlight Phixlang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">analyze</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
Line 142 ⟶ 929:
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fmt</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">&</span><span style="color: #000000;">w3</span><span style="color: #0000FF;">&</span><span style="color: #000000;">w10k</span><span style="color: #0000FF;">&</span><span style="color: #000000;">c2</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</langsyntaxhighlight>-->
Output identical to Wren
 
=={{header|Raku}}==
<syntaxhighlight lang="raku" perl6line>use Prime::Factor;
use Lingua::EN::Numbers;
 
my %cache;
sub frugal ($n, $base = 10) { ($n > 1) && $n.base($base).chars > sum $n.&prime-factors.Bag.map: { .key.base($base).chars + (.value > 1 ?? .value.base($base).chars !! 0) } }
 
sub equidigital ($n, $base = 10) { ($n == 1) || $n.base($base).chars == sum $n.&prime-factors.Bag.map: { .key.base($base).chars + (.value > 1 ?? .value.base($base).chars !! 0) } }
sub wasteful factor-char-sum ($n, $base = 10) { $n.base($base).chars < sum $n.&prime-factors.Bag.map: { .key.base($base).chars + (.value > 1 ?? .value.base($base).chars !! 0) } }
 
sub economical ($n, $base = 10) { ($n > 1) && $n.base($base).chars > (%cache{$base}[$n] //= factor-char-sum $n, $base) }
sub equidigital ($n, $base = 10) { ($n == 1) || $n.base($base).chars == (%cache{$base}[$n] //= factor-char-sum $n, $base) }
sub extravagant ($n, $base = 10) { $n.base($base).chars < (%cache{$base}[$n] //= factor-char-sum $n, $base) }
 
 
for 10, 11 -> $base {
%cache{$base}[3e6] = Any; # preallocate to avoid concurrency issues
say "\nIn Base $base:";
for &wastefulextravagant, &equidigital, &frugaleconomical -> &sub {
say "\nFirst 50 {&sub.name} numbers:";
say (^∞).grep( {.&sub($base)} )[^50].batch(10)».&comma».fmt("%6s").join: "\n";
Line 163 ⟶ 955:
 
my $upto = 1e6.Int;
my atomicint ($Wastefulextravagant, $Equidigitalequidigital, $Frugaleconomical);
say "\nOf the positive integers up to {$upto.&cardinal} :";
(1..^$upto).race(:5000batch).map: { .&frugalextravagant($base) ?? ++⚛$Frugalextravagant !! .&equidigital($base) ?? ++⚛$Equidigitalequidigital !! ++⚛$Wastefuleconomical };
say " WastefulExtravagant: {comma $Wastefulextravagant}\nEquidigitaln Equidigital: {comma $Equidigitalequidigital}\n FrugalEconomical: {comma $Frugaleconomical}";
%cache{$base} = Empty;
}</lang>
}</syntaxhighlight>
{{out}}
<pre>In Base 10:
 
First 50 wastefulextravagant numbers:
4 6 8 9 12 18 20 22 24 26
28 30 33 34 36 38 39 40 42 44
Line 187 ⟶ 980:
10,000th: 33,769
 
First 50 frugaleconomical numbers:
125 128 243 256 343 512 625 729 1,024 1,029
1,215 1,250 1,280 1,331 1,369 1,458 1,536 1,681 1,701 1,715
Line 195 ⟶ 988:
10,000th: 1,953,125
 
Of the positive integers up to one million :
Wasteful Extravagant: 831,231
Equidigital: 165,645
FrugalEconomical: 3,123
 
In Base 11:
 
First 50 wastefulextravagant numbers:
4 6 8 9 10 12 18 20 22 24
26 28 30 33 34 36 38 39 40 42
Line 218 ⟶ 1,011:
10,000th: 33,203
 
First 50 frugaleconomical numbers:
125 128 243 256 343 512 625 729 1,024 1,331
1,369 1,458 1,536 1,681 1,701 1,715 1,792 1,849 1,875 2,048
Line 226 ⟶ 1,019:
10,000th: 2,659,171
 
Of the positive integers up to one million :
Wasteful Extravagant: 795,861
Equidigital: 200,710
FrugalEconomical: 3,428</pre>
 
=={{header|RPL}}==
{{works with|HP|49}}
≪ DUP SIZE SWAP
FACTORS 0
1 3 PICK SIZE '''FOR''' j
OVER j GET
'''IF''' DUP 1 == '''THEN''' DROP '''ELSE''' SIZE + '''END'''
'''NEXT'''
NIP - SIGN
≫ '<span style="color:blue">WEF?</span>' STO
≪ 1 → t j
≪ t {} {1} IFTE
'''WHILE''' DUP SIZE 50 < '''REPEAT'''
'''IF''' 'j' INCR <span style="color:blue">WEF?</span> t == '''THEN''' j + '''END'''
'''END'''
≫ ≫ '<span style="color:blue">TASK</span>' STO
 
-1 <span style="color:blue">TASK</span> 0 <span style="color:blue">TASK</span> 1 <span style="color:blue">TASK</span>
{{out}}
<pre>
3: {4 6 8 9 12 18 20 22 24 26 28 30 33 34 36 38 39 40 42 44 45 46 48 50 51 52 54 55 56 57 58 60 62 63 65 66 68 69 70 72 74 75 76 77 78 80 82 84 85 86}
2: {1 2 3 5 7 10 11 13 14 15 16 17 19 21 23 25 27 29 31 32 35 37 41 43 47 49 53 59 61 64 67 71 73 79 81 83 89 97 101 103 105 106 107 109 111 112 113 115 118 119}
1: { 125 128 243 256 343 512 625 729 1024 1029 1215 1250 1280 1331 1369 1458 1536 1681 1701 1715 1792 1849 1875 2048 2187 2197 2209 2401 2560 2809 3125 3481 3584 3645 3721 4096 4374 4375 4489 4802 4913 5041 5103 5329 6241 6250 6561 6859 6889 7203}
</pre>
 
=={{header|Ruby}}==
<syntaxhighlight lang="ruby">require 'prime'
 
[10,11].each do |base|
res = Hash.new{|h, k| h[k] = [] }
puts "\nBase: #{base}"
 
(1..).each do |n|
pd = n.prime_division
pd = pd.map{|pr| pr.pop if pr.last == 1; pr}
pd = [1] if n == 1
selector = n.digits(base).size <=> pd.flatten.sum{|m| m.digits(base).size} # -1,0,1
res[[:Equidigital, :Frugal, :Wasteful][selector]] << n
break if res.values.all?{|v| v.size >= 10000}
end
 
res.each do |k, v|
puts "#{k}:"
puts "10000th: #{v[9999]}; count: #{v.count{|n| n < 1_000_000}}"
p v.first(50)
end
end
</syntaxhighlight>
{{out}}
<pre>Base: 10
Equidigital:
10000st: 33769 count: 165645
[1, 2, 3, 5, 7, 10, 11, 13, 14, 15, 16, 17, 19, 21, 23, 25, 27, 29, 31, 32, 35, 37, 41, 43, 47, 49, 53, 59, 61, 64, 67, 71, 73, 79, 81, 83, 89, 97, 101, 103, 105, 106, 107, 109, 111, 112, 113, 115, 118, 119]
Wasteful:
10000st: 14346 count: 831231
[4, 6, 8, 9, 12, 18, 20, 22, 24, 26, 28, 30, 33, 34, 36, 38, 39, 40, 42, 44, 45, 46, 48, 50, 51, 52, 54, 55, 56, 57, 58, 60, 62, 63, 65, 66, 68, 69, 70, 72, 74, 75, 76, 77, 78, 80, 82, 84, 85, 86]
Frugal:
10000st: 1953125 count: 3123
[125, 128, 243, 256, 343, 512, 625, 729, 1024, 1029, 1215, 1250, 1280, 1331, 1369, 1458, 1536, 1681, 1701, 1715, 1792, 1849, 1875, 2048, 2187, 2197, 2209, 2401, 2560, 2809, 3125, 3481, 3584, 3645, 3721, 4096, 4374, 4375, 4489, 4802, 4913, 5041, 5103, 5329, 6241, 6250, 6561, 6859, 6889, 7203]
 
Base: 11
Equidigital:
10000st: 33203 count: 200710
[1, 2, 3, 5, 7, 11, 13, 14, 15, 16, 17, 19, 21, 23, 25, 27, 29, 31, 32, 35, 37, 41, 43, 47, 49, 53, 59, 61, 64, 67, 71, 73, 79, 81, 83, 89, 97, 101, 103, 107, 109, 113, 121, 122, 123, 127, 129, 131, 133, 134]
Wasteful:
10000st: 12890 count: 795861
[4, 6, 8, 9, 10, 12, 18, 20, 22, 24, 26, 28, 30, 33, 34, 36, 38, 39, 40, 42, 44, 45, 46, 48, 50, 51, 52, 54, 55, 56, 57, 58, 60, 62, 63, 65, 66, 68, 69, 70, 72, 74, 75, 76, 77, 78, 80, 82, 84, 85]
Frugal:
10000st: 2659171 count: 3428
[125, 128, 243, 256, 343, 512, 625, 729, 1024, 1331, 1369, 1458, 1536, 1681, 1701, 1715, 1792, 1849, 1875, 2048, 2187, 2197, 2209, 2401, 2560, 2809, 3072, 3125, 3481, 3584, 3645, 3721, 4096, 4374, 4375, 4489, 4802, 4913, 5041, 5103, 5120, 5329, 6241, 6250, 6561, 6859, 6889, 7168, 7203, 7921]
</pre>
 
=={{header|Wren}}==
Line 235 ⟶ 1,101:
{{libheader|Wren-seq}}
{{libheader|Wren-fmt}}
<langsyntaxhighlight ecmascriptlang="wren">import "./math" for Int
import "./seq" for Lst
import "./fmt" for Fmt
Line 297 ⟶ 1,163:
Fmt.print(" Frugal numbers : $6d", fc2)
System.print()
}</langsyntaxhighlight>
 
{{out}}
9,476

edits