use strict; use warnings; use enum qw(False True); use ntheory qw/divisor_sum is_prime/; sub sieve { my($n) = @_; my %s; for my $k (0 .. $n+1) { my $sum = divisor_sum($k) - $k; $s{$sum} = True if $sum <= $n+1; } %s } my(%s,%c); my($max, $limit, $cnt) = (2000, 1e5, 0); %s = sieve 14 * $limit; !is_prime($_) and $c{$_} = True for 1..$limit; my @untouchable = (2, 5); for ( my $n = 6; $n <= $limit; $n += 2 ) { push @untouchable, $n if !$s{$n} and $c{$n-1} and $c{$n-3}; } map { $cnt++ if $_ <= $max } @untouchable; print "Number of untouchable numbers ≤ $max : $cnt \n\n" . (sprintf "@{['%6d' x $cnt]}", @untouchable[0..$cnt-1]) =~ s/(.{84})/$1\n/gr . "\n"; my($p, $count) = (10, 0); my $fmt = "%6d untouchable numbers were found ≤ %7d\n"; for my $n (@untouchable) { $count++; if ($n > $p) { printf $fmt, $count-1, $p; printf($fmt, scalar @untouchable, $limit) and last if $limit == ($p *= 10) } }