From 48b0651fd1169f9d0f65aac92fb754c858cf0d52 Mon Sep 17 00:00:00 2001 From: Jörg Sommrey <28217714+jo-37@users.noreply.github.com> Date: Thu, 16 Mar 2023 22:44:27 +0100 Subject: Challenge 020 task 2 --- challenge-020/jo-37/perl/ch-2.pl | 75 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100755 challenge-020/jo-37/perl/ch-2.pl 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 <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; +} -- cgit