A Disarium number is an integer where the sum of each digit raised to the power of its position in the number, is equal to the number.

Task
Disarium numbers
You are encouraged to solve this task according to the task description, using any language you may know.


E.G.

135 is a Disarium number:

11 + 32 + 53 == 1 + 9 + 125 == 135

There are a finite number of Disarium numbers.


Task
  • Find and display the first 18 Disarium numbers.


Stretch
  • Find and display all 20 Disarium numbers.


See also



11l

Translation of: Python
F is_disarium(n)
   V digitos = String(n).len
   V suma = 0
   V x = n
   L x != 0
      suma += (x % 10) ^ digitos
      digitos--
      x I/= 10
   I suma == n
      R 1B
   E
      R 0B

V limite = 19
V cont = 0
V n = 0
print(‘The first ’limite‘ Disarium numbers are:’)
L cont < limite
   I is_disarium(n)
      print(n, end' ‘ ’)
      cont++
   n++
Output:
The first 19 Disarium numbers are:
0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798 

Action!

Translation of: PL/M

which is

Translation of: ALGOL 68
;;; find some Disarium Numbers - numbers whose digit-position power sume
;;;      are equal to the number,  e.g.: 135 = 1^1 + 3^2 + 5^3

PROC Main()

  DEFINE MAX_DISARIUM = "9999"

  CARD ARRAY power( 40 )  ; table of powers up to the fourth power ( 1:4, 0:9 )
  CARD n, d, powerOfTen, count, length, v, p, dps, nsub, nprev

  ; compute the n-th powers of 0-9
  FOR d = 0 TO 9 DO power( d ) = D OD
  nsub  = 10
  nprev =  0
  FOR n = 2 TO 4 DO
    power( nsub ) = 0
    FOR d = 1 TO 9 DO
      power( nsub + d ) = power( nprev + d ) * d
    OD
    nprev = nsub
    nsub ==+ 10
  OD

  ; print the Disarium numbers up to 9999 or the 18th, whichever is sooner
  powerOfTen = 10
  length     =  1
  count = 0 n = 0
  WHILE n < MAX_DISARIUM AND count < 18 DO
    IF n = powerOfTen THEN
      ; the number of digits just increased
      powerOfTen ==* 10
      length     ==+  1
    FI
    ; form the digit power sum
    v   = n
    p   = length * 10;
    dps = 0;
    FOR d = 1 TO length DO
      p   ==- 10
      dps ==+ power( p + ( v MOD 10 ) )
      v   ==/ 10
    OD
    IF dps = N THEN
      ; n is Disarium
      count ==+ 1;
      Put( '  )
      PrintC( n )
    FI
    n ==+ 1
  OD

RETURN
Output:
 0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427

Ada

with Ada.Text_IO;

procedure Disarium_Numbers is

   Disarium_Count : constant := 19;

   function Is_Disarium (N : Natural) return Boolean is
      Nn  : Natural := N;
      Pos : Natural := 0;
      Sum : Natural := 0;
   begin
      while Nn /= 0 loop
         Nn  := Nn / 10;
         Pos := Pos + 1;
      end loop;
      Nn := N;
      while Nn /= 0 loop
         Sum := Sum + (Nn mod 10) ** Pos;
         Nn  := Nn / 10;
         Pos := Pos - 1;
      end loop;
      return N = Sum;
   end Is_Disarium;

   Count : Natural := 0;
begin
   for N in 0 .. Natural'Last loop
      if Is_Disarium (N) then
         Count := Count + 1;
         Ada.Text_IO.Put (N'Image);
      end if;
      exit when Count = Disarium_Count;
   end loop;
end Disarium_Numbers;
Output:
 0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798

ALGOL 60

Works with: GNU Marst version Any - tested with release 2.7
Translation of: ALGOL W
begin comment find some Disarium numbers
                 - numbers whose digit position-power sums are equal to the
                   number, e.g. 135 = 1^1 + 3^2 + 5^3;
    integer array power [ 1 : 9, 0 : 9 ];
    integer count, powerOfTen, length, n, d;
    comment compute the nth powers of 0-9;
    for d := 0 step 1 until 9 do power[ 1, d ] := d;
    for n := 2 step 1 until 9 do begin
        power[ n, 0 ] := 0;
        for d := 1 step 1 until 9 do power[ n, d ] := power[ n - 1, d ] * d
    end n;
    comment print the first few Disarium numbers;
    count      :=  0;
    powerOfTen := 10;
    length     :=  1;
    n          := -1;
    for n := n + 1 while count < 19 do begin
        integer v, dps, p;
        if n = powerOfTen then begin
            comment the number of digfits just increased;
            powerOfTen := powerOfTen * 10;
            length     := length     +  1
        end;
        comment form the digit power sum;
        v   := n;
        dps := 0;
        for p := length step -1 until 1 do begin
            dps := dps + power[ p, v - ( ( v % 10 ) * 10 ) ];
            v   := v % 10
        end p;
        if dps = n then begin
            comment n is Disarium;
            count := count + 1;
            outinteger( 1, n )
        end
    end n
end
Output:
0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798

ALGOL 68

Finds the first 19 Disarium numbers - to find the 20th would require a lot more time and also the table of digit powers would need to be increased to at least 20th powers (and 64 bit integers would be required).

BEGIN # find some Disarium numbers - numbers whose digit position-power sums  #
      # are equal to the number, e.g. 135 = 1^1 + 3^2 + 5^3                   #
    # compute the nth powers of 0-9                                           #
    [ 1 : 9, 0 : 9 ]INT power;
    FOR d FROM 0 TO 9 DO power[ 1, d ] := d OD;
    FOR n FROM 2 TO 9 DO
        power[ n, 0 ] := 0;
        FOR d TO 9 DO
            power[ n, d ] := power[ n - 1, d ] * d
        OD
    OD;
    # print the first few Disarium numbers                                    #
    INT max disarium  = 19;
    INT count        :=  0;
    INT power of ten := 10;
    INT length       :=  1;
    FOR n FROM 0 WHILE count < max disarium DO
        IF n = power of ten THEN
            # the number of digits just increased                             #
            power of ten *:= 10;
            length       +:=  1
        FI;
        # form the digit power sum                                            #
        INT v   := n;
        INT dps := 0;
        FOR p FROM length BY -1 TO 1 DO
            dps +:= power[ p, v MOD 10 ];
            v OVERAB 10
        OD;
        IF dps = n THEN
            # n is Disarium                                                   #
            count +:= 1;
            print( ( " ", whole( n, 0 ) ) )
        FI
    OD
END
Output:
 0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798

ALGOL W

Translation of: ALGOL 68
begin % find some Disarium numbers - numbers whose digit position-power sums  %
      % are equal to the number, e.g. 135 = 1^1 + 3^2 + 5^3                   %
    integer array power ( 1 :: 9, 0 :: 9 );
    integer MAX_DISARIUM;
    integer count, powerOfTen, length, n;
    % compute the nth powers of 0-9                                           %
    for d := 0 until 9 do power( 1, d ) := d;
    for n := 2 until 9 do begin
        power( n, 0 ) := 0;
        for d := 1 until 9 do power( n, d ) := power( n - 1, d ) * d
    end for_n;
    % print the first few Disarium numbers                                    %
    MAX_DISARIUM := 19;
    count        :=  0;
    powerOfTen   := 10;
    length       :=  1;
    n            :=  0;
    while count < MAX_DISARIUM do begin
        integer v, dps;
        if n = powerOfTen then begin
            % the number of digits just increased                             %
            powerOfTen := powerOfTen * 10;
            length     := length     +  1
        end if_m_eq_powerOfTen ;
        % form the digit power sum                                            %
        v   := n;
        dps := 0;
        for p := length step -1 until 1 do begin
            dps := dps + power( p, v rem 10 );
            v   := v div 10;
        end FOR_P;
        if dps = n then begin
            % n is Disarium                                                   %
            count := count + 1;
            writeon( i_w := 1, s_w := 0, " ", n )
        end if_dps_eq_n ;
        n := n + 1
    end
end.
Output:
 0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798

Amazing Hopper

#include <basico.h>

#proto encontrarunDisariumpara(_X_)
#synon _encontrarunDisariumpara   siencontréunDisarium

algoritmo    
    decimales '0'
    iterar para ( n=3000000, n, --n )
         si encontré un Disarium 'n', entonces{
             imprimir( #(utf8("El número ")),n," es Disarium\n")
         }
    siguiente
terminar

subrutinas

encontrar un Disarium para (n)

    i=0
    n, obtener tamaño parte entera, mover a 'i'
    m=0, tn=n, d=0
    iterar mientras ( tn )
         último dígito de 'tn', mover a 'd,tn'
         d, elevado a 'i', más 'm'
         mover a 'm'
         --i
    reiterar

retornar ' #(m==n) '
Output:
El número 2646798 es Disarium
El número 2427 es Disarium
El número 1676 es Disarium
El número 1306 es Disarium
El número 598 es Disarium
El número 518 es Disarium
El número 175 es Disarium
El número 135 es Disarium
El número 89 es Disarium
El número 9 es Disarium
El número 8 es Disarium
El número 7 es Disarium
El número 6 es Disarium
El número 5 es Disarium
El número 4 es Disarium
El número 3 es Disarium
El número 2 es Disarium
El número 1 es Disarium

APL

((/⍨)(⊢=(¨(+/*)))¨)0,⍳3000000
Output:
0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798

AppleScript

This returns the first 19 Disarium numbers.

on isDisarium(n)
    set temp to n
    set digitCount to 1
    repeat while (temp > 9)
        set temp to temp div 10
        set digitCount to digitCount + 1
    end repeat
    set temp to n
    set sum to 0
    repeat with position from digitCount to 2 by -1
        set sum to sum + (temp mod 10) ^ position
        set temp to temp div 10
    end repeat
    
    return (sum + temp = n)
end isDisarium

local Disaria, n
set Disaria to {}
set n to 0
repeat until ((count Disaria) = 19)
    if (isDisarium(n)) then set end of Disaria to n
    set n to n + 1
end repeat

return Disaria
Output:
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 89, 135, 175, 518, 598, 1306, 1676, 2427, 2646798}

Arturo

disarium?: function [x][
    j: 0
    psum: sum map digits x 'dig [
        j: j + 1
        dig ^ j
    ]
    return psum = x
]

cnt: 0
i: 0
while [cnt < 18][
    if disarium? i [
        print i
        cnt: cnt + 1
    ]
    i: i + 1
]
Output:
0
1
2
3
4
5
6
7
8
9
89
135
175
518
598
1306
1676
2427

AWK

# syntax: GAWK -f DISARIUM_NUMBERS.AWK
BEGIN {
    stop = 19
    printf("The first %d Disarium numbers:\n",stop)
    while (count < stop) {
      if (is_disarium(n)) {
        printf("%d ",n)
        count++
      }
      n++
    }
    printf("\n")
    exit(0)
}
function is_disarium(n,  leng,sum,x) {
    x = n
    leng = length(n)
    while (x != 0) {
      sum += (x % 10) ^ leng
      leng--
      x = int(x/10)
    }
    return((sum == n) ? 1 : 0)
}
Output:
The first 19 Disarium numbers:
0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798

BASIC

BASIC256

function isDisarium(n)
	digitos = length(string(n))
	suma = 0
	x = n
	while x <> 0
		suma += (x % 10) ^ digitos
		digitos -= 1
		x = x \ 10
	end while
	if suma = n then return True else return False
end function

limite = 19
cont = 0 : n = 0
print "The first"; limite; " Disarium numbers are:"
while cont < limite
	if isDisarium(n) then
		print n; " ";
		cont += 1
	endif
	n += 1
end while
end
Output:
Same as FreeBASIC entry.

Chipmunk Basic

Works with: Chipmunk Basic version 3.6.4
100 cls
110 sub isdisarium(n)
120   digitos = len(str$(n))
130   suma = 0
140   x = n
150   while x <> 0
160     r = (x mod 10)
170     suma = suma+(r^digitos)
180     digitos = digitos-1
190     x = int(x/10)
200   wend
210   if suma = n then isdisarium = true else isdisarium = false
220 end sub
230 '
240 limite = 19
250 cnt = 0
260 n = 0
270 print "The first ";limite;" Disarium numbers are:"
280 while cnt < limite
290   if isdisarium(n) then
300     print n;" ";
310     cnt = cnt+1
320   endif
330   n = n+1
340 wend
350 end
Output:
Same as FreeBASIC entry.

FreeBASIC

#define limite 19

Function isDisarium(n As Integer) As Boolean
    Dim As Integer digitos = Len(Str(n))
    Dim As Integer suma = 0, x = n
    While x <> 0
        suma += (x Mod 10) ^ digitos
        digitos -= 1
        x \= 10
    Wend
    Return Iif(suma = n, True, False)
End Function

Dim As Integer cont = 0, n = 0, i
Print "The first"; limite; " Disarium numbers are:"
Do While cont < limite
    If isDisarium(n) Then
        Print n; " ";
        cont += 1
    End If
    n += 1
Loop
Sleep
Output:
Same as Python entry.

Run BASIC

function isDisarium(n)
    digitos = len(str$(n))
    suma = 0 : x = n
    while x <> 0
        r = (x mod 10)
        suma = suma + (r ^ digitos)
        digitos = digitos - 1
        x = int(x / 10)
    wend
    if suma = n then isDisarium = 1 else isDisarium = 0
end function

limite = 18 : cont = 0 : n = 0
print "The first"; limite; " Disarium numbers are:"
while cont < limite
    if isDisarium(n) = 1 then
        print n; " ";
        cont = cont + 1
    end if
    n = n + 1
wend
Output:
 0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427

True BASIC

FUNCTION isDisarium(n)
    LET digitos = LEN(str$(n))
    LET suma = 0
    LET x = n
    DO WHILE x <> 0
        LET r = REMAINDER(x, 10)
        LET suma = suma + (r ^ digitos)
        LET digitos = digitos - 1
        LET x = INT(x / 10)
    LOOP
    IF suma = n THEN LET isDisarium = 1 ELSE LET isDisarium = 0
END FUNCTION

LET limite = 18
LET cont = 0
LET n = 0
PRINT "The first"; limite; " Disarium numbers are:"
DO WHILE cont < limite
    IF isDisarium(n) = 1 THEN
        PRINT n; " ";
        LET cont = cont + 1
    END IF
    LET n = n + 1
LOOP
END
Output:
 0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427

PureBasic

Procedure isDisarium(n.i)
  digitos.i = Len(Str(n))
  suma.i = 0
  x.i = n
  While x <> 0
    r.i = (x % 10)
    suma + Pow(r, digitos)
    digitos - 1
    x / 10
  Wend
  If suma = n 
    ProcedureReturn #True 
  Else 
    ProcedureReturn #False
  EndIf
EndProcedure

OpenConsole()
limite.i = 19
cont.i = 0
n.i = 0
PrintN("The first" + Str(limite) + " Disarium numbers are:")
While cont < limite
  If isDisarium(n)
    Print(Str(n) + #TAB$)
    cont + 1
  EndIf
  n + 1
Wend
Input()
CloseConsole()
Output:
Same as FreeBASIC entry.

e>

Yabasic

limite = 18 : cont = 0 : n = 0
print "The first", limite, " Disarium numbers are:"
while cont < limite
    if isDisarium(n) then
        print n, " ";
        cont = cont + 1
    fi
    n = n + 1
wend
end

sub isDisarium(n)
    digitos = len(str$(n))
    suma = 0 : x = n
    while x <> 0
        r = mod(x, 10)
        suma = suma + (r ^ digitos)
        digitos = digitos - 1
        x = int(x / 10)
    wend
    if suma = n then return True else return False : fi
end sub
Output:
 0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427

bc

define is_disarium (num) {
    n = num
    sum = 0
    len = length(n)
    while (n > 0) {
        sum += (n % 10) ^ len
        n = n/10
        len -= 1
    }
    return (sum == num)
}

count = 0
i = 0
while (count < 19) {
    if (is_disarium(i)) {
        print i, "\n"
        count += 1
    }
    i += 1
}
quit
Output:
0
1
2
3
4
5
6
7
8
9
89
135
175
518
598
1306
1676
2427
2646798


BCPL

get "libhdr"

let length(n)   = n < 10 -> 1,
                  length(n/10) + 1

let pow(b, e)   = e = 0 -> 1,
                  b * pow(b, e-1)
    
let dps(n)      = dpsl(n, length(n))
and dpsl(n, p)  = n = 0 -> 0,
                  pow(n rem 10, p) + dpsl(n/10, p-1)
    
let disarium(n) = dps(n) = n

let start() be
    for n=0 to 2500 if disarium(n) 
        do writef("%N*N", n)
Output:
0
1
2
3
4
5
6
7
8
9
89
135
175
518
598
1306
1676
2427

BQN

Digits         {𝕊 0: ⟨⟩; (𝕊⌊𝕩÷10)10|𝕩}
DigitPowerSum  (+´1+↕)Digits
Disarium       ⊢=DigitPowerSum

Disarium¨/ 2500
Output:
⟨ 0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 ⟩

C

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int power (int base, int exponent) {
    int result = 1;
    for (int i = 1; i <= exponent; i++) {
        result *= base;
    }
    return result;
}

int is_disarium (int num) {
    int n = num;
    int sum = 0;
    int len = n <= 9 ? 1 : floor(log10(n)) + 1;
    while (n > 0) {
        sum += power(n % 10, len);
        n /= 10;
        len--;
    }

    return num == sum;
}

int main() {
    int count = 0;
    int i = 0;
    while (count < 19) {
        if (is_disarium(i)) {
            printf("%d ", i);
            count++;
        }
        i++;
    }
    printf("%s\n", "\n");
}
Output:
0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798

C#

Translation of: Java
using System;

class DisariumNumbers {
    // Method to check if a number is a Disarium number
    public static bool IsDisarium(int num) {
        int n = num;
        int len = num.ToString().Length;
        int sum = 0;
        int i = 1;
        while (n > 0) {
            // C# does not support implicit conversion from double to int, so we explicitly convert the result of Math.Pow to int
            sum += (int)Math.Pow(n % 10, len - i + 1);
            n /= 10;
            i++;
        }
        return sum == num;
    }

    static void Main(string[] args) {
        int i = 0;
        int count = 0;
        // Find and print the first 19 Disarium numbers
        while (count <= 18) {
            if (IsDisarium(i)) {
                Console.Write($"{i} ");
                count++;
            }
            i++;
        }
        Console.WriteLine();
    }
}
Output:
0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798 

C++

#include <vector>
#include <iostream>
#include <cmath>
#include <algorithm>

std::vector<int> decompose( int n ) {
   std::vector<int> digits ;
   while ( n != 0 ) {
      digits.push_back( n % 10 ) ;
      n /= 10 ;
   }
   std::reverse( digits.begin( ) , digits.end( ) ) ;
   return digits ;
}

bool isDisarium( int n ) {
   std::vector<int> digits( decompose( n ) ) ;
   int exposum = 0 ;
   for ( int i = 1 ; i < digits.size( ) + 1 ; i++ ) {
      exposum += static_cast<int>( std::pow(
               static_cast<double>(*(digits.begin( ) + i - 1 )) ,
               static_cast<double>(i) )) ;
   }
   return exposum == n ;
}

int main( ) {
   std::vector<int> disariums ;
   int current = 0 ;
   while ( disariums.size( ) != 18 ){
      if ( isDisarium( current ) ) 
         disariums.push_back( current ) ;
      current++ ;
   }
   for ( int d : disariums ) 
      std::cout << d << " " ;
   std::cout << std::endl ;
   return 0 ;
}
Output:
0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427

CLU

is_disarium = proc (n: int) returns (bool)
    digits: array[int] := array[int]$[]
    number: int := n
    while n > 0 do
        array[int]$addl(digits, n//10)
        n := n / 10
    end
    array[int]$set_low(digits, 1)
    digit_power_sum: int := 0
    for i: int in array[int]$indexes(digits) do
        digit_power_sum := digit_power_sum + digits[i] ** i
    end
    return(digit_power_sum = number)
end is_disarium

disaria = iter (amount: int) yields (int)
    n: int := 0
    while amount > 0 do
        if is_disarium(n) then
            amount := amount - 1
            yield(n)
        end
        n := n + 1
    end
end disaria

start_up = proc ()
    po: stream := stream$primary_output()
    for n: int in disaria(19) do
        stream$putl(po, int$unparse(n))
    end
end start_up
Output:
0
1
2
3
4
5
6
7
8
9
89
135
175
518
598
1306
1676
2427
2646798

COBOL

       IDENTIFICATION DIVISION.
       PROGRAM-ID. DISARIUM.
       
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 VARIABLES.
          03 CANDIDATE     PIC 9(9).
          03 DIGITS        PIC 9 OCCURS 9 TIMES, REDEFINES CANDIDATE.
          03 IDX           PIC 99.
          03 EXPONENT      PIC 99.
          03 DGT-POWER     PIC 9(9).
          03 DGT-POWER-SUM PIC 9(9).
          03 CAND-OUT      PIC Z(8)9.
          03 AMOUNT        PIC 99 VALUE 18.
          
       PROCEDURE DIVISION.
       BEGIN.
           PERFORM DISARIUM-TEST VARYING CANDIDATE FROM ZERO BY 1
           UNTIL AMOUNT IS ZERO.
           STOP RUN.
        
       DISARIUM-TEST.
           MOVE ZERO TO DGT-POWER-SUM.
           MOVE 1 TO EXPONENT, IDX.
           INSPECT CANDIDATE TALLYING IDX FOR LEADING ZEROES.
           PERFORM ADD-DIGIT-POWER UNTIL IDX IS GREATER THAN 9.
           IF DGT-POWER-SUM IS EQUAL TO CANDIDATE,
               MOVE CANDIDATE TO CAND-OUT,
               DISPLAY CAND-OUT,
               SUBTRACT 1 FROM AMOUNT.
           
       ADD-DIGIT-POWER.
           COMPUTE DGT-POWER = DIGITS(IDX) ** EXPONENT.
           ADD DGT-POWER TO DGT-POWER-SUM.
           ADD 1 TO EXPONENT.
           ADD 1 TO IDX.
Output:
        0
        1
        2
        3
        4
        5
        6
        7
        8
        9
       89
      135
      175
      518
      598
     1306
     1676
     2427

Comal

0010 FUNC dps#(n#) CLOSED 
0020   DIM digits#(10)
0030   length#:=0
0040   rest#:=n#
0050   WHILE rest#>0 DO 
0060     length#:+1
0070     digits#(length#):=rest# MOD 10
0080     rest#:=rest# DIV 10
0090   ENDWHILE 
0100   sum#:=0
0110   FOR i#:=1 TO length# DO 
0120     sum#:+digits#(i#)^(length#-i#+1)
0130   ENDFOR i#
0140   RETURN sum#
0150 ENDFUNC dps#
0160 //
0170 amount#:=18
0180 num#:=0
0190 WHILE amount#>0 DO 
0200   IF dps#(num#)=num# THEN 
0210     amount#:-1
0220     PRINT num#
0230   ENDIF 
0240   num#:+1
0250 ENDWHILE 
0260 PRINT 
0270 END
Output:
0
1
2
3
4
5
6
7
8
9
89
135
175
518
598
1306
1676
2427

Cowgol

include "cowgol.coh";

sub pow(base: uint8, exp: uint8): (power: uint32) is
    power := 1;
    while exp > 0 loop
        power := power * base as uint32;
        exp := exp - 1;
    end loop;
end sub;

sub digit_power_sum(n: uint32): (dps: uint32) is
    var digits: uint8[10]; # 2**32 has 10 digits
    var digit := &digits[0];
    var length: uint8 := 0;
    
    while n > 0 loop
        [digit] := (n % 10) as uint8;
        digit := @next digit;
        length := length + 1;
        n := n / 10;
    end loop;
    
    dps := 0;
    var power: uint8 := 1;
    while power <= length loop
        digit := @prev digit;
        dps := dps + pow([digit], power);
        power := power + 1;
    end loop;
end sub;

var amount: uint8 := 19;
var candidate: uint32 := 0;
while amount > 0 loop
    if digit_power_sum(candidate) == candidate then
        amount := amount - 1;
        print_i32(candidate);
        print_nl();
    end if;
    candidate := candidate + 1;
end loop;
Output:
0
1
2
3
4
5
6
7
8
9
89
135
175
518
598
1306
1676
2427
2646798

Delphi

Works with: Delphi version 6.0

Finds the first 19 numbers in 425 miliseconds. It uses a look up table for the powers and tests about 5 million numbers per second. However, this is not fast enough to find the 20th number. By my calculation, at this speed, it would only take 77,000 years. In other words, the brute force method can't be used to find the 20th number.

{Table to speed up calculating powers. Contains all the powers
of the digits 0..9 raised to the 0..21 power}

const PowersTable: array [0..21,0..9] of int64 = (
($01,$01,$01,$01,$01,$01,$01,$01,$01,$01),
($00,$01,$02,$03,$04,$05,$06,$07,$08,$09),
($00,$01,$04,$09,$10,$19,$24,$31,$40,$51),
($00,$01,$08,$1B,$40,$7D,$D8,$157,$200,$2D9),
($00,$01,$10,$51,$100,$271,$510,$961,$1000,$19A1),
($00,$01,$20,$F3,$400,$C35,$1E60,$41A7,$8000,$E6A9),
($00,$01,$40,$2D9,$1000,$3D09,$B640,$1CB91,$40000,$81BF1),
($00,$01,$80,$88B,$4000,$1312D,$44580,$C90F7,$200000,$48FB79),
($00,$01,$100,$19A1,$10000,$5F5E1,$19A100,$57F6C1,$1000000,$290D741),
($00,$01,$200,$4CE3,$40000,$1DCD65,$99C600,$267BF47,$8000000,$17179149),
($00,$01,$400,$E6A9,$100000,$9502F9,$39AA400,$10D63AF1,$40000000,$CFD41B91),
($00,$01,$800,$2B3FB,$400000,$2E90EDD,$159FD800,$75DB9C97,$200000000,$74E74F819),
($00,$01,$1000,$81BF1,$1000000,$E8D4A51,$81BF1000,$339014821,$1000000000,$41C21CB8E1),
($00,$01,$2000,$1853D3,$4000000,$48C27395,$30A7A6000,$168F08F8E7,$8000000000,$24FD3027FE9),
($00,$01,$4000,$48FB79,$10000000,$16BCC41E9,$123EDE4000,$9DE93ECE51,$40000000000,$14CE6B167F31),
($00,$01,$8000,$DAF26B,$40000000,$71AFD498D,$6D79358000,$45160B7A437,$200000000000,$BB41C3CA78B9),
($00,$01,$10000,$290D741,$100000000,$2386F26FC1,$290D7410000,$1E39A5057D81,$1000000000000,$6954FE21E3E81),
($00,$01,$20000,$7B285C3,$400000000,$B1A2BC2EC5,$F650B860000,$D39383266E87,$8000000000000,$3B3FCEF3103289),
($00,$01,$40000,$17179149,$1000000000,$3782DACE9D9,$5C5E45240000,$5C908960D05B1,$40000000000000,$2153E468B91C6D1),
($00,$01,$80000,$4546B3DB,$4000000000,$1158E460913D,$22A359ED80000,$287F3C1A5B27D7,$200000000000000,$12BF307AE81FFD59),
($00,$01,$100000,$CFD41B91,$10000000000,$56BC75E2D631,$CFD41B9100000,$11B7AA4B87E16E1,$1000000000000000,$A8B8B452291FE821),
($00,$01,$200000,$26F7C52B3,$40000000000,$1B1AE4D6E2EF5,$4DEF8A56600000,$7C05A810B72A027,$8000000000000000,$EE7E56E3721F2929));


function GetPower(X,Y: integer): int64;
{Extract power from table}
begin
Result:=PowersTable[Y,X];
end;


function IsDisarium(N: integer): boolean;
{Sum all powers of the digits raised to position power}
var S: string;
var I,J: integer;
var Sum: int64;
begin
Sum:=0;
S:=IntToStr(N);
for I:=1 to Length(S) do
	begin
	Sum:=Sum+GetPower(byte(S[I])-$30,I);
	end;
Result:=Sum=N;
end;


procedure ShowDisariumNumbers(Memo: TMemo);
{Show Disarium numbers up to specified limit}
{Processes about 5 million numbers per second}
var I,Cnt: int64;
begin
Cnt:=0;
I:=0;
while I<High(int64) do
	begin
	if IsDisarium(I) then
		begin
		Inc(Cnt);
		Memo.Lines.Add(IntToStr(Cnt)+': '+IntToStr(I));
		if Cnt>=19 then break;
		end;
	Inc(I);
	end;
end;
Output:
1: 0
2: 1
3: 2
4: 3
5: 4
6: 5
7: 6
8: 7
9: 8
10: 9
11: 89
12: 135
13: 175
14: 518
15: 598
16: 1306
17: 1676
18: 2427
19: 2646798


D

import std.stdio;
import std.math;
import std.conv;

bool is_disarium(int num) {
    int n = num;
    int sum = 0;
    ulong len = to!string(num, 10).length;
    while (n > 0) {
        sum += pow(n % 10, len);
        n /= 10;
        len--;
    }
    return num == sum;
}
void main() {
    int i = 0;
    int count = 0;
    while (count < 19) {
        if (is_disarium(i)) {
            printf("%d ", i);
            count++;
        }
        i++;
    }
    writeln(" ");
}
Output:
0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798

Dart

import "dart:math";
import "dart:io";
void main() {
    var count = 0;
    var i = 0;
    while (count < 19) {
        if (is_disarium(i)) {
            stdout.write("$i ");
            count++;
        }
        i++;
    }
}

bool is_disarium(numb) {
    var n = numb;
    var len = n.toString().length;
    var sum = 0;
    while (n > 0) {
        sum += (pow(n % 10, len)).toInt();
        n = (n / 10).toInt();
        len--;
    }
    return numb == sum;
}
Output:
0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798

dc

[10/ll1+sld0<Lx] sL [d10%ll^ls+ss10/ll1-sld0<Dx] sD[lc1+sc
    lnp]sP[Osslisnln0sllLx0ssclnlDxlsln=Pli1+silc18>Ix] sI0si0sclIx
Output:
$ dc -e '[10/ll1+sld0<Lx] sL [d10%ll^ls+ss10/ll1-sld0<Dx] sD[lc1+sc
lnp]sP[Osslisnln0sllLx0ssclnlDxlsln=Pli1+silc18>Ix] sI0si0sclIx'
0
1
2
3
4
5
6
7
8
9
89
135
175
518
598
1306
1676
2427

Note that I printed out only 18 disarium numbers because it is getting very slow.

Explained version of the above:

# Macro for computing the input number length
[10      # pushes 10 to stack
 /       # divides input by 10 and stores result on stack
 ll      # push length on stack
 1+      # add one to stack (length)
 # p     # prints intermediate length (for debugging)
 sl      # saves length to register l
 d       # duplicates value (number) on top of stack
 0       # pushes 0 to stack
 <Lx     # executes length macro (L) if number > 0
] sL     # end of length macro, store it in L

# is Disarium macro
[d      # duplicates value (number) on top of stack
10      # pushes 10 to stack
%       # pushes (number % 10) to stack
ll      # pushes length to stack
^       # computes (n % 10) ^ len
ls      # pushes sum to stack
+ss     # computes new sum and stores it in s
10/     # integer division number / 10
ll      # pushes length on stack
1-      # subtract 1 froml length
sl      # stores new length in l
d       # duplicates value (number) on top of stack
0       # pushes 0 to stack
<Dx     # executes recursively disarium macro (D) if number > 0
] sD    # stores disarium macro in D

# Printing and counting macro
[lc1+sc # increments disarium number counter
lnp     # print number
]sP # Stores printing macro in P

# Iteration macro
[Oss    # stores 0 in register s (sum)
li sn   # Stores iteration variable in number register
ln      # pushes number to stack
0sl     # stores 0 in register l (length)
lLx     # runs the length macro
0ss     # inititialize sum to 0
cln     # clear stack and pushes number onto it
# llp   # print the length
lDx     # runs the Disarium macro once
lsln    # pushes sum and number
=P      # runs the printing macro if numbers are equal
li      # loads iteration variable
1+si    # increments iteration variable
lc18    # pushes counter and 18 on stack
>Ix     # runs recursively iteration macro if counter < 18
] sI    # end of iteration macro, stores it in I 

# Main
0si     # Initiate iteration variable
0sc     # Initiate disarium numbers counter
lIx     # running iteration macro the first time

Draco

proc nonrec pow(byte base, exp) word:
    word p;
    p := 1;
    while exp>0 do
        p := p*base;
        exp := exp-1
    od;
    p
corp

proc nonrec disarium(word n) bool:
    [5]byte digits;
    short i, len;
    word input_n, dps;
    
    dps := 0;
    i := 0;
    input_n := n;
    while n > 0 do
        digits[i] := n % 10;
        n := n / 10;
        i := i + 1
    od;
    
    len := i;
    for i from 0 upto len-1 do
        dps := dps + pow(digits[i], len-i)
    od;
    dps = input_n
corp

proc nonrec main() void:
    word n;
    for n from 0 upto 2500 do
        if disarium(n) then writeln(n:5) fi
    od
corp
Output:
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
   89
  135
  175
  518
  598
 1306
 1676
 2427

EasyLang

func disarium x .
   h = x
   while h > 0
      d[] &= h mod 10
      h = h div 10
   .
   for i = 1 to len d[]
      h += pow d[i] (len d[] - i + 1)
   .
   return if h = x
.
while count < 19
   if disarium n = 1
      count += 1
      print n
   .
   n += 1
.

Factor

Works with: Factor version 0.99 2021-06-02
USING: io kernel lists lists.lazy math.ranges math.text.utils
math.vectors prettyprint sequences ;

: disarium? ( n -- ? )
    dup 1 digit-groups dup length 1 [a,b] v^ sum = ;

: disarium ( -- list ) 0 lfrom [ disarium? ] lfilter ;

19 disarium ltake [ pprint bl ] leach nl
Output:
0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798 

FOCAL

01.10 F N=0,2500;D 2
01.20 Q

02.10 D 3
02.20 I (N-S)2.4,2.3,2.4
02.30 T %5,N,!
02.40 R

03.10 S Z=N;S L=0
03.20 G 3.7
03.30 S K=FITR(Z/10)
03.40 S L=L+1
03.50 S D(L)=Z-K*10
03.60 S Z=K
03.70 I (-Z)3.3
03.80 S S=0
03.90 F I=1,L;S S=S+D(L-I+1)^I
Output:
=     0
=     1
=     2
=     3
=     4
=     5
=     6
=     7
=     8
=     9
=    89
=   135
=   175
=   518
=   598
=  1306
=  1676
=  2427

Forth

: pow 1 swap 0 ?do over * loop nip ;
: len 1 swap begin dup 10 >= while 10 / swap 1+ swap repeat drop ;

: dps 0 swap dup len 
  begin dup while
    swap 10 /mod swap
    2 pick pow
    3 roll +
    rot 1- rot
    swap
  repeat
  2drop 
;

: disarium dup dps = ; 
: disaria 2700000 0 ?do i disarium if i . cr then loop ; 

disaria
bye
Output:
0 
1 
2 
3 
4 
5 
6 
7 
8 
9 
89 
135 
175 
518 
598 
1306 
1676 
2427 
2646798 

FutureBasic

long c = 0, n = 0, t, i
CFStringRef s

while ( c < 18 )
  s = fn StringWithFormat(@"%ld",n)
  t = 0
  for i = 0 to len(s) - 1
    t += intVal(mid(s,i,1))^(i+1)
  next
  if ( t == n )
    print n
    c++
  end if
  n++
wend

HandleEvents

Go

Translation of: Wren

A translation of Version 2.

Although Go has native unsigned 64 bit arithmetic, much quicker than I was expecting at a little under a minute.

package main

import (
    "fmt"
    "strconv"
)

const DMAX = 20  // maximum digits
const LIMIT = 20 // maximum number of disariums to find

func main() {
    // Pre-calculated exponential and power serials
    EXP := make([][]uint64, 1+DMAX)
    POW := make([][]uint64, 1+DMAX)

    EXP[0] = make([]uint64, 11)
    EXP[1] = make([]uint64, 11)
    POW[0] = make([]uint64, 11)
    POW[1] = make([]uint64, 11)
    for i := uint64(1); i <= 10; i++ {
        EXP[1][i] = i
    }
    for i := uint64(1); i <= 9; i++ {
        POW[1][i] = i
    }
    POW[1][10] = 9

    for i := 2; i <= DMAX; i++ {
        EXP[i] = make([]uint64, 11)
        POW[i] = make([]uint64, 11)
    }
    for i := 1; i < DMAX; i++ {
        for j := 0; j <= 9; j++ {
            EXP[i+1][j] = EXP[i][j] * 10
            POW[i+1][j] = POW[i][j] * uint64(j)
        }
        EXP[i+1][10] = EXP[i][10] * 10
        POW[i+1][10] = POW[i][10] + POW[i+1][9]
    }

    // Digits of candidate and values of known low bits
    DIGITS := make([]int, 1+DMAX) // Digits form
    Exp := make([]uint64, 1+DMAX) // Number form
    Pow := make([]uint64, 1+DMAX) // Powers form

    var exp, pow, min, max uint64
    start := 1
    final := DMAX
    count := 0
    for digit := start; digit <= final; digit++ {
        fmt.Println("# of digits:", digit)
        level := 1
        DIGITS[0] = 0
        for {
            // Check limits derived from already known low bit values
            // to find the most possible candidates
            for 0 < level && level < digit {
                // Reset path to try next if checking in level is done
                if DIGITS[level] > 9 {
                    DIGITS[level] = 0
                    level--
                    DIGITS[level]++
                    continue
                }

                // Update known low bit values
                Exp[level] = Exp[level-1] + EXP[level][DIGITS[level]]
                Pow[level] = Pow[level-1] + POW[digit+1-level][DIGITS[level]]

                // Max possible value
                pow = Pow[level] + POW[digit-level][10]

                if pow < EXP[digit][1] { // Try next since upper limit is invalidly low
                    DIGITS[level]++
                    continue
                }

                max = pow % EXP[level][10]
                pow -= max
                if max < Exp[level] {
                    pow -= EXP[level][10]
                }
                max = pow + Exp[level]

                if max < EXP[digit][1] { // Try next since upper limit is invalidly low
                    DIGITS[level]++
                    continue
                }

                // Min possible value
                exp = Exp[level] + EXP[digit][1]
                pow = Pow[level] + 1

                if exp > max || max < pow { // Try next since upper limit is invalidly low
                    DIGITS[level]++
                    continue
                }

                if pow > exp {
                    min = pow % EXP[level][10]
                    pow -= min
                    if min > Exp[level] {
                        pow += EXP[level][10]
                    }
                    min = pow + Exp[level]
                } else {
                    min = exp
                }

                // Check limits existence
                if max < min {
                    DIGITS[level]++ // Try next number since current limits invalid
                } else {
                    level++ // Go for further level checking since limits available
                }
            }

            // All checking is done, escape from the main check loop
            if level < 1 {
                break
            }

            // Finally check last bit of the most possible candidates
            // Update known low bit values
            Exp[level] = Exp[level-1] + EXP[level][DIGITS[level]]
            Pow[level] = Pow[level-1] + POW[digit+1-level][DIGITS[level]]

            // Loop to check all last bits of candidates
            for DIGITS[level] < 10 {
                // Print out new Disarium number
                if Exp[level] == Pow[level] {
                    s := ""
                    for i := DMAX; i > 0; i-- {
                        s += fmt.Sprintf("%d", DIGITS[i])
                    }
                    n, _ := strconv.ParseUint(s, 10, 64)
                    fmt.Println(n)
                    count++
                    if count == LIMIT {
                        fmt.Println("\nFound the first", LIMIT, "Disarium numbers.")
                        return
                    }
                }

                // Go to followed last bit candidate
                DIGITS[level]++
                Exp[level] += EXP[level][1]
                Pow[level]++
            }

            // Reset to try next path
            DIGITS[level] = 0
            level--
            DIGITS[level]++
        }
        fmt.Println()
    }
}
Output:
# of digits: 1
0
1
2
3
4
5
6
7
8
9

# of digits: 2
89

# of digits: 3
135
175
518
598

# of digits: 4
1306
1676
2427

# of digits: 5

# of digits: 6

# of digits: 7
2646798

# of digits: 8

# of digits: 9

# of digits: 10

# of digits: 11

# of digits: 12

# of digits: 13

# of digits: 14

# of digits: 15

# of digits: 16

# of digits: 17

# of digits: 18

# of digits: 19

# of digits: 20
12157692622039623539

Found the first 20 Disarium numbers.

real	0m57.430s
user	0m57.420s
sys	0m0.105s

Haskell

module Disarium 
   where
import Data.Char ( digitToInt)

isDisarium :: Int -> Bool
isDisarium n = (sum $ map (\(c , i ) -> (digitToInt c ) ^ i )
 $ zip ( show n ) [1 , 2 ..]) == n

solution :: [Int]
solution = take 18 $ filter isDisarium [0, 1 ..]
Output:
[0,1,2,3,4,5,6,7,8,9,89,135,175,518,598,1306,1676,2427]

J

digits=: "."0@":
disarium=: = (+/@:^ #\)@digits"0

   I. disarium i. 27e5
0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798

Java

import java.lang.Math;

public class DisariumNumbers {
    public static boolean is_disarium(int num) {
        int n = num;
        int len = Integer.toString(n).length();
        int sum = 0;
        int i = 1;
        while (n > 0) {
            sum += Math.pow(n % 10, len - i + 1);
            n /= 10;
            i ++;
        }
        return sum  == num;
    }

    public static void main(String[] args) {
        int i = 0;
        int count = 0;
        while (count <= 18) {
            if (is_disarium(i)) {
                System.out.printf("%d ", i);
                count++;
            }
            i++;
        }
        System.out.printf("%s", "\n");
    }
}
Output:
0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798

JavaScript

function is_disarium (num) {
    let n = num
    let len = n.toString().length
    let sum = 0
    while (n > 0) {
        sum += (n % 10) ** len
        n = parseInt(n / 10, 10)
        len--
    }
    return num == sum
}
let count = 0
let i = 1
while (count < 18) {
    if (is_disarium(i)) {
        process.stdout.write(i + " ")
        count++
    }
    i++
}
Output:
1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798

jq

Works with: jq

Also works with gojq, the Go implementation of jq

The naive algorithm is good enough to find the first 19 disarium numbers, ergo `limit(19; ...)` below.

# To take advantage of gojq's arbitrary-precision integer arithmetic:
def power($in;$b): reduce range(0;$b) as $i (1; . * $in);

# $n is assumed to be a non-negative integer
def is_disarium:
  . as $n
  | {$n, sum: 0, len: (tostring|length) }
  | until (.n == 0;
      .sum += power(.n % 10; .len)
      | .n = (.n/10 | floor)
      | .len -= 1 )
  | .sum == $n ;

# Emit a stream ...
def disariums:
  range(0; infinite) | select(is_disarium);

limit(19; disariums)
Output:
0
...
2646798

Julia

isdisarium(n) = sum(last(p)^first(p) for p in enumerate(reverse(digits(n)))) == n

function disariums(numberwanted)
    n, ret = 0, Int[]
    while length(ret) < numberwanted
        isdisarium(n) && push!(ret, n)
        n += 1
    end
    return ret
end

println(disariums(19))
@time disariums(19)
Output:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 89, 135, 175, 518, 598, 1306, 1676, 2427, 2646798]
  0.555962 seconds (5.29 M allocations: 562.335 MiB, 10.79% gc time)

Kotlin

fun power(n: Int, exp: Int): Int {
    return when {
        exp > 1 -> n * power(n, exp-1)
        exp == 1 -> n
        else -> 1
    }
}

fun is_disarium(num: Int): Boolean {
    val n = num.toString()
    var sum = 0
    for (i in 1..n.length) {
        sum += power (n[i-1] - '0', i)
    }
    return sum == num
}

fun main() {
    var i = 0
    var count = 0
    while (count < 19) {
        if (is_disarium(i)) {
            print("$i ")
            count++
        }
        i++
    }
    println("")
}
Output:
0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798

Lua

Like most other solutions, this stops at 19. Computation time aside, the 20th Disarium number is greater than 2^53, above which double-precision floating-point format (which is Lua's in-built number type) has insufficient precision to distinguish between one integer and the next.

function isDisarium (x)
    local str, sum, digit = tostring(x), 0
    for pos = 1, #str do
        digit = tonumber(str:sub(pos, pos))
        sum = sum + (digit ^ pos)
    end
    return sum == x
end

local count, n = 0, 0
while count < 19 do
    if isDisarium(n) then
        count = count + 1
        io.write(n .. " ")
    end
    n = n + 1
end
Output:
0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798

MAD

            NORMAL MODE IS INTEGER
            
            VECTOR VALUES FMT = $ I7*$
            AMOUNT = 19
           
            THROUGH TEST, FOR CAND=0, 1, AMOUNT.E.0
            WHENEVER DISARI.(CAND)
                PRINT FORMAT FMT,CAND
                AMOUNT = AMOUNT-1
            END OF CONDITIONAL
TEST        CONTINUE
            
            INTERNAL FUNCTION(N)
            ENTRY TO LENGTH.
            L = 0
            THROUGH COUNT, FOR NN=N, 0, NN.E.0
            L = L+1
COUNT       NN = NN/10
            FUNCTION RETURN L
            END OF FUNCTION
            
            INTERNAL FUNCTION(BASE,EXP)
            ENTRY TO RAISE.
            R = 1
            THROUGH MUL, FOR E=EXP, -1, E.E.0
MUL         R = R*BASE
            FUNCTION RETURN R
            END OF FUNCTION
            
            INTERNAL FUNCTION(N)
            ENTRY TO DISARI.
            L = LENGTH.(N)
            POWSUM = 0
            THROUGH DGTLP, FOR NN=N, 0, NN.E.0
            NX = NN/10
            DG = NN-NX*10
            POWSUM = POWSUM+RAISE.(DG,L)
            L = L-1
DGTLP       NN = NX
            FUNCTION RETURN POWSUM.E.N
            END OF FUNCTION
            END OF PROGRAM
Output:
      0
      1
      2
      3
      4
      5
      6
      7
      8
      9
     89
    135
    175
    518
    598
   1306
   1676
   2427
2646798

Mathematica /Wolfram Language

ClearAll[DisariumQ]
DisariumQ[n_Integer] := Module[{digs},
  digs = IntegerDigits[n];
  digs = digs^Range[Length[digs]];
  Total[digs] == n
]
i = 0;
Reap[Do[
   If[DisariumQ[n],
    i++;
    Sow[n]
    ];
   If[i == 19, Break[]]
   ,
   {n, 0, \[Infinity]}
   ]][[2, 1]]
Output:
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 89, 135, 175, 518, 598, 1306, 1676, 2427, 2646798}

Maxima

/* Function that returns a list of digits given a nonnegative integer */
decompose(num) := block([digits, remainder],
  digits: [],
  while num > 0 do
   (remainder: mod(num, 10),
    digits: cons(remainder, digits), 
    num: floor(num/10)),
  digits
)$

disariump(n):=block(
    decompose(n),
    makelist(%%[i]^i,i,length(%%)),
    apply("+",%%),
    if n=%% then true)$

disarium_count(len):=block([i:0,count:0,result:[]],
while count<len do (if disariump(i) then (result:endcons(i,result),count:count+1),i:i+1),
    result)$

/*Test cases */
disarium_count(18);
Output:
[0,1,2,3,4,5,6,7,8,9,89,135,175,518,598,1306,1676,2427]

MiniScript

isDisarium = function(n)
	num = n
	sum = 0
	if num == 0 then return true
	for i in range(ceil(log(n)), 1)
		sum +=  (n % 10) ^ i
		n = floor(n / 10)
	end for
	return num == sum
end function

foundCnt = 0
cnt = 0
while foundCnt < 19
	if isDisarium(cnt) then
		foundCnt += 1
		print cnt
	end if
	cnt +=1
end while
Output:
0
1
2
3
4
5
6
7
8
9
89
135
175
518
598
1306
1676
2427
2646798

Miranda

main :: [sys_message]
main = [Stdout (show (take 18 disaria)), Stdout "\n"]

disaria :: [num]
disaria = filter disarium [0..]

disarium :: num->bool 
disarium n = n = sum (zipWith (^) (digits n) [1..])

digits :: num->[num]
digits 0 = [0]
digits n = reverse (digits' n)
           where digits' 0 = []
                 digits' n = (n mod 10) : digits' (n div 10)

zipWith :: (* -> ** -> ***) -> [*] -> [**] -> [***]                 
zipWith f x y = map f' (zip2 x y)
                where f' (x,y) = f x y
Output:
[0,1,2,3,4,5,6,7,8,9,89,135,175,518,598,1306,1676,2427]

Modula-2

MODULE DisariumNumbers;
FROM InOut IMPORT WriteLn, WriteCard;

CONST Max = 2500;
VAR n: CARDINAL;

PROCEDURE cpow(base, power: CARDINAL): CARDINAL;
    VAR i, result: CARDINAL;
BEGIN
    result := 1;
    FOR i := 1 TO power DO 
        result := result * base 
    END;
    RETURN result
END cpow;

PROCEDURE length(n: CARDINAL): CARDINAL;
    VAR len: CARDINAL;
BEGIN
    len := 1;
    WHILE n > 10 DO
        INC(len);
        n := n DIV 10
    END;
    RETURN len
END length;

PROCEDURE digitpowersum(n: CARDINAL): CARDINAL;
    VAR powsum, exp: CARDINAL;
BEGIN
    powsum := 0;
    FOR exp := length(n) TO 1 BY -1 DO
        powsum := powsum + cpow(n MOD 10, exp);
        n := n DIV 10
    END;
    RETURN powsum
END digitpowersum;

PROCEDURE disarium(n: CARDINAL): BOOLEAN;
BEGIN
    RETURN digitpowersum(n) = n
END disarium;

BEGIN
    FOR n := 0 TO Max DO
        IF disarium(n) THEN 
            WriteCard(n, 5);
            WriteLn
        END
    END
END DisariumNumbers.
Output:
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
   89
  135
  175
  518
  598
 1306
 1676
 2427

Nim

import strutils
import math

proc is_disarium(num: int): bool =
  let n = intToStr(num)
  var sum = 0
  for i in 0..len(n)-1:
    sum += int((int(n[i])-48) ^ (i+1))
  return sum == num

var i = 0
var count = 0
while count < 19:
  if is_disarium(i):
    stdout.write i, " "
    count += 1
  i += 1
echo ""
Output:
0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798

OCaml

(* speed-optimized exponentiation; doesn't support exponents < 2 *)
let rec pow b n =
  if n land 1 = 0
  then if n = 2 then b * b else pow (b * b) (n lsr 1)
  else if n = 3 then b * b * b else b * pow (b * b) (n lsr 1)

let is_disarium n =
  let rec aux x f =
    if x < 10
    then f 2 x
    else aux (x / 10) (fun l y -> f (succ l) (y + pow (x mod 10) l))
  in
  n = aux n Fun.(const id)

let () =
  Seq.(ints 0 |> filter is_disarium |> take 19 |> iter (Printf.printf " %u%!"))
  |> print_newline
Output:
 0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798

Odin

package disarium
import "core:fmt"
import "core:math"

/* main block start */
main :: proc() {
	fmt.print("\nThe first 18 Disarium numbers are:")
	count, i: int
	for count < 19 {
		if is_disarium(i) {
			fmt.print(" ", i)
			count += 1
		}
		i += 1
	}
	fmt.println("")
} /* main block end */

/* proc definitions */
power :: proc(base, exponent: int) -> int {
	result := 1
	for _ in 1 ..= exponent {
		result *= base
	}
	return result
}

is_disarium :: proc(num: int) -> bool {
	n := num
	sum := 0
	len := n <= 9 ? 1 : cast(int)math.floor_f64(math.log10_f64(auto_cast n) + 1)
	for n > 0 {
		sum += power(n % 10, len)
		n /= 10
		len -= 1
	}
	return num == sum
}
Output:
The first 18 Disarium numbers are:  0  1  2  3  4  5  6  7  8  9  89  135  175  518  598  1306  1676  2427  2646798

Pascal

Free Pascal

simply adding one by one and keep track of sums.

program disarium;
//compile with fpc -O3 -Xs
{$IFDEF WINDOWS}
  {$APPTYPE CONSOLE}
{$ENDIF}
{$IFDEF FPC}
  {$Mode Delphi}
  uses
    sysutils;
{$ELSE}
  uses
    system.SysUtils;
{$ENDIF}
const
 MAX_BASE = 16;
 cDigits : array[0..MAX_BASE-1] of char =
    ('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');

 MAX_DIGIT_CNT = 31;

type
  tDgt_cnt= 0..MAX_DIGIT_CNT-1;
  tdgtPows = array[tDgt_cnt,0..MAX_BASE] of Uint64;
  tdgtMaxSumPot = array[tDgt_cnt] of Uint64;
  tmyDigits = record
                dgtPot  : array[tDgt_cnt] of Uint64;
                dgtSumPot : array[tDgt_cnt] of Uint64;
                dgtNumber : UInt64;
                digit  : array[0..31] of byte;
                dgtMaxLen : tDgt_cnt;
              end;

const
  UPPER_LIMIT = 100*1000*1002;

var
{$Align 32}
  dgtPows :tdgtPows;

procedure InitMyPots(var mp :tdgtPows;base:int32);
var
  pot,dgt:Uint32;
  p : Uint64;
begin
  fillchar(mp,SizeOf(mp),#0);
  For dgt := 0 to BASE do
  begin
    p := dgt;
    For pot in tDgt_cnt do
    begin
      mp[pot,dgt] := p;
      p := p*dgt;
    end;
  end;
  p := 0;
end;

procedure Out_Digits(var md:tmyDigits);
var
  i : Int32;
Begin
  with md do
  begin
   write('dgtNumber ',dgtNumber,' = ',dgtSumPot[0],' in Base ');
   For i := dgtMaxLen-1 downto 0 do
     write(cDigits[digit[i]]);
   writeln;
  end;
end;

procedure IncByOne(var md:tmyDigits;Base: Int32);inline;
var
  PotSum : Uint64;
  potBase: nativeInt;
  dg,pot,idx : Int32;

Begin
  with md do
  begin
    //first digit seperate
    pot := dgtMaxLen-1;
    dg := digit[0]+1;
    if dg < BASE then
    begin
      inc(dgtNumber);
      digit[0]:= dg;
      dgtPot[0] := dgtPows[pot,dg];
      dgtSumPot[0] := dgtSumPot[1] + dgtPot[0];
      EXIT;
    end;

    dec(dgtNumber,Base-1);
    digit[0]:= 0;
    dgtPot[0]:= 0;
    dgtSumPot[0] := dgtSumPot[1];

    potbase := Base;
    idx := 1;
    dec(pot);
    while pot >= 0 do
    Begin
      dg := digit[idx]+1;
      if dg < BASE then
      begin
        inc(dgtNumber,potbase);
        digit[idx]:= dg;
        dgtPot[idx]:= dgtPows[pot,dg];
        PotSum := dgtSumPot[idx+1];
        //update sum
        while idx>=0 do
        begin
          inc(PotSum,dgtPot[idx]);
          dgtSumPot[idx] := PotSum;
          dec(idx);
        end;
        EXIT;
      end;
      dec(dgtNumber,(dg-1)*PotBase);
      potbase *= Base;
      digit[idx]:= 0;
      dgtPot[idx] := 0;
      dec(pot);
      inc(idx);
    end;

    For pot := idx downto 0 do
    Begin
      dgtPot[idx] :=0;
      dgtSumPot[pot] := 1;
    end;
    digit[idx] := 1;
    dgtPot[idx] :=1;
    dgtMaxLen := idx+1;
    dgtNumber := potbase;
  end;
end;

procedure OneRun(var s: tmyDigits;base:UInt32;Limit:Int64);
var
  i : int64;
  cnt : Int32;
begin
  Writeln('Base = ',base);
  InitMyPots(dgtPows,base);
  fillchar(s,SizeOf(s),#0);
  s.dgtMaxLen := 1;

  i := 0;
  cnt := 0;
  repeat
    if s.dgtSumPot[0] = s.dgtNumber then
    Begin
      Out_Digits(s);
      inc(cnt);
    end;
    IncByOne(s,base);
    inc(i);
  until (i>=Limit);
  writeln ( i,' increments and found ',cnt);
end;

var
{$Align 32}
  s  : tmyDigits;
  T0: TDateTime;
  base: nativeInt;
Begin
  base := 10;
  T0 := time;
  OneRun(s,base,2646799);
  T0 := (time-T0)*86400;
  writeln(T0:8:3,' s');
  writeln;

  base := 11;
  T0 := time;
  OneRun(s,base,100173172);
  T0 := (time-T0)*86400;
  writeln(T0:8:3,' s');
  writeln;
  {$IFDEF WINDOWS}
   readln;
  {$ENDIF}
end.
@TIO.RUN:
Base = 10
dgtNumber 0 = 0 in Base 0
dgtNumber 1 = 1 in Base 1
dgtNumber 2 = 2 in Base 2
dgtNumber 3 = 3 in Base 3
dgtNumber 4 = 4 in Base 4
dgtNumber 5 = 5 in Base 5
dgtNumber 6 = 6 in Base 6
dgtNumber 7 = 7 in Base 7
dgtNumber 8 = 8 in Base 8
dgtNumber 9 = 9 in Base 9
dgtNumber 89 = 89 in Base 89
dgtNumber 135 = 135 in Base 135
dgtNumber 175 = 175 in Base 175
dgtNumber 518 = 518 in Base 518
dgtNumber 598 = 598 in Base 598
dgtNumber 1306 = 1306 in Base 1306
dgtNumber 1676 = 1676 in Base 1676
dgtNumber 2427 = 2427 in Base 2427
dgtNumber 2646798 = 2646798 in Base 2646798
2646799 increments and found 19
   0.008 s

Base = 11
dgtNumber 0 = 0 in Base 0
dgtNumber 1 = 1 in Base 1
dgtNumber 2 = 2 in Base 2
dgtNumber 3 = 3 in Base 3
dgtNumber 4 = 4 in Base 4
dgtNumber 5 = 5 in Base 5
dgtNumber 6 = 6 in Base 6
dgtNumber 7 = 7 in Base 7
dgtNumber 8 = 8 in Base 8
dgtNumber 9 = 9 in Base 9
dgtNumber 10 = 10 in Base A
dgtNumber 27 = 27 in Base 25
dgtNumber 39 = 39 in Base 36
dgtNumber 109 = 109 in Base 9A
dgtNumber 126 = 126 in Base 105
dgtNumber 525 = 525 in Base 438
dgtNumber 580 = 580 in Base 488
dgtNumber 735 = 735 in Base 609
dgtNumber 1033 = 1033 in Base 85A
dgtNumber 1044 = 1044 in Base 86A
dgtNumber 2746 = 2746 in Base 2077
dgtNumber 59178 = 59178 in Base 40509
dgtNumber 63501 = 63501 in Base 43789
dgtNumber 100173171 = 100173171 in Base 515AA64A
100173172 increments and found 24
   0.294 s

PascalABC.NET

##
function disariums: sequence of integer;
begin
  var n := 0;
  while true do 
  begin
    var sum := 0.0;
    foreach var x in n.ToString.ToCharArray index i do
      sum := sum + power((x.todigit), i + 1);
    if sum = n then yield (n);
    n += 1;
  end;
end;

disariums.Take(19).Println;
Output:
0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798

Perl

use strict;
use warnings;

my ($n,@D) = (0, 0);
while (++$n) {
    my($m,$sum);
    map { $sum += $_ ** ++$m } split '', $n;
    push @D, $n if $n == $sum;
    last if 19 == @D;
}
print "@D\n";
Output:
0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798

Phix

with javascript_semantics
constant limit = 19
integer count = 0, n = 0
printf(1,"The first 19 Disarium numbers are:\n")
while count<limit do
    atom dsum = 0
    string digits = sprintf("%d",n)
    for i=1 to length(digits) do
         dsum += power(digits[i]-'0',i)
    end for
    if dsum=n then
        printf(1," %d",n)
        count += 1
    end if
    n += 1
end while
Output:
The first 19 Disarium numbers are:
 0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798

stretch

with javascript_semantics
-- translation of https://github.com/rgxgr/Disarium-Numbers/blob/master/Disarium.c
constant DMAX = iff(machine_bits()=64?20:7)

// Pre-calculated exponential & power serials
sequence exps = repeat(repeat(0,11),1+DMAX),
         pows = repeat(repeat(0,11),1+DMAX)
exps[1..2] = {{0,0,0,0,0,0,0,0,0,0,1},{0,1,2,3,4,5,6,7,8,9,10}}
pows[1..2] = {{0,0,0,0,0,0,0,0,0,0,0},{0,1,2,3,4,5,6,7,8,9, 9}}
for i=2 to DMAX do
    for j=1 to 10 do
        exps[i+1][j] = exps[i][j]*10
        pows[i+1][j] = pows[i][j]*(j-1)
    end for
    exps[i+1][11] = exps[i][11]*10
    pows[i+1][11] = pows[i][11] + pows[i+1][10]
end for

// Digits of candidate and values of known low bits
sequence digits = repeat(0,1+DMAX), // Digits form
         expl = repeat(0,1+DMAX),   // Number form
         powl = repeat(0,1+DMAX)    // Powers form

printf(1,"") -- (exclude console setup from timings [if pw.exe])
atom expn, powr, minn, maxx, t0 = time(), t1 = t0+1, count = 0
for digit=2 to DMAX+1 do
    printf(1,"Searching %d digits (started at %s):\n", {digit-1,elapsed(time()-t0)});
    integer level = 2
    digits[1] = 0
    while true do
        // Check limits derived from already known low bit values
        // to find the most possible candidates
        while 1<level and level<digit do
            // Reset path to try next if checking in level is done
            integer dl = digits[level]+1
            if dl>10 then
                digits[level] = 0;
                level -= 1
                digits[level] += 1
            else
                // Update known low bit values
                expl[level] = expl[level-1] + exps[level][dl]
                powl[level] = powl[level-1] + pows[digit-level+2][dl]

                // Max possible value
                powr = powl[level] + pows[digit-level+1][11]

                atom ed2 = exps[digit][2]
                if powr<ed2 then  // Try next since upper limit is invalidly low
                    digits[level] += 1
                else
                    atom el11 = exps[level][11],
                         el = expl[level]
                    maxx = remainder(powr,el11)
                    powr -= maxx
                    if maxx<el then
                        powr -= el11
                    end if
                    maxx = powr + el
                    if maxx<ed2 then  // Try next since upper limit is invalidly low
                        digits[level] += 1
                    else
                        // Min possible value
                        expn = el + ed2
                        powr = powl[level] + 1

                        if expn>maxx or maxx<powr then // Try next since upper limit is invalidly low
                            digits[level] += 1
                        else
                            if powr>expn then
                                minn = remainder(powr,el11)
                                powr -= minn
                                if minn>el then
                                    powr += el11
                                end if
                                minn = powr + el
                            else
                                minn = expn
                            end if

                            // Check limits existence
                            if maxx<minn then
                                digits[level] +=1   // Try next number since current limits invalid
                            else
                                level +=1   // Go for further level checking since limits available
                            end if
                        end if
                    end if
                end if
            end if
            if time()>t1 and platform()!=JS then
                progress("working:%v... (%s)",{digits,elapsed(time()-t0)})
                t1 = time()+1
            end if
        end while
      
        // All checking is done, escape from the main check loop
        if level<2 then exit end if

        // Final check last bit of the most possible candidates
        // Update known low bit values
        integer dlx = digits[level]+1
        expl[level] = expl[level-1] + exps[level][dlx];
        powl[level] = powl[level-1] + pows[digit+1-level][dlx];

        // Loop to check all last bit of candidates
        while digits[level]<10 do
            // Print out new disarium number
            if expl[level] == powl[level] then
                if platform()!=JS then progress("") end if
                integer ld = max(trim_tail(digits,0,true),2)
                printf(1,"%s\n",{reverse(join(apply(digits[2..ld],sprint),""))})
                count += 1
            end if

            // Go to followed last bit candidate
            digits[level] += 1
            expl[level] += exps[level][2]
            powl[level] += 1
        end while

        // Reset to try next path
        digits[level] = 0;
        level -= 1
        digits[level] += 1
    end while
    if platform()!=JS then progress("") end if
end for
printf(1,"%d disarium numbers found (%s)\n",{count,elapsed(time()-t0)})
Output:
Searching 1 digits (started at 0s):
0
1
2
3
4
5
6
7
8
9
Searching 2 digits (started at 0s):
89
Searching 3 digits (started at 0s):
135
175
518
598
Searching 4 digits (started at 0s):
1306
1676
2427
Searching 5 digits (started at 0.0s):
Searching 6 digits (started at 0.0s):
Searching 7 digits (started at 0.0s):
2646798
Searching 8 digits (started at 0.0s):
Searching 9 digits (started at 0.0s):
Searching 10 digits (started at 0.0s):
Searching 11 digits (started at 0.1s):
Searching 12 digits (started at 0.1s):
Searching 13 digits (started at 0.3s):
Searching 14 digits (started at 0.8s):
Searching 15 digits (started at 2.5s):
Searching 16 digits (started at 6.9s):
Searching 17 digits (started at 23.2s):
Searching 18 digits (started at 1 minute and 8s):
Searching 19 digits (started at 3 minutes and 35s):
Searching 20 digits (started at 10 minutes and 8s):
12157692622039623539
20 disarium numbers found (2 hours and 7s)

Takes about 48min to find the 20 digit number, then trundles away for over another hour. I think that technically it should also scan for 21 and 22 digit numbers to be absolutely sure there aren't any, but that certainly exceeds my patience.

Picat

Iterative approach

Translation of: Python
main =>
  Limit = 19,
  D = [],
  N = 0,
  printf("The first %d Disarium numbers are:\n",Limit),  
  while (D.len < Limit)
     if disarium_number(N) then
       D := D ++ [N]
     end,
     N := N + 1,
     if N mod 10_000_000 == 0 then
       println(test=N)
     end
  end,
  println(D).

disarium_number(N) =>
  Sum = 0,
  Digits = N.to_string.len,
  X = N,
  while (X != 0, Sum <= N)
    Sum := Sum + (X mod 10) ** Digits,
    Digits := Digits - 1,
    X := X div 10
  end,
  Sum == N.
Output:
The first 19 Disarium numbers are:
[0,1,2,3,4,5,6,7,8,9,89,135,175,518,598,1306,1676,2427,2646798]

2.905s

Constraint modelling

A faster approach is to use constraint modeling. It finds the first 19 Disarium numbers in 0.591s (vs 2.905s for the iterative approach).

Note that the domain of Picat's constraint variables is -2**56..2**56 (about 10**17) which means that this approach cannot be used to handle numbers of length 20.

The cp solver and sat solvers takes about the same time for finding the 7-digits number 2646798, but the sat solver is much faster for checking longer numbers; it took almost 9 minutes to prove that there are no Disarium numbers of length 8..17.

import sat.
% import cp.

main =>
  D = [],
  Limit = 19,
  Base = 10,
  foreach(Len in 1..20, D.len < Limit)
     Nums = disarium_number_cp(Len,Base),
     if Nums.len > 0 then
       foreach(Num in Nums)
         B = to_radix_string(Num,Base),
         D := D ++ [B]
       end
     end
  end,
  printf("The first %d Disarius numbers in base %d:\n",D.len, Base),
  println(D[1..Limit]),
  nl.

% Find all Disarium of a certain length
disarium_number_cp(Len,Base) = findall(N,disarium_number_cp(Len,Base,N)).sort.

% Find a Disarium number of a certain length
disarium_number_cp(Len,Base,N) =>
  X = new_list(Len),
  X :: 0..Base-1,
  N :: Base**(Len-1)-1..Base**Len-1,
  N #= sum([X[I]**I : I in 1..Len]),  
  to_num(X,Base,N), % convert X <=> N
  solve($[],X++[N]).

% Converts a number Num to/from a list of integer List given a base Base
to_num(List, Base, Num) =>
   Len = length(List),
   Num #= sum([List[I]*Base**(Len-I) : I in 1..Len]).
Output:
The first 19 Disarius numbers in base 10:
[0,1,2,3,4,5,6,7,8,9,89,135,175,518,598,1306,1676,2427,2646798]

0.591s

Finding the first 23 Disarium numbers in base 11 is easier:

The first 23 Disarius numbers in base 11:
[0,1,2,3,4,5,6,7,8,9,A,25,36,9A,105,438,488,609,85A,86A,2077,40509,43789]

0.015s

(And finding the first 36 Disarium numbers in base 36 is even easier: 0..Z.)

PicoLisp

(de disarium (N)
   (let S 0
      (for (I . N) (mapcar format (chop N))
         (inc 'S (** N I)) )
      (= N S) ) )
(let (N 0  C 0)
   (until (= C 19)
      (and
         (disarium N)
         (printsp N)
         (inc 'C) )
      (inc 'N) )
   (prinl) )

Python

#!/usr/bin/python

def isDisarium(n):
    digitos = len(str(n))
    suma = 0
    x = n
    while x != 0:
        suma += (x % 10) ** digitos
        digitos -= 1
        x //= 10
    if suma == n:
        return True
    else:
        return False

if __name__ == '__main__':
    limite = 19
    cont = 0
    n = 0
    print("The first",limite,"Disarium numbers are:")
    while cont < limite:
        if isDisarium(n):
            print(n, end = " ")
            cont += 1
        n += 1
Output:
The first 19 Disarium numbers are:
 0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798

PL/M

Based on...

Translation of: ALGOL 68

... but as the original PL/M compiler only supports 8 and 16-bit unsigned integers, this stops after trying up to 9999 or finding 18 Disarium numbers. Also, PL/M only supports 1-dimensional arrays.

Works with: 8080 PL/M Compiler

... under CP/M (or an emulator)

100H: /* FIND SOME DISARIUM NUMBERS - NUMBERS WHOSE DIGIT POSITION-POWER     */
      /* SUMS ARE EQUAL TO THE NUMBER, E.G. 135 = 1^1 + 3^2 + 5^3            */

   /* CP/M BDOS SYSTEM CALL, IGNORE THE RETURN VALUE                         */
   BDOS: PROCEDURE( FN, ARG ); DECLARE FN BYTE, ARG ADDRESS; GOTO 5; END;
   PR$CHAR:   PROCEDURE( C ); DECLARE C BYTE;    CALL BDOS( 2, C );  END;
   PR$STRING: PROCEDURE( S ); DECLARE S ADDRESS; CALL BDOS( 9, S );  END;
   PR$NUMBER: PROCEDURE( N ); /* PRINTS A NUMBER IN THE MINIMUN FIELD WIDTH  */
      DECLARE N ADDRESS;
      DECLARE V ADDRESS, N$STR ( 6 )BYTE, W BYTE;
      V = N;
      W = LAST( N$STR );
      N$STR( W ) = '$';
      N$STR( W := W - 1 ) = '0' + ( V MOD 10 );
      DO WHILE( ( V := V / 10 ) > 0 );
         N$STR( W := W - 1 ) = '0' + ( V MOD 10 );
      END;
      CALL PR$STRING( .N$STR( W ) );
   END PR$NUMBER;

   /* TABLE OF POWERS UP TO THE FOURTH POWER - AS WE ARE ONLY FINDING THE   */
   /* DISARIUM NUMBERS UP TO 9999                                           */
   DECLARE POWER( 40 /* ( 1 : 4, 0 : 9 ) */ ) ADDRESS;
   DECLARE MAX$DISARIUM LITERALLY '9999';

   DECLARE ( N, D, POWER$OF$TEN, COUNT, LENGTH, V, P, DPS, NSUB, NPREV )
                                              ADDRESS;

   /* COMPUTE THE NTH POWERS OF 0-9                                         */
   DO D = 0 TO 9; POWER( D ) = D; END;
   NSUB  = 10;
   NPREV =  0;
   DO N = 2 TO 4;
      POWER( NSUB ) = 0;
      DO D = 1 TO 9;
         POWER( NSUB + D ) = POWER( NPREV + D ) * D;
      END;
      NPREV = NSUB;
      NSUB  = NSUB + 10;
   END;

   /* PRINT THE DISARIUM NUMBERS UPTO 9999 OR THE 18TH, WHICHEVER IS SOONER */
   POWER$OF$TEN = 10;
   LENGTH       =  1;
   COUNT, N     =  0;
   DO WHILE( N < MAX$DISARIUM AND COUNT < 18 );
      IF N = POWER$OF$TEN THEN DO;
         /* THE NUMBER OF DIGITS JUST INCREASED                             */
         POWER$OF$TEN = POWER$OF$TEN * 10;
         LENGTH       = LENGTH       +  1;
      END;
      /* FORM THE DIGIT POWER SUM                                           */
      V   = N;
      P   = LENGTH * 10;
      DPS = 0;
      DO D = 1 TO LENGTH;
         P = P - 10;
         DPS = DPS + POWER( P + ( V MOD 10 ) );
         V = V / 10;
      END;
      IF DPS = N THEN DO;
         /* N IS DISARIUM                                                   */
         COUNT = COUNT + 1;
         CALL PR$CHAR( ' ' );
         CALL PR$NUMBER( N );
      END;
      N = N + 1;
   END;

EOF
Output:
 0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427

Quackery

  [ [ [] swap
      [ 10 /mod
      rot join swap
      dup 0 = until ]
    drop ] ]               is digits    ( n --> [ )

  [ 0 over digits
    witheach
      [ i^ 1+ ** + ] = ]   is disarium  ( n --> b )

  [ temp put [] 0
    [ dup disarium if
        [ dup dip join ]
      1+
      over size
      temp share = until ]
    drop ]                 is disariums ( n --> [ )

   19 disariums echo
Output:
[ 0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798 ]

Raku

Not an efficient algorithm. First 18 in less than 1/4 second. 19th in around 45 seconds. Pretty much unusable for the 20th.

my $disarium = (^∞).hyper.map: { $_ if $_ == sum .polymod(10 xx *).reverse Z** 1..* };

put $disarium[^18];
put $disarium[18];
Output:
0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427
2646798


Refal

$ENTRY Go {
    = <FindDisarium 19 0>;
};

Digits {
    0 = ;
    s.N, <Divmod s.N 10>: (s.R) s.D = <Digits s.R> s.D;
};

Pow {
    s.N 0 = 1;
    s.N s.P = <* s.N <Pow s.N <- s.P 1>>>;
};

PowSum {
    () e.P = 0;
    (s.I e.X) e.P = <+ <Pow s.I e.P> <PowSum (e.X) <+ e.P 1>>>;
    e.X = <PowSum (e.X) 1>;
};

Disarium {
    e.N, <PowSum <Digits e.N>>: e.N = True;
    e.N = False;
};

FindDisarium {
    0 s.N = ;
    s.I s.N, <Disarium s.N>: {
        True = <Prout s.N> <FindDisarium <- s.I 1> <+ s.N 1>>;
        False = <FindDisarium s.I <+ s.N 1>>;
    };
};
Output:
0
1
2
3
4
5
6
7
8
9
89
135
175
518
598
1306
1676
2427
2646798

RPL

≪ DUP →STR → digits 
  ≪ 0 
     1 digits SIZE FOR j 
        digits j DUP SUB STR→ j ^ + 
     NEXT 
     == 
≫ ≫ 'DSRM?' STO

≪ → max 
  ≪ { } 0 
  WHILE OVER SIZE max < REPEAT 
     IF DUP DSRM? THEN SWAP OVER + SWAP END 
     1 + 
  END DROP 
≫ ≫ 'DSRMN' STO
18 DSRMN
Output:
{ 0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 }

Ruby

disariums = Enumerator.new do |y|
  (0..).each do |n|
    i = 0
    y << n if n.digits.reverse.sum{|d| d ** (i+=1) } == n
  end
end

puts disariums.take(19).to_a.join(" ")
Output:
0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798

Rust

fn power(n: i32, exp: i32) -> i32 {
    let mut result = 1;
    for _i in 0..exp {
        result *= n;
    }
    return result;
}

fn is_disarium(num: i32) -> bool {
    let mut n = num;
    let mut sum = 0;
    let mut i = 1;
    let len = num.to_string().len();
    while n > 0 {
        sum += power(n % 10, len as i32 - i + 1);
        n /= 10;
        i += 1
    }
    return sum == num;
}


fn main() {
    let mut i = 0;
    let mut count = 0;
    while count <= 18 {
        if is_disarium(i) {
            print!("{} ", i);
            count += 1;
        }
        i += 1;
    }
    println!("{}", " ")
}
0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798

Ring

i = 0
count = 0
while count < 19
    if is_disarium(i)
        see "" + i + " "
        count++
    ok
    i++
end
see nl

func pow (base, exp)
    result = 1
    for i = 0 to exp - 1
        result *= base
    next
    return result

func is_disarium (num)
    n = "" + num
    sum = 0
    for i = 1 to len(n)
        sum += pow (n[i] % 10, i)
    next
    return sum = num
Output:
$ ring ./disarium.ring
0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798

Scala

object Disarium extends App {
  def power(base: Int, exp: Int): Int = {
    var result = 1
    for (i <- 1 to exp) {
      result *= base
    }
    return result
  }
  def is_disarium(num: Int): Boolean = {
    val digits = num.toString.split("")
    var sum = 0
    for (i <- 0 to (digits.size - 1)) {
      sum += power(digits(i).toInt, i + 1)
    }
    return num == sum
  }

  var i = 0
  var count = 0
  while (count < 19) {
    if (is_disarium(i)) {
      count += 1
      printf("%d ", i)
    }
    i += 1
  }
  println("")
}
Output:
0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798

SETL

program disarium_numbers;
    loop for n in [0..2700000] | disarium n do
        print(n);
    end loop;

    op disarium(n);
        k := n;
        digits := [[k mod 10, k div:= 10](1) : until k=0];
        p := #digits+1;
        powsum := +/[d ** (p -:= 1) : d in digits];
        return powsum = n;
    end op;
end program;
Output:
0
1
2
3
4
5
6
7
8
9
89
135
175
518
598
1306
1676
2427
2646798

Sidef

func is_disarium(n) {
    n.digits.flip.sum_kv{|k,d| d**(k+1) } == n
}

say 18.by(is_disarium)
Output:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 89, 135, 175, 518, 598, 1306, 1676, 2427]

Tcl

proc is_disarium {num} {
    set n num
    set sum 0
    set i 1
    set ch 1
    foreach char [split $num {}] {
        scan $char %d ch
        set sum [ expr ($sum + $ch ** $i)]
        incr i
    }
    return [ expr $num == $sum ? 1 : 0]
}
set i 0
set count 0
while { $count < 19 } {
    if [ is_disarium $i ] {
        puts -nonewline  "${i} "
        incr count
    }
    incr i
}
puts ""
Output:
$ time tclsh ./disarium.tcl
0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798

real    1m59,638s
user    1m56,328s
sys     0m0,234s
}

V (Vlang)

Recommend to build first `v -prod disarium.v` and then run `./disarium`

Translation of: Go
import strconv

const dmax = 20  // maximum digits
const limit = 20 // maximum number of disariums to find
 
fn main() {
    // Pre-calculated exponential and power serials
    mut exp1 := [][]u64{len: 1+dmax, init: []u64{len: 11}}
    mut pow1 := [][]u64{len: 1+dmax, init: []u64{len: 11}}
 
    for i := u64(1); i <= 10; i++ {
        exp1[1][i] = i
    }
    for i := u64(1); i <= 9; i++ {
        pow1[1][i] = i
    }
    pow1[1][10] = 9
 
    for i := 1; i < dmax; i++ {
        for j := 0; j <= 9; j++ {
            exp1[i+1][j] = exp1[i][j] * 10
            pow1[i+1][j] = pow1[i][j] * u64(j)
        }
        exp1[i+1][10] = exp1[i][10] * 10
        pow1[i+1][10] = pow1[i][10] + pow1[i+1][9]
    }
 
    // Digits of candidate and values of known low bits
    mut digits := []int{len: 1+dmax} // Digits form
    mut exp2 := []u64{len: 1+dmax} // Number form
    mut pow2 := []u64{len: 1+dmax} // pow2ers form
 
    mut exp, mut pow, mut min, mut max := u64(0),u64(0),u64(0),u64(0)
    start := 1
    final := dmax
    mut count := 0
    for digit := start; digit <= final; digit++ {
        println("# of digits: $digit")
        mut level := 1
        digits[0] = 0
        for {
            // Check limits derived from already known low bit values
            // to find the most possible candidates
            for 0 < level && level < digit {
                // Reset path to try next if checking in level is done
                if digits[level] > 9 {
                    digits[level] = 0
                    level--
                    digits[level]++
                    continue
                }
 
                // Update known low bit values
                exp2[level] = exp2[level-1] + exp1[level][digits[level]]
                pow2[level] = pow2[level-1] + pow1[digit+1-level][digits[level]]
 
                // Max possible value
                pow = pow2[level] + pow1[digit-level][10]
 
                if pow < exp1[digit][1] { // Try next since upper limit is invalidly low
                    digits[level]++
                    continue
                }
 
                max = pow % exp1[level][10]
                pow -= max
                if max < exp2[level] {
                    pow -= exp1[level][10]
                }
                max = pow + exp2[level]
 
                if max < exp1[digit][1] { // Try next since upper limit is invalidly low
                    digits[level]++
                    continue
                }
 
                // Min possible value
                exp = exp2[level] + exp1[digit][1]
                pow = pow2[level] + 1
 
                if exp > max || max < pow { // Try next since upper limit is invalidly low
                    digits[level]++
                    continue
                }
 
                if pow > exp {
                    min = pow % exp1[level][10]
                    pow -= min
                    if min > exp2[level] {
                        pow += exp1[level][10]
                    }
                    min = pow + exp2[level]
                } else {
                    min = exp
                }
 
                // Check limits existence
                if max < min {
                    digits[level]++ // Try next number since current limits invalid
                } else {
                    level++ // Go for further level checking since limits available
                }
            }
 
            // All checking is done, escape from the main check loop
            if level < 1 {
                break
            }
 
            // Finally check last bit of the most possible candidates
            // Update known low bit values
            exp2[level] = exp2[level-1] + exp1[level][digits[level]]
            pow2[level] = pow2[level-1] + pow1[digit+1-level][digits[level]]
 
            // Loop to check all last bits of candidates
            for digits[level] < 10 {
                // Print out new Disarium number
                if exp2[level] == pow2[level] {
                    mut s := ""
                    for i := dmax; i > 0; i-- {
                        s += "${digits[i]}"
                    }
                    n, _ := strconv.common_parse_uint2(s, 10, 64)
                    println(n)
                    count++
                    if count == limit {
                        println("\nFound the first $limit Disarium numbers.")
                        return
                    }
                }
 
                // Go to followed last bit candidate
                digits[level]++
                exp2[level] += exp1[level][1]
                pow2[level]++
            }
 
            // Reset to try next path
            digits[level] = 0
            level--
            digits[level]++
        }
        println('')
    }
}
Output:
# of digits: 1
0
1
2
3
4
5
6
7
8
9

# of digits: 2
89

# of digits: 3
135
175
518
598

# of digits: 4
1306
1676
2427

# of digits: 5

# of digits: 6

# of digits: 7
2646798

# of digits: 8

# of digits: 9

# of digits: 10

# of digits: 11

# of digits: 12

# of digits: 13

# of digits: 14

# of digits: 15

# of digits: 16

# of digits: 17

# of digits: 18

# of digits: 19

# of digits: 20
12157692622039623539

Found the first 20 Disarium numbers.

VTL-2

Translation of: ALGOL W

Finds the first 18 Disarium numbers - computes a table of digit powers up to the fourth power.

1000 N=1
1010 D=0
1020 :N*10+D)=D
1030 D=D+1
1040 #=D<10*1020
1050 N=2
1060 :N*10)=0
1070 D=1
1080 :N*10+D)=:N-1*10+D)*D
1090 D=D+1
1100 #=D<10*1080
1120 N=N+1
1130 #=N<5*1060
2000 C=0
2010 T=10
2020 L=1
2030 N=0
2040 #=N=T=0*2070
2050 T=T*10
2060 L=L+1
2070 V=N
2080 P=L
2090 S=0
2100 V=V/10
2110 S=S+:P*10+%
2120 P=P-1
2130 #=V>1*(S-1<N)*2100
2140 #=S=N=0*2180
2150 C=C+1
2160 $=32
2170 ?=N
2180 N=N+1
2190 #=C<18*2040
Output:
 0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427

Wren

Library: Wren-math

Version 1 (Brute force)

This version finds the first 19 Disarium numbers in 3.35 seconds though, clearly, finding the 20th is out of the question with this approach.

As a possible optimization, I tried caching all possible digit powers but there was no perceptible difference in running time for numbers up to 7 digits long.

import "./math" for Int

var limit = 19
var count = 0
var disarium = []
var n = 0
while (count < limit) {
    var sum = 0
    var digits = Int.digits(n)
    for (i in 0...digits.count) sum = sum + digits[i].pow(i+1)
    if (sum == n) {
        disarium.add(n)
        count = count + 1
    }
    n = n + 1
}
System.print("The first 19 Disarium numbers are:")
System.print(disarium)
Output:
The first 19 Disarium numbers are:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 89, 135, 175, 518, 598, 1306, 1676, 2427, 2646798]


Version 2 (Much faster)

This is a translation of the C code referred to in the Phix entry and finds the first 19 Disarium numbers in 0.012 seconds.

Efficient though this method is, unfortunately finding the 20th is still out of reasonable reach for Wren. If we let this run until 15 digit numbers have been examined (the most that 53 bit integer math can accurately manage), then the time taken rises to 19 seconds - roughly 3 times slower than Phix.

However, we need 64 bit integer arithmetic to get up to 20 digits and this requires the use of Wren-long which (as it's written entirely in Wren, not C) needs about 7 times longer (2 minutes 16 seconds) to even reach 15 digits. Using BigInt or GMP would be even slower.

So, if the Phix example requires 48 minutes to find the 20th number, it would probably take Wren the best part of a day to do the same which is far longer than I have patience for.

var DMAX  = 7  // maxmimum digits
var LIMIT = 19 // maximum number of Disariums to find

// Pre-calculated exponential and power serials
var EXP = List.filled(1 + DMAX, null)
var POW = List.filled(1 + DMAX, null)
EXP[0] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
EXP[1] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
POW[0] = List.filled(11, 0)
POW[1] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9]
for (i in 2..DMAX) {
    EXP[i] = List.filled(11, 0)
    POW[i] = List.filled(11, 0)
}    
for (i in 1...DMAX) {
    for (j in 0..9) {
        EXP[i+1][j] = EXP[i][j] * 10
        POW[i+1][j] = POW[i][j] * j
    }
    EXP[i+1][10] = EXP[i][10] * 10
    POW[i+1][10] = POW[i][10] + POW[i+1][9]
}

// Digits of candidate and values of known low bits
var DIGITS = List.filled(1 + DMAX, 0)  // Digits form
var Exp    = List.filled(1 + DMAX, 0)  // Number form
var Pow    = List.filled(1 + DMAX, 0)  // Powers form

var exp
var pow
var min
var max
var start = 1
var final = DMAX
var count = 0
for (digit in start..final) {
    System.print("# of digits: %(digit)")
    var level = 1
    DIGITS[0] = 0
    while (true) {
        // Check limits derived from already known low bit values
        // to find the most possible candidates
        while (0 < level && level < digit) {
            // Reset path to try next if checking in level is done
            if (DIGITS[level] > 9) {
                DIGITS[level] = 0
                level = level - 1
                DIGITS[level] = DIGITS[level] + 1
                continue
            }

            // Update known low bit values
            Exp[level] = Exp[level - 1] + EXP[level][DIGITS[level]]
            Pow[level] = Pow[level - 1] + POW[digit + 1 - level][DIGITS[level]]

            // Max possible value
            pow = Pow[level] + POW[digit - level][10]

            if (pow < EXP[digit][1]) {  // Try next since upper limit is invalidly low
                DIGITS[level] = DIGITS[level] + 1
                continue
            }

            max = pow % EXP[level][10]
            pow = pow - max
            if (max < Exp[level]) pow = pow - EXP[level][10]
            max = pow + Exp[level]

            if (max < EXP[digit][1]) {  // Try next since upper limit is invalidly low
                DIGITS[level] = DIGITS[level] + 1
                continue
            }

            // Min possible value
            exp = Exp[level] + EXP[digit][1]
            pow = Pow[level] + 1

            if (exp > max || max < pow) { // Try next since upper limit is invalidly low
                DIGITS[level] = DIGITS[level] + 1
                continue
            }

            if (pow > exp ) {
                min = pow % EXP[level][10]
                pow = pow - min 
                if (min > Exp[level]) {
                    pow = pow + EXP[level][10]
                }
                min = pow + Exp[level]
            } else {
                min = exp
            }

            // Check limits existence
            if (max < min) {
                DIGITS[level] = DIGITS[level] + 1  // Try next number since current limits invalid
            } else {
                level= level + 1  // Go for further level checking since limits available
            }
        }

        // All checking is done, escape from the main check loop
        if (level < 1) break

        // Finally check last bit of the most possible candidates
        // Update known low bit values
        Exp[level] = Exp[level - 1] + EXP[level][DIGITS[level]]
        Pow[level] = Pow[level - 1] + POW[digit + 1 - level][DIGITS[level]]

        // Loop to check all last bits of candidates
        while (DIGITS[level] < 10) {
            // Print out new Disarium number
            if (Exp[level] == Pow[level]) {
                var s = ""
                for (i in DMAX...0) s = s + DIGITS[i].toString
                System.print(Num.fromString(s))
                count = count + 1
                if (count == LIMIT) {
                    System.print("\nFound the first %(LIMIT) Disarium numbers.")
                    return
                }
            }

            // Go to followed last bit candidate
            DIGITS[level] = DIGITS[level] + 1
            Exp[level] = Exp[level] + EXP[level][1]
            Pow[level] = Pow[level] + 1
        }

        // Reset to try next path
        DIGITS[level] = 0
        level = level - 1
        DIGITS[level] = DIGITS[level] + 1
    }
    System.print()
}
Output:
# of digits: 1
0
1
2
3
4
5
6
7
8
9

# of digits: 2
89

# of digits: 3
135
175
518
598

# of digits: 4
1306
1676
2427

# of digits: 5

# of digits: 6

# of digits: 7
2646798

Found the first 19 Disarium numbers.

real	0m0.012s
user	0m0.008s
sys	0m0.004s


Version 3 (Embedded)

Library: Wren-i64

An initial outing for the above module which aims to speed up 64 bit arithmetic in Wren by wrapping the corresponding C99 fixed size types.

Early indications are that this is at least 4 times faster than Wren-long as it can search up to 15 digits in about 29 seconds which in turn is about 4 times slower than the Phix entry.

This suggested that the 20th Disarium number would be found in around 3.5 hours so I thought I'd have a go. However, after taking consistently 4 times longer than Phix to search each digit length up to 19, I was pleasantly surprised when the 20th number popped up after only 81 minutes!

I haven't bothered to search all 20 digits numbers up to the unsigned 64 limit as this would take far longer and, of course, be fruitless in any case.

import "./i64" for U64

var DMAX  = 20 // maxmimum digits
var LIMIT = 20 // maximum number of disariums to find

// Pre-calculated exponential and power serials
var EXP = List.filled(1 + DMAX, null)
var POW = List.filled(1 + DMAX, null)
EXP[0]  = List.filled(11, null)
EXP[1]  = List.filled(11, null)
POW[0]  = List.filled(11, null)
POW[1]  = List.filled(11, null)
for (i in 0..9) EXP[0][i] = U64.zero
EXP[0][10] = U64.one

for (i in 0..10) EXP[1][i] = U64.from(i)

for (i in 0..10) POW[0][i] = U64.zero

for (i in 0..9) POW[1][i] = U64.from(i)
POW[1][10] = U64.from(9)

for (i in 2..DMAX) {
    EXP[i] = List.filled(11, null)
    POW[i] = List.filled(11, null)
    for (j in 0..10) {
        EXP[i][j] = U64.zero
        POW[i][j] = U64.zero
    }
}
for (i in 1...DMAX) {
    for (j in 0..9) {
        EXP[i+1][j] = EXP[i][j] * 10
        POW[i+1][j] = POW[i][j] * j
    }
    EXP[i+1][10] = EXP[i][10] * 10
    POW[i+1][10] = POW[i][10] + POW[i+1][9]
}

// Digits of candidate and values of known low bits
var DIGITS = List.filled(1 + DMAX, 0)  // Digits form
var Exp    = List.filled(1 + DMAX, null)  // Number form
var Pow    = List.filled(1 + DMAX, null)  // Powers form
for (i in 0..DMAX) {
    Exp[i] = U64.zero
    Pow[i] = U64.zero
}

var exp = U64.new()
var pow = U64.new()
var min = U64.new()
var max = U64.new()
var start = 1
var final = DMAX
var count = 0
for (digit in start..final) {
    System.print("# of digits: %(digit)")
    var level = 1
    DIGITS[0] = 0
    while (true) {
        // Check limits derived from already known low bit values
        // to find the most possible candidates
        while (0 < level && level < digit) {
            // Reset path to try next if checking in level is done
            if (DIGITS[level] > 9) {
                DIGITS[level] = 0
                level = level - 1
                DIGITS[level] = DIGITS[level] + 1
                continue
            }

            // Update known low bit values
            Exp[level].add(Exp[level - 1], EXP[level][DIGITS[level]])
            Pow[level].add(Pow[level - 1], POW[digit + 1 - level][DIGITS[level]])

            // Max possible value
            pow.add(Pow[level], POW[digit - level][10])

            if (pow < EXP[digit][1]) {  // Try next since upper limit is invalidly low
                DIGITS[level] = DIGITS[level] + 1
                continue
            }

            max.rem(pow, EXP[level][10])
            pow.sub(max)
            if (max < Exp[level]) pow.sub(EXP[level][10])
            max.add(pow, Exp[level])

            if (max < EXP[digit][1]) {  // Try next since upper limit is invalidly low
                DIGITS[level] = DIGITS[level] + 1
                continue
            }

            // Min possible value
            exp.add(Exp[level], EXP[digit][1])
            pow.add(Pow[level], 1)

            if (exp > max || max < pow) { // Try next since upper limit is invalidly low
                DIGITS[level] = DIGITS[level] + 1
                continue
            }

            if (pow > exp ) {
                min.rem(pow, EXP[level][10])
                pow.sub(min)
                if (min > Exp[level]) {
                    pow.add(EXP[level][10])
                }
                min.add(pow, Exp[level])
            } else {
                min.set(exp)
            }

            // Check limits existence
            if (max < min) {
                DIGITS[level] = DIGITS[level] + 1  // Try next number since current limits invalid
            } else {
                level = level + 1  // Go for further level checking since limits available
            }
        }

        // All checking is done, escape from the main check loop
        if (level < 1) break

        // Final check last bit of the most possible candidates
        // Update known low bit values
        Exp[level].add(Exp[level - 1], EXP[level][DIGITS[level]])
        Pow[level].add(Pow[level - 1], POW[digit + 1 - level][DIGITS[level]])

        // Loop to check all last bit of candidates
        while (DIGITS[level] < 10) {
            // Print out new disarium number
            if (Exp[level] == Pow[level]) {
                var s = ""
                for (i in DMAX...0) s = s + DIGITS[i].toString
                s = s.trimStart("0")
                if (s == "") s = "0"
                System.print(s)
                count = count + 1
                if (count == LIMIT) {
                    if (LIMIT < 20) {
                        System.print("\nFound the first %(LIMIT) Disarium numbers.")
                    } else {
                        System.print("\nFound all 20 Disarium numbers.")
                    }
                    return
                }
            }

            // Go to followed last bit candidate
            DIGITS[level] = DIGITS[level] + 1
            Exp[level].add(Exp[level], EXP[level][1])
            Pow[level].inc
        }

        // Reset to try next path
        DIGITS[level] = 0
        level = level - 1
        DIGITS[level] = DIGITS[level] + 1
    }
    System.print()
}
Output:
# of digits: 1
0
1
2
3
4
5
6
7
8
9

# of digits: 2
89

# of digits: 3
135
175
518
598

# of digits: 4
1306
1676
2427

# of digits: 5

# of digits: 6

# of digits: 7
2646798

# of digits: 8

# of digits: 9

# of digits: 10

# of digits: 11

# of digits: 12

# of digits: 13

# of digits: 14

# of digits: 15

# of digits: 16

# of digits: 17

# of digits: 18

# of digits: 19

# of digits: 20
12157692622039623539

Found all 20 Disarium numbers.

real	81m16.365s
user	81m16.181s
sys	0m0.016s

XPL0

1.35 seconds on Pi4.

func Disarium(N);       \Return 'true' if N is a Disarium number
int  N, N0, D(10), A(10), I, J, Sum;
[N0:= N;
for J:= 0 to 10-1 do A(J):= 1;
I:= 0;
repeat  N:= N/10;
        D(I):= rem(0);
        I:= I+1;
        for J:= 0 to I-1 do
            A(J):= A(J) * D(J);
until   N = 0;
Sum:= 0;
for J:= 0 to I-1 do
    Sum:= Sum + A(J);
return Sum = N0;
];

int Cnt, N;
[Cnt:= 0;  N:= 0;
loop    [if Disarium(N) then
            [IntOut(0, N);  ChOut(0, ^ );
            Cnt:= Cnt+1;
            if Cnt >= 19 then quit;
            ];
        N:= N+1;
        ];
]
Output:
0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798