Own digits power sum
For the purposes of this task, an own digits power sum is a decimal integer which is N digits long and is equal to the sum of its individual digits raised to the power N.
You are encouraged to solve this task according to the task description, using any language you may know.
- Description
- Example
The three digit integer 153 is an own digits power sum because 1³ + 5³ + 3³ = 1 + 125 + 27 = 153.
- Task
Find and show here all own digits power sums for N = 3 to N = 8 inclusive.
Optionally, do the same for N = 9 which may take a while for interpreted languages.
- Related
11l
V MAX_BASE = 10
V POWER_DIGIT = (0 .< MAX_BASE).map(_ -> (0 .< :MAX_BASE).map(_ -> 1))
V USED_DIGITS = (0 .< MAX_BASE).map(_ -> 0)
[Int] NUMBERS
F calc_num(=depth, &used)
‘ calculate the number at a given recurse depth ’
V result = Int64(0)
I depth < 3
R
L(i) 1 .< :MAX_BASE
I used[i] > 0
result += Int64(used[i]) * :POWER_DIGIT[depth][i]
I result != 0
V (num, rnum) = (result, Int64(1))
L rnum != 0
rnum = num I/ :MAX_BASE
used[Int(num - rnum * :MAX_BASE)]--
num = rnum
depth--
I depth == 0
V i = 1
L i < :MAX_BASE & used[i] == 0
i++
I i >= :MAX_BASE
:NUMBERS.append(Int(result))
F next_digit(=dgt, depth) -> Void
‘ get next digit at the given depth ’
I depth < :MAX_BASE - 1
L(i) dgt .< :MAX_BASE
:USED_DIGITS[dgt]++
next_digit(i, depth + 1)
:USED_DIGITS[dgt]--
I dgt == 0
dgt = 1
L(i) dgt .< :MAX_BASE
:USED_DIGITS[i]++
calc_num(depth, ©(:USED_DIGITS))
:USED_DIGITS[i]--
L(j) 1 .< MAX_BASE
L(k) 0 .< MAX_BASE
POWER_DIGIT[j][k] = POWER_DIGIT[j - 1][k] * k
next_digit(0, 0)
print(NUMBERS)
NUMBERS = Array(Set(NUMBERS))
NUMBERS.sort()
print(‘Own digits power sums for N = 3 to 9 inclusive:’)
L(n) NUMBERS
print(n)
- Output:
[9800817, 9800817, 24678050, 24678050, 146511208, 146511208, 146511208, 4210818, 24678051, 24678051, 8208, 370, 93084, 93084, 370, 370, 370, 370, 407, 407, 407, 407, 912985153, 1741725, 9926315, 153, 371, 1634, 1634, 1634, 153, 371, 153, 371, 371, 371, 92727, 92727, 92727, 472335975, 472335975, 472335975, 534494836, 534494836, 548834, 88593477, 88593477, 54748, 54748, 9474, 9474, 9474] Own digits power sums for N = 3 to 9 inclusive: 153 370 371 407 1634 8208 9474 54748 92727 93084 548834 1741725 4210818 9800817 9926315 24678050 24678051 88593477 146511208 472335975 534494836 912985153
ALGOL 68
Non-recursive, generates the possible combinations ands the own digits power sums in reverse order, without duplication.
Uses ideas from various solutions on this page, particularly the observation that the own digits power sum is independent of the order of the digits. Uses the minimum possible highest digit for the number of digits (width) and maximum number of zeros for the width to avoid some combinations. This trys 73 359 combinations.
BEGIN
# counts of used digits, check is a copy used to check the number is an own digit power sum #
[ 0 : 9 ]INT used, check; FOR i FROM 0 TO 9 DO check[ i ] := 0 OD;
[ 1 : 9, 1 : 9 ]LONG INT power; # table of digit powers #
FOR i TO 9 DO power[ 1, i ] := i OD;
FOR j FROM 2 TO 9 DO
FOR i TO 9 DO power[ j, i ] := power[ j - 1, i ] * i OD
OD;
# find the lowest possible first digit for each digit combination #
# this is the roughly the low3est n where P*n^p > 10^p #
[ 1 : 9 ]INT lowest digit;
lowest digit[ 2 ] := lowest digit[ 1 ] := -1;
LONG INT p10 := 100;
FOR i FROM 3 TO 9 DO
FOR p FROM 2 TO 9 WHILE LONG INT np = power[ i, p ] * i;
np < p10 DO
lowest digit[ i ] := p
OD;
p10 *:= 10
OD;
# find the maximum number of zeros possible for each width and max digit #
[ 1 : 9, 1 : 9 ]INT max zeros; FOR i TO 9 DO FOR j TO 9 DO max zeros[ i, j ] := 0 OD OD;
p10 := 1000;
FOR w FROM 3 TO 9 DO
FOR d FROM lowest digit[ w ] TO 9 DO
INT nz := 9;
WHILE IF nz < 0
THEN FALSE
ELSE LONG INT np := power[ w, d ] * nz;
np > p10
FI
DO
nz -:= 1
OD;
max zeros[ w, d ] := IF nz > w THEN 0 ELSE w - nz FI
OD;
p10 *:= 10
OD;
# find the numbers, works backeards through the possible combinations of #
# digits, starting from all 9s #
[ 1 : 100 ]LONG INT numbers; # will hold the own digit power sum numbers #
INT n count := 0; # count of the own digit power sums #
INT try count := 0; # count of digit combinations tried #
[ 1 : 9 ]INT digits; # the latest digit combination to try #
FOR d TO 9 DO digits[ d ] := 9 OD;
FOR d FROM 0 TO 8 DO used[ d ] := 0 OD; used[ 9 ] := 9;
INT width := 9; # number of digits #
INT last := width; # final digit position #
p10 := 100 000 000; # min value for a width digit power sum #
WHILE width > 2 DO
try count +:= 1;
LONG INT dps := 0; # construct the digit power sum #
check := used;
FOR i TO 9 DO
IF used[ i ] /= 0 THEN dps +:= used[ i ] * power[ width, i ] FI
OD;
# reduce the count of each digit by the number of times it appear in the digit power sum #
LONG INT n := dps;
WHILE check[ SHORTEN ( n MOD 10 ) ] -:= 1; # reduce the count of this digit #
( n OVERAB 10 ) > 0
DO SKIP OD;
BOOL reduce width := dps <= p10;
IF NOT reduce width THEN
# dps is not less than the minimum possible width number #
# check there are no non-zero check counts left and so result is #
# equal to its digit power sum #
INT z count := 0;
FOR i FROM 0 TO 9 WHILE check[ i ] = 0 DO z count +:= 1 OD;
IF z count = 10 THEN
numbers[ n count +:= 1 ] := dps
FI;
# prepare the next digit combination: reduce the last digit #
used[ digits[ last ] ] -:= 1;
digits[ last ] -:= 1;
IF digits[ last ] = 0 THEN
# the last digit is now zero - check this number of zeros is possible #
IF used[ 0 ] >= max zeros[ width, digits[ 1 ] ] THEN
# have exceeded the maximum number of zeros for the first digit in this width #
digits[ last ] := -1
FI
FI;
IF digits[ last ] >= 0 THEN
# still processing the last digit #
used[ digits[ last ] ] +:= 1
ELSE
# last digit is now -1, start processing the previous digit #
INT prev := last;
WHILE IF ( prev -:= 1 ) < 1
THEN # processed all digits #
FALSE
ELSE
# have another digit #
used[ digits[ prev ] ] -:= 1;
digits[ prev ] -:= 1;
digits[ prev ] < 0
FI
DO SKIP OD;
IF prev > 0 THEN
# still some digits to process #
IF prev = 1 THEN
IF digits[ 1 ] <= lowest digit[ width ] THEN
# just finished the lowest possible maximum digit for this width #
prev := 0
FI
FI;
IF prev /= 0 THEN
# OK to try a lower digit #
used[ digits[ prev ] ] +:= 1;
FOR i FROM prev + 1 TO width DO
digits[ i ] := digits[ prev ];
used[ digits[ prev ] ] +:= 1
OD
FI
FI;
IF prev <= 0 THEN
# processed all the digits for this width #
reduce width := TRUE
FI
FI
FI;
IF reduce width THEN
# reduce the number of digits #
width := last -:= 1;
IF last > 0 THEN
# iniialise for fewer digits #
FOR d TO last DO digits[ d ] := 9 OD;
FOR d FROM last + 1 TO 9 DO digits[ d ] := -1 OD;
FOR d FROM 0 TO 9 DO used[ d ] := 0 OD;
used[ 9 ] := last;
p10 OVERAB 10
FI
FI
OD;
# show the own digit power sums #
print( ( "Own digits power sums for N = 3 to 9 inclusive:", newline ) );
FOR i FROM n count BY -1 TO LWB numbers DO
print( ( whole( numbers[ i ], 0 ), newline ) )
OD;
print( ( "Considered ", whole( try count, 0 ), " digit combinations" ) )
END
- Output:
Own digits power sums for N = 3 to 9 inclusive: 153 370 371 407 1634 8208 9474 54748 92727 93084 548834 1741725 4210818 9800817 9926315 24678050 24678051 88593477 146511208 472335975 534494836 912985153 Considered 73359 digit combinations
Arturo
loop 3..8 'nofDigits ->
loop (10 ^ nofDigits-1)..dec 10^nofDigits 'n ->
if n = sum map digits n => [& ^ nofDigits] ->
print n
- Output:
153 370 371 407 1634 8208 9474 54748 92727 93084 548834 1741725 4210818 9800817 9926315 24678050 24678051 88593477
C
Iterative (slow)
Takes about 1.9 seconds to run (GCC 9.3.0 -O3).
#include <stdio.h>
#include <math.h>
#define MAX_DIGITS 9
int digits[MAX_DIGITS];
void getDigits(int i) {
int ix = 0;
while (i > 0) {
digits[ix++] = i % 10;
i /= 10;
}
}
int main() {
int n, d, i, max, lastDigit, sum, dp;
int powers[10] = {0, 1, 4, 9, 16, 25, 36, 49, 64, 81};
printf("Own digits power sums for N = 3 to 9 inclusive:\n");
for (n = 3; n < 10; ++n) {
for (d = 2; d < 10; ++d) powers[d] *= d;
i = (int)pow(10, n-1);
max = i * 10;
lastDigit = 0;
while (i < max) {
if (!lastDigit) {
getDigits(i);
sum = 0;
for (d = 0; d < n; ++d) {
dp = digits[d];
sum += powers[dp];
}
} else if (lastDigit == 1) {
sum++;
} else {
sum += powers[lastDigit] - powers[lastDigit-1];
}
if (sum == i) {
printf("%d\n", i);
if (lastDigit == 0) printf("%d\n", i + 1);
i += 10 - lastDigit;
lastDigit = 0;
} else if (sum > i) {
i += 10 - lastDigit;
lastDigit = 0;
} else if (lastDigit < 9) {
i++;
lastDigit++;
} else {
i++;
lastDigit = 0;
}
}
}
return 0;
}
- Output:
Same as Wren example.
Recursive (very fast)
Down now to 14ms.
#include <stdio.h>
#include <string.h>
#define MAX_BASE 10
typedef unsigned long long ulong;
int usedDigits[MAX_BASE];
ulong powerDgt[MAX_BASE][MAX_BASE];
ulong numbers[60];
int nCount = 0;
void initPowerDgt() {
int i, j;
powerDgt[0][0] = 0;
for (i = 1; i < MAX_BASE; ++i) powerDgt[0][i] = 1;
for (j = 1; j < MAX_BASE; ++j) {
for (i = 0; i < MAX_BASE; ++i) {
powerDgt[j][i] = powerDgt[j-1][i] * i;
}
}
}
ulong calcNum(int depth, int used[MAX_BASE]) {
int i;
ulong result = 0, r, n;
if (depth < 3) return 0;
for (i = 1; i < MAX_BASE; ++i) {
if (used[i] > 0) result += powerDgt[depth][i] * used[i];
}
if (result == 0) return 0;
n = result;
do {
r = n / MAX_BASE;
used[n-r*MAX_BASE]--;
n = r;
depth--;
} while (r);
if (depth) return 0;
i = 1;
while (i < MAX_BASE && used[i] == 0) i++;
if (i >= MAX_BASE) numbers[nCount++] = result;
return 0;
}
void nextDigit(int dgt, int depth) {
int i, used[MAX_BASE];
if (depth < MAX_BASE-1) {
for (i = dgt; i < MAX_BASE; ++i) {
usedDigits[dgt]++;
nextDigit(i, depth+1);
usedDigits[dgt]--;
}
}
if (dgt == 0) dgt = 1;
for (i = dgt; i < MAX_BASE; ++i) {
usedDigits[i]++;
memcpy(used, usedDigits, sizeof(usedDigits));
calcNum(depth, used);
usedDigits[i]--;
}
}
int main() {
int i, j;
ulong t;
initPowerDgt();
nextDigit(0, 0);
// sort and remove duplicates
for (i = 0; i < nCount-1; ++i) {
for (j = i + 1; j < nCount; ++j) {
if (numbers[j] < numbers[i]) {
t = numbers[i];
numbers[i] = numbers[j];
numbers[j] = t;
}
}
}
j = 0;
for (i = 1; i < nCount; ++i) {
if (numbers[i] != numbers[j]) {
j++;
t = numbers[i];
numbers[i] = numbers[j];
numbers[j] = t;
}
}
printf("Own digits power sums for N = 3 to 9 inclusive:\n");
for (i = 0; i <= j; ++i) printf("%lld\n", numbers[i]);
return 0;
}
- Output:
Same as before.
C++
#include <cmath>
#include <cstdint>
#include <iostream>
#include <vector>
int main() {
std::vector<uint32_t> powers = { 0, 1, 4, 9, 16, 25, 36, 49, 64, 81 };
std::cout << "Own digits power sums for N = 3 to 9 inclusive:" << std::endl;
for ( uint32_t n = 3; n <= 9; ++n ) {
for ( uint32_t d = 2; d <= 9; ++d ) {
powers[d] *= d;
}
uint64_t number = std::pow(10, n - 1);
uint64_t maximum = number * 10;
uint32_t last_digit = 0;
uint32_t digit_sum = 0;
while ( number < maximum ) {
if ( last_digit == 0 ) {
digit_sum = 0;
uint64_t copy = number;
while ( copy > 0 ) {
digit_sum += powers[copy % 10];
copy /= 10;
}
} else if ( last_digit == 1 ) {
digit_sum++;
} else {
digit_sum += powers[last_digit] - powers[last_digit - 1];
}
if ( digit_sum == number ) {
std::cout << number << std::endl;
if ( last_digit == 0 ) {
std::cout << number + 1 << std::endl;
}
number += 10 - last_digit;
last_digit = 0;
} else if ( digit_sum > number ) {
number += 10 - last_digit;
last_digit = 0;
} else if ( last_digit < 9 ) {
number++;
last_digit++;
} else {
number++;
last_digit = 0;
}
}
}
}
- Output:
Own digits power sums for N = 3 to 9 inclusive: 153 370 371 407 1634 8208 9474 54748 92727 93084 548834 1741725 4210818 9800817 9926315 24678050 24678051 88593477 146511208 472335975 534494836 912985153
D
Slow
import std.stdio;
import std.conv;
import std.algorithm;
import std.range;
bool isOwnDigitsPowerSum(uint n)
{
auto nStr = n.text;
return nStr.map!(d => (d - '0') ^^ nStr.length).sum == n;
}
void main()
{
iota(10^^2, 10^^9).filter!isOwnDigitsPowerSum.writeln;
}
- Output:
[153, 370, 371, 407, 1634, 8208, 9474, 54748, 92727, 93084, 548834, 1741725, 4210818, 9800817, 9926315, 24678050, 24678051, 88593477, 146511208, 472335975, 534494836, 912985153]
Faster
import std.stdio;
const int[10][10] powerTable = [
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 2, 4, 8, 16, 32, 64, 128, 256, 512],
[1, 3, 9, 27, 81, 243, 729, 2_187, 6_561, 19_683],
[1, 4, 16, 64, 256, 1_024, 4_096, 16_384, 65_536, 262_144],
[1, 5, 25, 125, 625, 3125, 15_625, 78_125, 390_625, 1_953_125],
[1, 6, 36, 216, 1_296, 7_776, 46_656, 279_936, 1_679_616, 10_077_696],
[1, 7, 49, 343, 2_401, 16_807, 117_649, 823_543, 57_64_801, 40_353_607],
[1, 8, 64, 512, 4_096, 32_768, 262_144, 2_097_152, 16_777_216, 134_217_728],
[1, 9, 81, 729, 6_561, 59_049, 531_441, 4_782_969, 43_046_721, 387_420_489]
];
void digitsPowerSum(ref int Number, ref int DigitCount, int Level, int Sum) {
if (Level == 0) {
for (int Digits = 0; Digits <= 9; ++Digits) {
if (((Sum + powerTable[Digits][DigitCount]) == Number) && (Number >= 100)) {
writefln("%s: %s", DigitCount, Number);
}
++Number;
switch (Number) {
case 10:
case 100:
case 1_000:
case 10_000:
case 100_000:
case 1_000_000:
case 10_000_000:
case 100_000_000:
++DigitCount;
break;
default:
break;
}
}
}
else {
for (int Digits = 0; Digits <= 9; ++Digits) {
digitsPowerSum(Number, DigitCount, Level - 1, Sum + powerTable[Digits][DigitCount]);
}
}
}
void main() {
int Number = 0;
int DigitCount = 1;
//
digitsPowerSum(Number, DigitCount, 9-1, 0);
}
- Output:
3: 153 3: 370 3: 371 3: 407 4: 1634 4: 8208 4: 9474 5: 54748 5: 92727 5: 93084 6: 548834 7: 1741725 7: 4210818 7: 9800817 7: 9926315 8: 24678050 8: 24678051 8: 88593477 9: 146511208 9: 472335975 9: 534494836 9: 912985153
Delphi
Started with brute force method which took over a minute to do the 8-digit problem. Then borrowed ideas from everywhere, especially the XPL0 implementation.
{Table to speed up power(X,Y) calculation }
const PowerTable: array [0..9] of array [0..9] of integer = (
(1, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
(1, 2, 4, 8, 16, 32, 64, 128, 256, 512),
(1, 3, 9, 27, 81, 243, 729, 2187, 6561, 19683),
(1, 4, 16, 64, 256, 1024, 4096, 16384, 65536, 262144),
(1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125),
(1, 6, 36, 216, 1296, 7776, 46656, 279936, 1679616, 10077696),
(1, 7, 49, 343, 2401, 16807, 117649, 823543, 5764801, 40353607),
(1, 8, 64, 512, 4096, 32768, 262144, 2097152, 16777216, 134217728),
(1, 9, 81, 729, 6561, 59049, 531441, 4782969, 43046721, 387420489)
);
procedure DigitsPowerSum(Memo: TMemo; var Number, DigitCount: integer; Level, Sum: integer);
{Recursively process DigitCount power}
var Digits: integer;
begin
{Finish when recursion = Level Zero}
if Level = 0 then
begin
for Digits:= 0 to 9 do
begin
{Test combinations of digits and previous sum against number}
if ((Sum + PowerTable[Digits, DigitCount]) = Number) and
(Number >= 100) then
begin
Memo.Lines.Add(IntToStr(DigitCount)+' '+IntToStr(Number));
end;
Inc(Number);
{Keep track of digit count - increases on even power of 10}
case Number of
10, 100, 1000, 10000, 100000,
1000000, 10000000, 100000000: Inc(DigitCount);
end;
end;
end
else for Digits:= 0 to 9 do
begin
{Recurse through all digits/levels}
DigitsPowerSum(Memo, Number, DigitCount,
Level-1, Sum + PowerTable[Digits, DigitCount]);
end;
end;
procedure ShowDigitsPowerSum(Memo: TMemo);
var Number, DigitCount: integer;
begin
Number:= 0;
DigitCount:= 1;
DigitsPowerSum(Memo, Number, DigitCount, 9-1, 0);
end;
- Output:
3 153 3 370 3 371 3 407 4 1634 4 8208 4 9474 5 54748 5 92727 5 93084 6 548834 7 1741725 7 4210818 7 9800817 7 9926315 8 24678050 8 24678051 8 88593477 9 146511208 9 472335975 9 534494836 9 912985153 Elapsed Time: 3.058 Sec.
EasyLang
fastfunc next curr n limit .
repeat
curr += 1
if curr = limit
return -1
.
sum = 0
tmp = curr
repeat
dig = tmp mod 10
tmp = tmp div 10
h = n
r = 1
while h > 0
r *= dig
h -= 1
.
sum += r
until tmp = 0
.
until sum = curr
.
return curr
.
for n = 3 to 8
curr = pow 10 (n - 1)
repeat
curr = next curr n pow 10 n
until curr = -1
print curr
.
.
F#
// Own digits power sum. Nigel Galloway: October 2th., 2021
let fN g=let N=[|for n in 0..9->pown n g|] in let rec fN g=function n when n<10->N.[n]+g |n->fN(N.[n%10]+g)(n/10) in (fun g->fN 0 g)
{3..9}|>Seq.iter(fun g->let fN=fN g in printf $"%d{g} digit are:"; {pown 10 (g-1)..(pown 10 g)-1}|>Seq.iter(fun g->if g=fN g then printf $" %d{g}"); printfn "")
- Output:
3 digit are: 153 370 371 407 4 digit are: 1634 8208 9474 5 digit are: 54748 92727 93084 6 digit are: 548834 7 digit are: 1741725 4210818 9800817 9926315 8 digit are: 24678050 24678051 88593477 9 digit are: 146511208 472335975 534494836 912985153
FreeBASIC
dim as uinteger N, curr, temp, dig, sum
for N = 3 to 9
for curr = 10^(N-1) to 10^N-1
sum = 0
temp = curr
do
dig = temp mod 10
temp = temp \ 10
sum += dig ^ N
loop until temp = 0
if sum = curr then print curr
next curr
next N
- Output:
As above.
Go
Iterative (slow)
Takes about 16.5 seconds to run including compilation time.
package main
import (
"fmt"
"math"
"rcu"
)
func main() {
powers := [10]int{0, 1, 4, 9, 16, 25, 36, 49, 64, 81}
fmt.Println("Own digits power sums for N = 3 to 9 inclusive:")
for n := 3; n < 10; n++ {
for d := 2; d < 10; d++ {
powers[d] *= d
}
i := int(math.Pow(10, float64(n-1)))
max := i * 10
lastDigit := 0
sum := 0
var digits []int
for i < max {
if lastDigit == 0 {
digits = rcu.Digits(i, 10)
sum = 0
for _, d := range digits {
sum += powers[d]
}
} else if lastDigit == 1 {
sum++
} else {
sum += powers[lastDigit] - powers[lastDigit-1]
}
if sum == i {
fmt.Println(i)
if lastDigit == 0 {
fmt.Println(i + 1)
}
i += 10 - lastDigit
lastDigit = 0
} else if sum > i {
i += 10 - lastDigit
lastDigit = 0
} else if lastDigit < 9 {
i++
lastDigit++
} else {
i++
lastDigit = 0
}
}
}
}
- Output:
Same as Wren example.
Recursive (very fast)
Down to about 128 ms now including compilation time. Actual run time only 8 ms!
package main
import "fmt"
const maxBase = 10
var usedDigits = [maxBase]int{}
var powerDgt = [maxBase][maxBase]uint64{}
var numbers []uint64
func initPowerDgt() {
for i := 1; i < maxBase; i++ {
powerDgt[0][i] = 1
}
for j := 1; j < maxBase; j++ {
for i := 0; i < maxBase; i++ {
powerDgt[j][i] = powerDgt[j-1][i] * uint64(i)
}
}
}
func calcNum(depth int, used [maxBase]int) uint64 {
if depth < 3 {
return 0
}
result := uint64(0)
for i := 1; i < maxBase; i++ {
if used[i] > 0 {
result += uint64(used[i]) * powerDgt[depth][i]
}
}
if result == 0 {
return 0
}
n := result
for {
r := n / maxBase
used[n-r*maxBase]--
n = r
depth--
if r == 0 {
break
}
}
if depth != 0 {
return 0
}
i := 1
for i < maxBase && used[i] == 0 {
i++
}
if i >= maxBase {
numbers = append(numbers, result)
}
return 0
}
func nextDigit(dgt, depth int) {
if depth < maxBase-1 {
for i := dgt; i < maxBase; i++ {
usedDigits[dgt]++
nextDigit(i, depth+1)
usedDigits[dgt]--
}
}
if dgt == 0 {
dgt = 1
}
for i := dgt; i < maxBase; i++ {
usedDigits[i]++
calcNum(depth, usedDigits)
usedDigits[i]--
}
}
func main() {
initPowerDgt()
nextDigit(0, 0)
// sort and remove duplicates
for i := 0; i < len(numbers)-1; i++ {
for j := i + 1; j < len(numbers); j++ {
if numbers[j] < numbers[i] {
numbers[i], numbers[j] = numbers[j], numbers[i]
}
}
}
j := 0
for i := 1; i < len(numbers); i++ {
if numbers[i] != numbers[j] {
j++
numbers[i], numbers[j] = numbers[j], numbers[i]
}
}
numbers = numbers[0 : j+1]
fmt.Println("Own digits power sums for N = 3 to 9 inclusive:")
for _, n := range numbers {
fmt.Println(n)
}
}
- Output:
Same as before.
Haskell
Using a function from the Combinations with Repetitions task:
import Data.List (sort)
------------------- OWN DIGITS POWER SUM -----------------
ownDigitsPowerSums :: Int -> [Int]
ownDigitsPowerSums n = sort (ns >>= go)
where
ns = combsWithRep n [0 .. 9]
go xs
| digitsMatch m xs = [m]
| otherwise = []
where
m = foldr ((+) . (^ n)) 0 xs
digitsMatch :: Show a => a -> [Int] -> Bool
digitsMatch n ds =
sort ds == sort (digits n)
--------------------------- TEST -------------------------
main :: IO ()
main = do
putStrLn "N ∈ [3 .. 8]"
mapM_ print ([3 .. 8] >>= ownDigitsPowerSums)
putStrLn ""
putStrLn "N=9"
mapM_ print $ ownDigitsPowerSums 9
------------------------- GENERIC ------------------------
combsWithRep ::
(Eq a) =>
Int ->
[a] ->
[[a]]
combsWithRep k xs = comb k []
where
comb 0 ys = ys
comb n [] = comb (pred n) (pure <$> xs)
comb n peers = comb (pred n) (peers >>= nextLayer)
where
nextLayer ys@(h : _) =
(: ys) <$> dropWhile (/= h) xs
digits :: Show a => a -> [Int]
digits n = (\x -> read [x] :: Int) <$> show n
- Output:
N ∈ [3 .. 8] 153 370 371 407 1634 8208 9474 54748 92727 93084 548834 1741725 4210818 9800817 9926315 24678050 24678051 88593477 N=9 146511208 472335975 534494836 912985153
J
Java
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public final class OwnDigitsPowerSum {
public static void main(String[] args) {
List<Integer> powers = IntStream.rangeClosed(0, 9).boxed().map( i -> i * i ).collect(Collectors.toList());
System.out.println("Own digits power sums for N = 3 to 9 inclusive:");
for ( int n = 3; n <= 9; n++ ) {
for ( int d = 2; d <= 9; d++ ) {
powers.set(d, powers.get(d) * d);
}
long number = (long) Math.pow(10, n - 1);
long maximum = number * 10;
int lastDigit = 0;
int sum = 0;
while ( number < maximum ) {
if ( lastDigit == 0 ) {
sum = String.valueOf(number)
.chars().map(Character::getNumericValue).map( i -> powers.get(i) ).sum();
} else if ( lastDigit == 1 ) {
sum += 1;
} else {
sum += powers.get(lastDigit) - powers.get(lastDigit - 1);
}
if ( sum == number ) {
System.out.println(number);
if ( lastDigit == 0 ) {
System.out.println(number + 1);
}
number += 10 - lastDigit;
lastDigit = 0;
} else if ( sum > number ) {
number += 10 - lastDigit;
lastDigit = 0;
} else if ( lastDigit < 9 ) {
number += 1;
lastDigit += 1;
} else {
number += 1;
lastDigit = 0;
}
}
}
}
}
- Output:
Own digits power sums for N = 3 to 9 inclusive: 153 370 371 407 1634 8208 9474 54748 92727 93084 548834 1741725 4210818 9800817 9926315 24678050 24678051 88593477 146511208 472335975 534494836 912985153
jq
Works with gojq, the Go implementation of jq (*)
(*) gojq requires significantly more time and memory to run this program.
def maxBase: 10;
# The global object:
# { usedDigits, powerDgt, numbers }
def initPowerDgt:
reduce range(0; maxBase) as $i (null; .[$i] = [range(0;maxBase)|0])
| reduce range(1; maxBase) as $i (.; .[0][$i] = 1)
| reduce range(1; maxBase) as $j (.;
reduce range(0; maxBase) as $i (.;
.[$j][$i] = .[$j-1][$i] * $i )) ;
# Input: global object
# Output: .numbers
def calcNum($depth):
if $depth < 3 then .
else .usedDigits as $used
| .powerDgt as $powerDgt
| (reduce range(1; maxBase) as $i (0;
if $used[$i] > 0 then . + $used[$i] * $powerDgt[$depth][$i]
else . end )) as $result
| if $result == 0 then .
else {n: $result, $used, $depth, numbers, r: null}
| until (.r == 0;
.r = ((.n / maxBase) | floor)
| .used[.n - .r * maxBase] += -1
| .n = .r
| .depth += -1 )
| if .depth != 0 then .
else . + {i: 1}
| until( .i >= maxBase or .used[.i] != 0; .i += 1)
| if .i >= maxBase
then .numbers += [$result]
else .
end
end
end
end
| .numbers ;
# input: global object
# output: updated global object
def nextDigit($dgt; $depth):
if $depth < maxBase-1
then reduce range($dgt; maxBase) as $i (.;
.usedDigits[$dgt] += 1
| nextDigit($i; $depth+1)
| .usedDigits[$dgt] += -1 )
else .
end
| reduce range(if $dgt == 0 then 1 else $dgt end; maxBase) as $i (.;
.usedDigits[$i] += 1
| .numbers = calcNum($depth)
| .usedDigits[$i] += -1 ) ;
def main:
{ usedDigits: [range(0; maxBase)|0],
powerDgt: initPowerDgt,
numbers:[] }
| nextDigit(0; 0)
| .numbers
| unique[]
;
"Own digits power sums for N = 3 to 9 inclusive:",
main
- Output:
As for Wren.
Julia
function isowndigitspowersum(n::Integer, base=10)
dig = digits(n, base=base)
exponent = length(dig)
return mapreduce(x -> x^exponent, +, dig) == n
end
for i in 10^2:10^9-1
isowndigitspowersum(i) && println(i)
end
- Output:
153 370 371 407 1634 8208 9474 54748 92727 93084 548834 1741725 4210818 9800817 9926315 24678050 24678051 88593477 146511208 472335975 534494836 912985153
Nim
import std/[algorithm, sequtils, strutils]
const MaxBase = 10
type UsedDigits = array[MaxBase, int]
var
usedDigits: UsedDigits
numbers: seq[int]
proc initPowerDigits(): array[MaxBase, array[MaxBase, int]] {.compileTime.} =
for i in 1..<MaxBase:
result[0][i] = 1
for j in 1..<MaxBase:
for i in 0..<MaxBase:
result[j][i] = result[j - 1][i] * i
const PowerDigits = initPowerDigits()
proc calcNum(depth: int; used: UsedDigits) =
var used = used
var depth = depth
if depth < 3: return
var result = 0
for i in 1..<MaxBase:
if used[i] > 0:
result += used[i] * PowerDigits[depth][i]
if result == 0: return
var n = result
while true:
let r = n div MaxBase
dec used[n - r * MaxBase]
n = r
dec depth
if r == 0: break
if depth != 0: return
var i = 1
while i < MaxBase and used[i] == 0:
inc i
if i == MaxBase:
numbers.add result
proc nextDigit(digit, depth: int) =
var depth = depth
if depth < MaxBase - 1:
for i in digit..<MaxBase:
inc usedDigits[digit]
nextDigit(i, depth + 1)
dec usedDigits[digit]
let digit = if digit == 0: 1 else: digit
for i in digit..<MaxBase:
inc usedDigits[i]
calcNum(depth, usedDigits)
dec usedDigits[i]
nextDigit(0, 0)
numbers.sort()
numbers = numbers.deduplicate(true)
echo "Own digits power sums for N = 3 to 9 inclusive:"
echo numbers.join("\n")
- Output:
Own digits power sums for N = 3 to 9 inclusive: 153 370 371 407 1634 8208 9474 54748 92727 93084 548834 1741725 4210818 9800817 9926315 24678050 24678051 88593477 146511208 472335975 534494836 912985153
Pascal
Mathematica /Wolfram Language
cf = Compile[{{n, _Integer}}, Module[{digs, len},
digs = IntegerDigits[n];
len = Length[digs];
Total[digs^len] == n
], CompilationTarget -> "C"];
Select[Range[100, 100000000 - 1], cf]
- Output:
{153, 370, 371, 407, 1634, 8208, 9474, 54748, 92727, 93084, 548834, 1741725, 4210818, 9800817, 9926315, 24678050, 24678051, 88593477}
PARI/GP
You should have enough memory to avoid stack overflow and configure GP accordingly...
select(is_Armstrong(n)={n==vecsum([d^#n|d<-n=digits(n)])}, [100..999999999])
- Output:
%1 = [153,370,371,407,1634,8208,9474,54748,92727,93084,548834,1741725,4210818,9800817,9926315, 24678050,24678051,88593477,146511208,472335975,534494836,912985153]
Perl
Brute Force
Use Parallel::ForkManager
to obtain concurrency, trading some code complexity for less-than-infinite run time. Still very slow.
use strict;
use warnings;
use feature 'say';
use List::Util 'sum';
use Parallel::ForkManager;
my %own_dps;
my($lo,$hi) = (3,9);
my $cores = 8; # configure to match hardware being used
my $start = 10**($lo-1);
my $stop = 10**$hi - 1;
my $step = int(1 + ($stop - $start)/ ($cores+1));
my $pm = Parallel::ForkManager->new($cores);
RUN:
for my $i ( 0 .. $cores ) {
$pm->run_on_finish (
sub {
my ($pid, $exit_code, $ident, $exit_signal, $core_dump, $data_ref) = @_;
$own_dps{$ident} = $data_ref;
}
);
$pm->start($i) and next RUN;
my @values;
for my $n ( ($start + $i*$step) .. ($start + ($i+1)*$step) ) {
push @values, $n if $n == sum map { $_**length($n) } split '', $n;
}
$pm->finish(0, \@values)
}
$pm->wait_all_children;
say $_ for sort { $a <=> $b } map { @$_ } values %own_dps;
- Output:
153 370 371 407 1634 8208 9474 54748 92727 93084 548834 1741725 4210818 9800817 9926315 24678050 24678051 88593477 146511208 472335975 534494836 912985153
Combinatorics
Leverage the fact that all combinations of digits give same DPS. Much faster than brute force, as only non-redundant values tested.
use strict;
use warnings;
use List::Util 'sum';
use Algorithm::Combinatorics qw<combinations_with_repetition>;
my @own_dps;
for my $d (3..9) {
my $iter = combinations_with_repetition([0..9], $d);
while (my $p = $iter->next) {
my $dps = sum map { $_**$d } @$p;
next unless $d == length $dps and join('', @$p) == join '', sort split '', $dps;
push @own_dps, $dps;
}
}
print join "\n", sort { $a <=> $b } @own_dps;
- Output:
153 370 371 407 1634 8208 9474 54748 92727 93084 548834 1741725 4210818 9800817 9926315 24678050 24678051 88593477 146511208 472335975 534494836 912985153
Phix
with javascript_semantics atom minps, maxps sequence pdn, results procedure own_digit_power_sum(integer n, taken=0, at=0, atom cps=0, son=0) -- looking for n digit numbers, taken is the number of digits collected so far, -- any further digits must be "at" or higher. cps is the current power sum and -- son is the smallest ordered number from those digits (eg 47 not 407). -- results collected in son order eg 370 407 153 371 (from 37 47 135 137). if taken=n then if cps>=minps and cps>=son then string scps = sprintf("%d",cps), tcps = trim_head(sort(scps),"0"), sson = sprintf("%d",son) if tcps=sson then results = append(results, scps) end if end if else taken += 1 for d=at to 9 do atom ncps = cps+pdn[d+1] if ncps>maxps then exit end if own_digit_power_sum(n,taken,d,ncps,son*10+d) end for end if end procedure atom t0 = time() for n=3 to iff(machine_bits()=64?17:14) do minps = power(10,n-1) -- eg 100 maxps = power(10,n)-1 -- eg 999 pdn = sq_power(tagset(9,0),n) results = {} own_digit_power_sum(n) if length(results) then printf(1,"%d digits: %s\n",{n,join(sort(deep_copy(results))," ")}) end if end for ?elapsed(time()-t0)
- Output:
3 digits: 153 370 371 407 4 digits: 1634 8208 9474 5 digits: 54748 92727 93084 6 digits: 548834 7 digits: 1741725 4210818 9800817 9926315 8 digits: 24678050 24678051 88593477 9 digits: 146511208 472335975 534494836 912985153 10 digits: 4679307774 11 digits: 32164049650 32164049651 40028394225 42678290603 44708635679 49388550606 82693916578 94204591914 14 digits: 28116440335967 "8.8s"
Takes about 3 times as long under p2js. You can push it a bit further on 64 bit, but unfortunately some discrepancies crept in at 19 digits, so I decided to call it a day at 17 digits (there are no 18 digit solutions).
16 digits: 4338281769391370 4338281769391371 17 digits: 21897142587612075 35641594208964132 35875699062250035 "33.2s"
Python
Python :: Procedural
slower
""" Rosetta code task: Own_digits_power_sum """
def isowndigitspowersum(integer):
""" true if sum of (digits of number raised to number of digits) == number """
digits = [int(c) for c in str(integer)]
exponent = len(digits)
return sum(x ** exponent for x in digits) == integer
print("Own digits power sums for N = 3 to 9 inclusive:")
for i in range(100, 1000000000):
if isowndigitspowersum(i):
print(i)
- Output:
Same as Wren example. Takes over a half hour to run.
faster
Same output.
""" Rosetta code task: Own_digits_power_sum (recursive method)"""
MAX_BASE = 10
POWER_DIGIT = [[1 for _ in range(MAX_BASE)] for _ in range(MAX_BASE)]
USED_DIGITS = [0 for _ in range(MAX_BASE)]
NUMBERS = []
def calc_num(depth, used):
""" calculate the number at a given recurse depth """
result = 0
if depth < 3:
return 0
for i in range(1, MAX_BASE):
if used[i] > 0:
result += used[i] * POWER_DIGIT[depth][i]
if result != 0:
num, rnum = result, 1
while rnum != 0:
rnum = num // MAX_BASE
used[num - rnum * MAX_BASE] -= 1
num = rnum
depth -= 1
if depth == 0:
i = 1
while i < MAX_BASE and used[i] == 0:
i += 1
if i >= MAX_BASE:
NUMBERS.append(result)
return 0
def next_digit(dgt, depth):
""" get next digit at the given depth """
if depth < MAX_BASE - 1:
for i in range(dgt, MAX_BASE):
USED_DIGITS[dgt] += 1
next_digit(i, depth + 1)
USED_DIGITS[dgt] -= 1
if dgt == 0:
dgt = 1
for i in range(dgt, MAX_BASE):
USED_DIGITS[i] += 1
calc_num(depth, USED_DIGITS.copy())
USED_DIGITS[i] -= 1
for j in range(1, MAX_BASE):
for k in range(MAX_BASE):
POWER_DIGIT[j][k] = POWER_DIGIT[j - 1][k] * k
next_digit(0, 0)
print(NUMBERS)
NUMBERS = list(set(NUMBERS))
NUMBERS.sort()
print('Own digits power sums for N = 3 to 9 inclusive:')
for n in NUMBERS:
print(n)
Python :: Functional
Using a function from the Combinations with Repetitions task:
'''Own digit power sums'''
from itertools import accumulate, chain, islice, repeat
from functools import reduce
# ownDigitsPowerSums :: Int -> [Int]
def ownDigitsPowerSums(n):
'''All own digit power sums of digit length N'''
def go(xs):
m = reduce(lambda a, x: a + (x ** n), xs, 0)
return [m] if digitsMatch(m)(xs) else []
return concatMap(go)(
combinationsWithRepetitions(n)(range(0, 1 + 9))
)
# digitsMatch :: Int -> [Int] -> Bool
def digitsMatch(n):
'''True if the digits in ds contain exactly
the digits of n, in any order.
'''
def go(ds):
return sorted(ds) == sorted(digits(n))
return go
# ------------------------- TEST -------------------------
# main :: IO ()
def main():
'''Own digit power sums for digit lengths 3..9'''
print(
'\n'.join([
'N ∈ [3 .. 8]',
*map(str, concatMap(ownDigitsPowerSums)(
range(3, 1 + 8)
)),
'\nN=9',
*map(str, ownDigitsPowerSums(9))
])
)
# ----------------------- GENERIC ------------------------
# combinationsWithRepetitions :: Int -> [a] -> [kTuple a]
def combinationsWithRepetitions(k):
'''Combinations with repetitions.
A list of tuples, representing
sets of cardinality k,
with elements drawn from xs.
'''
def f(a, x):
def go(ys, xs):
return xs + [[x] + y for y in ys]
return accumulate(a, go)
def combsBySize(xs):
return [
tuple(x) for x in next(islice(
reduce(
f, xs, chain(
[[[]]],
islice(repeat([]), k)
)
), k, None
))
]
return combsBySize
# concatMap :: (a -> [b]) -> [a] -> [b]
def concatMap(f):
'''A concatenated list over which a function has been
mapped.
The list monad can be derived by using a function f
which wraps its output in a list, (using an empty
list to represent computational failure).
'''
def go(xs):
return list(chain.from_iterable(map(f, xs)))
return go
# digits :: Int -> [Int]
def digits(n):
'''The individual digits of n as integers'''
return [int(c) for c in str(n)]
# MAIN ---
if __name__ == '__main__':
main()
- Output:
N ∈ [3 .. 8] 153 370 371 407 1634 8208 9474 54748 92727 93084 548834 1741725 4210818 9800817 9926315 24678050 24678051 88593477 N=9 146511208 472335975 534494836 912985153
Quackery
narcissistic
is defined at Narcissistic decimal number#Quackery.
100000000 100 - times
[ i^ 100 + narcissistic if
[ i^ 100 + echo cr ] ]
- Output:
153 370 371 407 1634 8208 9474 54748 92727 93084 548834 1741725 4210818 9800817 9926315 24678050 24678051 88593477
Raku
(3..8).map: -> $p {
my %pow = (^10).map: { $_ => $_ ** $p };
my $start = 10 ** ($p - 1);
my $end = 10 ** $p;
my @temp;
for ^9 -> $i {
([X] ($i..9) xx $p).race.map: {
next unless [<=] $_;
my $sum = %pow{$_}.sum;
next if $sum < $start;
next if $sum > $end;
@temp.push: $sum if $sum.comb.Bag eqv $_».Str.Bag
}
}
.say for unique sort @temp;
}
- Output:
153 370 371 407 1634 8208 9474 54748 92727 93084 548834 1741725 4210818 9800817 9926315 24678050 24678051 88593477
Combinations with repetitions
Using code from Combinations with repetitions task, a version that runs relatively quickly, and scales well.
proto combs_with_rep (UInt, @ ) { * }
multi combs_with_rep (0, @ ) { () }
multi combs_with_rep ($, []) { () }
multi combs_with_rep (1, @a) { map { $_, }, @a }
multi combs_with_rep ($n, [$head, *@tail]) {
|combs_with_rep($n - 1, ($head, |@tail)).map({ $head, |@_ }),
|combs_with_rep($n, @tail);
}
say sort gather {
for 3..9 -> $d {
for combs_with_rep($d, [^10]) -> @digits {
.take if $d == .comb.elems and @digits.join == .comb.sort.join given sum @digits X** $d;
}
}
}
- Output:
153 370 371 407 1634 8208 9474 54748 92727 93084 548834 1741725 4210818 9800817 9926315 24678050 24678051 88593477 146511208 472335975 534494836 912985153
Ring
see "working..." + nl
see "Own digits power sum for N = 3 to 9 inclusive:" + nl
for n = 3 to 9
for curr = pow(10,n-1) to pow(10,n)-1
sum = 0
temp = curr
while temp != 0
dig = temp % 10
temp = floor(temp/10)
sum += pow(dig,n)
end
if sum = curr
see "" + curr + nl
ok
next
next
see "done..." + nl
- Output:
working... Own digits power sum for N = 3 to 9 inclusive: 153 370 371 407 1634 8208 9474 54748 92727 93084 548834 1741725 4210818 9800817 9926315 24678050 24678051 88593477 146511208 472335975 534494836 912985153 done...
Ruby
Repeated combinations allow for N=18 in less than a minute.
DIGITS = (0..9).to_a
range = (3..18)
res = range.map do |s|
powers = {}
DIGITS.each{|n| powers[n] = n**s}
DIGITS.repeated_combination(s).filter_map do |combi|
sum = powers.values_at(*combi).sum
sum if sum.digits.sort == combi.sort
end.sort
end
puts "Own digits power sums for N = #{range}:", res
- Output:
Own digits power sums for 3..18 153 370 371 407 1634 8208 9474 54748 92727 93084 548834 1741725 4210818 9800817 9926315 24678050 24678051 88593477 146511208 472335975 534494836 912985153 4679307774 32164049650 32164049651 40028394225 42678290603 44708635679 49388550606 82693916578 94204591914 28116440335967 4338281769391370 4338281769391371 21897142587612075 35641594208964132 35875699062250035
Rust
Slow
fn is_own_digits_power_sum(n: u32) -> bool {
let n_str = n.to_string();
n_str.chars()
.map(|c| {
let digit = c.to_digit(10).unwrap();
digit.pow(n_str.len() as u32)
})
.sum::<u32>()
== n
}
fn main() {
let result: Vec<u32> = (10u32.pow(2)..10u32.pow(9))
.filter(|&n| is_own_digits_power_sum(n))
.collect();
println!("{:?}", result);
}
- Output:
[153, 370, 371, 407, 1634, 8208, 9474, 54748, 92727, 93084, 548834, 1741725, 4210818, 9800817, 9926315, 24678050, 24678051, 88593477, 146511208, 472335975, 534494836, 912985153]
Faster
fn main() {
let mut powers = vec![0, 1, 4, 9, 16, 25, 36, 49, 64, 81];
println!("Own digits power sums for N = 3 to 9 inclusive:");
for n in 3..=9 {
for d in 2..=9 {
powers[d] *= d;
}
let mut i = 10u64.pow(n - 1);
let max = i * 10;
let mut last_digit = 0;
let mut sum = 0;
let mut digits: Vec<u32>;
while i < max {
if last_digit == 0 {
digits = i.to_string()
.chars()
.map(|c| c.to_digit(10).unwrap())
.collect();
sum = digits.iter().map(|&d| powers[d as usize]).sum();
} else if last_digit == 1 {
sum += 1;
} else {
sum += powers[last_digit as usize] - powers[(last_digit - 1) as usize];
}
if sum == i.try_into().unwrap() {
println!("{}", i);
if last_digit == 0 {
println!("{}", i + 1);
}
i += 10 - last_digit;
last_digit = 0;
} else if sum > i.try_into().unwrap() {
i += 10 - last_digit;
last_digit = 0;
} else if last_digit < 9 {
i += 1;
last_digit += 1;
} else {
i += 1;
last_digit = 0;
}
}
}
}
- Output:
Own digits power sums for N = 3 to 9 inclusive: 153 370 371 407 1634 8208 9474 54748 92727 93084 548834 1741725 4210818 9800817 9926315 24678050 24678051 88593477 146511208 472335975 534494836 912985153
Sidef
func armstrong_numbers(n, base=10) {
var D = @(^base)
var P = D.map {|d| d**n }
var list = []
D.combinations_with_repetition(n, {|*c|
var v = c.sum {|d| P[d] }
if (v.digits(base).sort == c) {
list.push(v)
}
})
list.sort
}
for n in (3..10) {
say ("For n = #{'%2d' % n}: ", armstrong_numbers(n))
}
- Output:
For n = 3: [153, 370, 371, 407] For n = 4: [1634, 8208, 9474] For n = 5: [54748, 92727, 93084] For n = 6: [548834] For n = 7: [1741725, 4210818, 9800817, 9926315] For n = 8: [24678050, 24678051, 88593477] For n = 9: [146511208, 472335975, 534494836, 912985153] For n = 10: [4679307774]
Visual Basic .NET
Option Strict On
Option Explicit On
Imports System.IO
''' <summary>
''' Finds n digit numbers N such that the sum of the nth powers of
''' their digits = N
''' </summary>
Module OwnDigitsPowerSum
Public Sub Main
' counts of used digits, check is a copy used to check the number is an own digit power sum
Dim used(9) As Integer
Dim check(9) As Integer
Dim power(9, 9) As Long
For i As Integer = 0 To 9
check(i) = 0
Next i
For i As Integer = 1 To 9
power(1, i) = i
Next i
For j As Integer = 2 To 9
For i As Integer = 1 To 9
power(j, i) = power(j - 1, i) * i
Next i
Next j
' find the lowest possible first digit for each digit combination
' this is the roughly the low3est n where P*n^p > 10^p
Dim lowestDigit(9) As Integer
lowestDigit(1) = -1
lowestDigit(2) = -1
Dim p10 As Long = 100
For i As Integer = 3 To 9
For p As Integer = 2 To 9
Dim np As Long = power(i, p) * i
If Not ( np < p10) Then Exit For
lowestDigit(i) = p
Next p
p10 *= 10
Next i
' find the maximum number of zeros possible for each width and max digit
Dim maxZeros(9, 9) As Integer
For i As Integer = 1 To 9
For j As Integer = 1 To 9
maxZeros(i, j) = 0
Next j
Next i
p10 = 1000
For w As Integer = 3 To 9
For d As Integer = lowestDigit(w) To 9
Dim nz As Integer = 9
Do
If nz < 0 Then
Exit Do
Else
Dim np As Long = power(w, d) * nz
IF Not ( np > p10) Then Exit Do
End If
nz -= 1
Loop
maxZeros(w, d) = If(nz > w, 0, w - nz)
Next d
p10 *= 10
Next w
' find the numbers, works backeards through the possible combinations of
' digits, starting from all 9s
Dim numbers(100) As Long ' will hold the own digit power sum numbers
Dim nCount As Integer = 0 ' count of the own digit power sums
Dim tryCount As Integer = 0 ' count of digit combinations tried
Dim digits(9) As Integer ' the latest digit combination to try
For d As Integer = 1 To 9
digits(d) = 9
Next d
For d As Integer = 0 To 8
used(d) = 0
Next d
used(9) = 9
Dim width As Integer = 9 ' number of digits
Dim last As Integer = width ' final digit position
p10 = 100000000 ' min value for a width digit power sum
Do While width > 2
tryCount += 1
Dim dps As Long = 0 ' construct the digit power sum
check(0) = used(0)
For i As Integer = 1 To 9
check(i) = used(i)
If used(i) <> 0 Then
dps += used(i) * power(width, i)
End If
Next i
' reduce the count of each digit by the number of times it appear in the digit power sum
Dim n As Long = dps
Do
check(CInt(n Mod 10)) -= 1 ' reduce the count of this digit
n \= 10
Loop Until n <= 0
Dim reduceWidth As Boolean = dps <= p10
If Not reduceWidth Then
' dps is not less than the minimum possible width number
' check there are no non-zero check counts left and so result is
' equal to its digit power sum
Dim zCount As Integer = 0
For i As Integer = 0 To 9
If check(i) <> 0 Then Exit For
zCount+= 1
Next i
If zCount = 10 Then
nCount += 1
numbers(nCount) = dps
End If
' prepare the next digit combination: reduce the last digit
used(digits(last)) -= 1
digits(last) -= 1
If digits(last) = 0 Then
' the last digit is now zero - check this number of zeros is possible
If used(0) >= maxZeros(width, digits(1)) Then
' have exceeded the maximum number of zeros for the first digit in this width
digits(last) = -1
End If
End If
If digits(last) >= 0 Then
' still processing the last digit
used(digits(last)) += 1
Else
' last digit is now -1, start processing the previous digit
Dim prev As Integer = last
Do
prev -= 1
If prev < 1 Then
Exit Do
Else
used(digits(prev)) -= 1
digits(prev) -= 1
IF digits(prev) >= 0 Then Exit Do
End If
Loop
If prev > 0 Then
' still some digits to process
If prev = 1 Then
If digits(1) <= lowestDigit(width) Then
' just finished the lowest possible maximum digit for this width
prev = 0
End If
End If
If prev <> 0 Then
' OK to try a lower digit
used(digits(prev)) += 1
For i As Integer = prev + 1 To width
digits(i) = digits(prev)
used(digits(prev)) += 1
Next i
End If
End If
If prev <= 0 Then
' processed all the digits for this width
reduceWidth = True
End If
End If
End If
If reduceWidth Then
' reduce the number of digits
last -= 1
width = last
If last > 0 Then
' iniialise for fewer digits
For d As Integer = 1 To last
digits(d) = 9
Next d
For d As Integer = last + 1 To 9
digits(d) = -1
Next d
For d As Integer = 0 To 8
used(d) = 0
Next d
used(9) = last
p10 \= 10
End If
End If
Loop
' show the own digit power sums
Console.Out.WriteLine("Own digits power sums for N = 3 to 9 inclusive:")
For i As Integer = nCount To 1 Step -1
Console.Out.WriteLine(numbers(i))
Next i
Console.Out.WriteLine("Considered " & tryCount & " digit combinations")
End Sub
End Module
- Output:
Own digits power sums for N = 3 to 9 inclusive: 153 370 371 407 1634 8208 9474 54748 92727 93084 548834 1741725 4210818 9800817 9926315 24678050 24678051 88593477 146511208 472335975 534494836 912985153 Considered 73359 digit combinations
Wren
Iterative (slow)
Includes some simple optimizations to try and quicken up the search. However, getting up to N = 9 still took a little over 4 minutes on my machine.
import "./math" for Int
var powers = [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
System.print("Own digits power sums for N = 3 to 9 inclusive:")
for (n in 3..9) {
for (d in 2..9) powers[d] = powers[d] * d
var i = 10.pow(n-1)
var max = i * 10
var lastDigit = 0
var sum = 0
var digits = null
while (i < max) {
if (lastDigit == 0) {
digits = Int.digits(i)
sum = digits.reduce(0) { |acc, d| acc + powers[d] }
} else if (lastDigit == 1) {
sum = sum + 1
} else {
sum = sum + powers[lastDigit] - powers[lastDigit-1]
}
if (sum == i) {
System.print(i)
if (lastDigit == 0) System.print(i + 1)
i = i + 10 - lastDigit
lastDigit = 0
} else if (sum > i) {
i = i + 10 - lastDigit
lastDigit = 0
} else if (lastDigit < 9) {
i = i + 1
lastDigit = lastDigit + 1
} else {
i = i + 1
lastDigit = 0
}
}
}
- Output:
Own digits power sums for N = 3 to 9 inclusive: 153 370 371 407 1634 8208 9474 54748 92727 93084 548834 1741725 4210818 9800817 9926315 24678050 24678051 88593477 146511208 472335975 534494836 912985153
Recursive (very fast)
Astonishing speed-up. Runtime now only 0.5 seconds!
import "./seq" for Lst
var maxBase = 10
var usedDigits = List.filled(maxBase, 0)
var powerDgt = List.filled(maxBase, null)
var numbers = []
var initPowerDgt = Fn.new {
for (i in 0...maxBase) powerDgt[i] = List.filled(maxBase, 0)
for (i in 1...maxBase) powerDgt[0][i] = 1
for (j in 1...maxBase) {
for (i in 0...maxBase) powerDgt[j][i] = powerDgt[j-1][i] * i
}
}
var calcNum = Fn.new { |depth, used|
if (depth < 3) return 0
var result = 0
for (i in 1...maxBase) {
if (used[i] > 0) result = result + used[i] * powerDgt[depth][i]
}
if (result == 0) return 0
var n = result
while (true) {
var r = (n/maxBase).floor
used[n - r*maxBase] = used[n - r*maxBase] - 1
n = r
depth = depth - 1
if (r == 0) break
}
if (depth != 0) return 0
var i = 1
while (i < maxBase && used[i] == 0) i = i + 1
if (i >= maxBase) numbers.add(result)
return 0
}
var nextDigit // recursive function
nextDigit = Fn.new { |dgt, depth|
if (depth < maxBase-1) {
for (i in dgt...maxBase) {
usedDigits[dgt] = usedDigits[dgt] + 1
nextDigit.call(i, depth + 1)
usedDigits[dgt] = usedDigits[dgt] - 1
}
}
if (dgt == 0) dgt = 1
for (i in dgt...maxBase) {
usedDigits[i] = usedDigits[i] + 1
calcNum.call(depth, usedDigits.toList)
usedDigits[i] = usedDigits[i] - 1
}
}
initPowerDgt.call()
nextDigit.call(0, 0)
numbers = Lst.distinct(numbers)
numbers.sort()
System.print("Own digits power sums for N = 3 to 9 inclusive:")
System.print(numbers.map { |n| n.toString }.join("\n"))
- Output:
Same as iterative version.
XPL0
Slow (14.4 second) recursive solution on a Pi4.
int Num, NumLen, PowTbl(10, 10);
proc PowSum(Lev, Sum); \Display own digits power sum
int Lev, Sum, Dig;
[if Lev = 0 then
[for Dig:= 0 to 9 do
[if Sum + PowTbl(Dig, NumLen) = Num and Num >= 100 then
[IntOut(0, Num); CrLf(0)];
Num:= Num+1;
case Num of
10, 100, 1_000, 10_000, 100_000, 1_000_000, 10_000_000, 100_000_000:
NumLen:= NumLen+1
other [];
];
]
else for Dig:= 0 to 9 do \recurse
PowSum(Lev-1, Sum + PowTbl(Dig, NumLen));
];
int Dig, Pow;
[for Dig:= 0 to 9 do \make digit power table (for speed)
[PowTbl(Dig, 1):= Dig;
for Pow:= 2 to 9 do
PowTbl(Dig, Pow):= PowTbl(Dig, Pow-1)*Dig;
];
Num:= 0;
NumLen:= 1;
PowSum(9-1, 0);
]
- Output:
153 370 371 407 1634 8208 9474 54748 92727 93084 548834 1741725 4210818 9800817 9926315 24678050 24678051 88593477 146511208 472335975 534494836 912985153