use strict;
use warnings;
use feature 'say';
use List::Util qw(max sum);

my ($i, $pow, $digits, $offset, $lastSelf, @selfs)
 = ( 1,   10,       1,       9,         0,       );

my $final = 50;

while () {
   my $isSelf = 1;
   my $sum = my $start = sum split //, max(($i-$offset), 0);
   for ( my $j = $start; $j < $i; $j++ ) {
      if ($j+$sum == $i) { $isSelf = 0 ; last }
      ($j+1)%10 != 0 ? $sum++ : ( $sum = sum split '', ($j+1) );
   }

   if ($isSelf) {
      push @selfs, $lastSelf = $i;
      last if @selfs == $final;
   }

   next unless ++$i % $pow == 0;
   $pow *= 10;
   $offset = 9 * $digits++
}

say "The first 50 self numbers are:\n" . join ' ', @selfs;