Own digits power sum

From Rosetta Code
Own digits power sum is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
Description

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.


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[edit]

Translation of: Python
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) -> N
   ‘ 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, &copy(: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[edit]

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

C[edit]

Iterative (slow)[edit]

Takes about 1.9 seconds to run (GCC 9.3.0 -O3).

Translation of: Wren
#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)[edit]

Translation of: Pascal

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.

F#[edit]

// 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[edit]

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[edit]

Iterative (slow)[edit]

Translation of: Wren
Library: Go-rcu

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)[edit]

Down to about 128 ms now including compilation time. Actual run time only 8 ms!

Translation of: Pascal
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[edit]

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[edit]

See Narcissistic_decimal_number#J

jq[edit]

Translation of: Wren – (recursive version)
Works with: 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[edit]

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

Mathematica/Wolfram Language[edit]

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}

Perl[edit]

Brute Force[edit]

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[edit]

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[edit]

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[edit]

Python :: Procedural[edit]

slower[edit]

""" 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[edit]

Translation of: Wren
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[edit]

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

Raku[edit]

(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[edit]

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[edit]

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[edit]

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

Sidef[edit]

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[edit]

Translation of: ALGOL 68
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[edit]

Iterative (slow)[edit]

Library: Wren-math

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)[edit]

Translation of: Pascal
Library: Wren-seq

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[edit]

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