|
| 1 | +#!/usr/bin/perl |
| 2 | +# By Shlomi Fish. |
| 3 | +# |
| 4 | +# Based on: |
| 5 | +# https://bitbucket.org/shlomif/project-euler/src/aa5eecd18f0825901afeb3c54dcda0da79ac3576/project-euler/23/euler-23-4.pl?at=default |
| 6 | +# |
| 7 | +# Solution for: |
| 8 | +# |
| 9 | +# http://projecteuler.net/problem=23 |
| 10 | +# |
| 11 | +# A perfect number is a number for which the sum of its proper divisors |
| 12 | +# is exactly equal to the number. For example, the sum of the proper |
| 13 | +# divisors of 28 would be 1 + 2 + 4 + 7 + 14 = 28, which means that 28 |
| 14 | +# is a perfect number. |
| 15 | +# |
| 16 | +# A number n is called deficient if the sum of its proper divisors is |
| 17 | +# less than n and it is called abundant if this sum exceeds n. |
| 18 | +# |
| 19 | +# As 12 is the smallest abundant number, 1 + 2 + 3 + 4 + 6 = 16, the |
| 20 | +# smallest number that can be written as the sum of two abundant numbers |
| 21 | +# is 24. By mathematical analysis, it can be shown that all integers |
| 22 | +# greater than 28123 can be written as the sum of two abundant numbers. |
| 23 | +# However, this upper limit cannot be reduced any further by analysis |
| 24 | +# even though it is known that the greatest number that cannot be |
| 25 | +# expressed as the sum of two abundant numbers is less than this limit. |
| 26 | +# |
| 27 | +# Find the sum of all the positive integers which cannot be written as |
| 28 | +# the sum of two abundant numbers. |
| 29 | +# |
| 30 | + |
| 31 | +my @divisors_sums; |
| 32 | +@divisors_sums[1] = 0; |
| 33 | + |
| 34 | +my $MAX = 28_123; |
| 35 | +for (1 .. ($MAX +> 1)) -> $div |
| 36 | +{ |
| 37 | + loop (my $prod = ($div +< 1); $prod <= $MAX; $prod += $div) |
| 38 | + { |
| 39 | + @divisors_sums[$prod] += $div; |
| 40 | + } |
| 41 | +} |
| 42 | + |
| 43 | +# Memoized. |
| 44 | +# |
| 45 | +my @is_abundant_sum; |
| 46 | + |
| 47 | +my @abundants; |
| 48 | +my $total = 0; |
| 49 | +for (1 .. $MAX) -> $num |
| 50 | +{ |
| 51 | + if @divisors_sums[$num] > $num |
| 52 | + { |
| 53 | + @abundants.push($num); |
| 54 | + # The sub { ... } and return are a workaround for the fact that Rakudo |
| 55 | + # Perl 6 does not have last LABEL yet. |
| 56 | + my $c = sub { |
| 57 | + for @abundants -> $i |
| 58 | + { |
| 59 | + if ((my $s = $i + $num) > $MAX) |
| 60 | + { |
| 61 | + return; |
| 62 | + } |
| 63 | + else |
| 64 | + { |
| 65 | + if (! @is_abundant_sum[$s]) |
| 66 | + { |
| 67 | + $total += $s; |
| 68 | + @is_abundant_sum[$s] = True; |
| 69 | + } |
| 70 | + } |
| 71 | + } |
| 72 | + }; |
| 73 | + |
| 74 | + $c(); |
| 75 | + } |
| 76 | +} |
| 77 | + |
| 78 | +say "Sum == ", ((((1 + $MAX) * $MAX) +> 1)-$total); |
0 commit comments