aboutsummaryrefslogtreecommitdiff
path: root/challenge-020/jo-37
diff options
context:
space:
mode:
authorJörg Sommrey <28217714+jo-37@users.noreply.github.com>2023-03-16 22:44:27 +0100
committerJörg Sommrey <28217714+jo-37@users.noreply.github.com>2023-03-23 18:03:42 +0100
commit48b0651fd1169f9d0f65aac92fb754c858cf0d52 (patch)
tree21fdddc1173cbbf9c35d15287feea49f17877581 /challenge-020/jo-37
parent312cd5841215a5f45a07c88bffeabaa0e166d734 (diff)
downloadperlweeklychallenge-club-48b0651fd1169f9d0f65aac92fb754c858cf0d52.tar.gz
perlweeklychallenge-club-48b0651fd1169f9d0f65aac92fb754c858cf0d52.tar.bz2
perlweeklychallenge-club-48b0651fd1169f9d0f65aac92fb754c858cf0d52.zip
Challenge 020 task 2
Diffstat (limited to 'challenge-020/jo-37')
-rwxr-xr-xchallenge-020/jo-37/perl/ch-2.pl75
1 files changed, 75 insertions, 0 deletions
diff --git a/challenge-020/jo-37/perl/ch-2.pl b/challenge-020/jo-37/perl/ch-2.pl
new file mode 100755
index 0000000000..9548e27449
--- /dev/null
+++ b/challenge-020/jo-37/perl/ch-2.pl
@@ -0,0 +1,75 @@
+#!/usr/bin/perl -s
+
+use v5.16;
+use Test2::V0;
+use List::Gen;
+use Math::Prime::Util 'divisor_sum';
+
+our ($tests, $examples);
+
+run_tests() if $tests || $examples; # does not return
+
+die <<EOS unless @ARGV;
+usage: $0 [-examples] [-tests] [N]
+
+-examples
+ run the examples from the challenge
+
+-tests
+ run some tests
+
+N
+ find the first N amicable pairs
+
+EOS
+
+
+### Input and Output
+
+gen_amicable_pairs()->map(sub{"(@$_)"})->say(shift);
+
+
+### Implementation
+
+# Build a generator for amicable pairs.
+sub gen_amicable_pairs {
+ my %pairs;
+ <2..>->filter(sub {
+ # Skip seen pairs.
+ return if exists $pairs{$_};
+ my $s = divisor_sum($_) - $_;
+ # Skip perfect numbers.
+ return if $s == $_;
+ my $t = divisor_sum($s) - $s;
+ # Skip non-pairs.
+ return if $_ != $t;
+ # Remember the second.
+ $pairs{$s} = undef;
+ # Pair the second with the first and return "true".
+ $pairs{$_} = $s;
+ })
+ # Actually build the pairs.
+ ->map(sub{[$_, $pairs{$_}]});
+}
+
+
+### Examples and tests
+
+sub run_tests {
+ SKIP: {
+ skip "examples" unless $examples;
+
+ is gen_amicable_pairs()->take(10),
+ [[220, 284], [1184, 1210], [2620, 2924], [5020, 5564],
+ [6232, 6368], [10744, 10856], [12285, 14595],
+ [17296, 18416], [63020, 76084], [66928, 66992]],
+ 'first ten pairs from Wiki';
+ }
+
+ SKIP: {
+ skip "tests" unless $tests;
+ }
+
+ done_testing;
+ exit;
+}