Peter
Peter Campbell Smith

Disariums and ranks

Weekly challenge 174 — 18 July 2022

Week 174 - 18 Jul 2022

Task 1

Task — Disarium numbers

Write a script to generate first 19 Disarium Numbers. 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.

Examples


Example 1:
518
as (5 ** 1) + (1 ** 2) + (8 ** 3) => 5 + 1 + 512 => 518

Analysis

Clearly 1 to 9 inclusive are Disarium numbers because they all contain 1 digit and n ^ 1 == n. The next 8 are easily found, ranging from 89 to 2427. One further one needs a little more effort: 2646798. I found them simply by examining 1 .. (big integer). It pays to do the examination from the last digit back to the first, because you can give up as soon as the sum exceeds the number under examination.

So there's 18 of them without much effort. But what of the nineteenth?

I left my algorithm running while I had a leisurely lunch (it's 39 degrees here, after all) and came back to find ... nothing. So if there are any more DNs, they are quite big.

But, aha! Mohammad didn't specify where we should start, so I am claiming that 0 is a Disarium number, because 0^1 == 0, and that makes 2646798 the 19th.

So Disarium disaster averted!

Script


#!/usr/bin/perl

# Peter Campbell Smith - 2022-07-19
# PWC 174 task 1

use v5.26;
use strict;
use warnings;
use utf8;
binmode(STDOUT, ':utf8');

my ($j, $k, $sum, $count, $digit, $s1, $s2);

# loop over everything
$count = 1;
say qq[\nOutput:];
NUMBER: for $j (0 .. 0xffffffff) {   # 2**64
    
    # calculate the Disarian sum
    $sum = 0;
    for ($k = length($j); $k >= 1; $k --) {
        $sum += substr($j, $k - 1, 1) ** $k;
        next NUMBER if $sum > $j;   # too big already - give up
    }
    next unless $sum == $j;
    
    # explain reason
    $s1 = $s2 = '';
    for $k (1 .. length($j)) {
        $digit = substr($j, $k - 1, 1);
        $s1 .= qq[($digit ** $k) + ];
        $s2 .= ($digit ** $k) . ' + ';
    }
    say sprintf('D%02d: %d ∵ %s => %s => %d',
        $count, $j, substr($s1, 0, -3), substr($s2, 0, -3),  $j);
    last if $count ++ == 19;
}

Output


Output:
D01: 0 ∵ (0 ** 1) => 0 => 0
D02: 1 ∵ (1 ** 1) => 1 => 1
D03: 2 ∵ (2 ** 1) => 2 => 2
D04: 3 ∵ (3 ** 1) => 3 => 3
D05: 4 ∵ (4 ** 1) => 4 => 4
D06: 5 ∵ (5 ** 1) => 5 => 5
D07: 6 ∵ (6 ** 1) => 6 => 6
D08: 7 ∵ (7 ** 1) => 7 => 7
D09: 8 ∵ (8 ** 1) => 8 => 8
D10: 9 ∵ (9 ** 1) => 9 => 9
D11: 89 ∵ (8 ** 1) + (9 ** 2) => 8 + 81 => 89
D12: 135 ∵ (1 ** 1) + (3 ** 2) + (5 ** 3) => 
     1 + 9 + 125 => 135
D13: 175 ∵ (1 ** 1) + (7 ** 2) + (5 ** 3) => 
     1 + 49 + 125 => 175
D14: 518 ∵ (5 ** 1) + (1 ** 2) + (8 ** 3) => 
     5 + 1 + 512 => 518
D15: 598 ∵ (5 ** 1) + (9 ** 2) + (8 ** 3) => 
     5 + 81 + 512 => 598
D16: 1306 ∵ (1 ** 1) + (3 ** 2) + (0 ** 3) + (6 ** 4) =>
     1 + 9 + 0 + 1296 => 1306
D17: 1676 ∵ (1 ** 1) + (6 ** 2) + (7 ** 3) + (6 ** 4) =>
     1 + 36 + 343 + 1296 => 1676
D18: 2427 ∵ (2 ** 1) + (4 ** 2) + (2 ** 3) + (7 ** 4) =>
     2 + 16 + 8 + 2401 => 2427
D19: 2646798 ∵ (2 ** 1) + (6 ** 2) + (4 ** 3) + (6 ** 4) +
     (7 ** 5) + (9 ** 6) + (8 ** 7) => 2 + 36 + 64 + 1296
     + 16807 + 531441 + 2097152 => 2646798