I’ve been doing the Weekly
Challenges. The
latest
involved findind odd abundant numbers and first-class functions. (Note
that this is open until 3 July 2022.)
Task 1: Abundant Number
Write a script to generate first 20 Abundant Odd Numbers.
An abundant number being one where all proper divisors (including 1
but not itself) sum to more than the number. This sequence is of
course in the OEIS.
I'd already written a divisors function for Challenge 156 Task 2, so I
adapted that to make an abundance tester. But not in Perl, where I
used Math::Prime::Util
.
use Math::Prime::Util qw(divisor_sum);
sub oddabundant($ct) {
my $n = 1;
my @o;
while (1) {
if (divisor_sum($n) > $n * 2) {
push @o,$n;
if (scalar @o >= $ct) {
last;
}
}
$n += 2;
}
return \@o;
}
In Raku, the tester (note that I can short-circuit the division
process if the divisor sum already exceeds the input):
sub abundant($n) {
if ($n==1) {
return False;
}
my $ff=1;
my $s=floor(sqrt($n));
if ($s * $s == $n) {
$ff += $s;
$s--;
}
for 2..$s -> $pf {
if ($n % $pf == 0) {
$ff += $pf;
$ff += $n div $pf;
if ($ff > $n) {
return True;
}
}
}
return False;
}
and the primary function looks much like the Perl version.
sub oddabundant($ct) {
my $n = 1;
my @o;
while (True) {
if (abundant($n)) {
@o.push($n);
if (@o.elems >= $ct) {
last;
}
}
$n += 2;
}
return @o;
}
Task 2: First-class Function
Create sub compose($f, $g)
which takes in two parameters $f
and
$g
as subroutine refs and returns subroutine ref i.e. compose($f, $g)->($x)
= $f->($g->($x))
.
I don't generally go this deep into functional programming, but it
turns out that all nine of the languages I'm using can do this, with
more or less facility.
Lua:
local f = function(x)
return x + 1
end
local g = function(x)
return x * 2
end
function compose (f1, f2)
return function(x)
return f1(f2(x))
end
end
local h = compose(f, g)
PostScript (where an executable procedure is just an array with an
"executable" flag):
/compose {
3 dict begin
/f1 exch cvlit def
/f2 exch cvlit def
/o f1 length f2 length add array def
o 0 f1 putinterval
o f1 length f2 putinterval
o cvx
end
} bind def
/f {
1 add
} bind def
/g {
2 mul
} bind def
/h { f } { g } compose bind def
Kotlin (where the hard part is working out how to declare the various
types:
fun compose(f1: (Int) -> Int, f2: (Int) -> Int): (Int) -> Int {
return fun(x: Int): Int = f1(f2(x))
}
val f = fun (x: Int): Int = x + 1
val g = fun (x: Int): Int = x * 2
val h = compose(f, g)
Raku:
my $f = sub {return @_[0] + 1};
my $g = sub {return @_[0] * 2};
my $h = compose($f,$g);
sub compose($f1,$f2) {
return sub {
$f1.($f2.(@_[0]));
}
}
and Perl:
my $f = sub {return $_[0] + 1};
my $g = sub {return $_[0] * 2};
my $h = compose($f,$g);
sub compose($f1,$f2) {
return sub {
$f1->($f2->($_[0]));
}
}
Python, which gets explicit with the lambdas:
def compose(f1,f2):
return lambda x: f1(f2(x))
f = lambda x: x + 1
g = lambda x: x * 2
h = compose(f,g)
And so does Ruby:
def compose(f1,f2)
return lambda { |x| f1.call(f2.call(x)) }
end
f = lambda { |x| return x+1 }
g = lambda { |x| return x*2 }
h = compose(f,g)
JavaScript:
let f = function(x) { return x+1 };
let g = function(x) { return x*2 };
function compose(f1,f2) {
return function(x) { return f1(f2(x)) };
}
let h = compose(f,g);
and finally Rust, which I don't really understand :
let f = |x| x + 1;
let g = |x| x * 2;
let h = compose(f, g);
fn compose<A, B, C, G, F>(f: F, g: G) -> impl Fn(A) -> C
where
F: Fn(B) -> C,
G: Fn(A) -> B,
{
move |x| f(g(x))
}
Full code on
github.
Comments on this post are now closed. If you have particular grounds for adding a late comment, comment on a more recent post quoting the URL of this one.