aboutsummaryrefslogtreecommitdiff
path: root/challenge-069
diff options
context:
space:
mode:
authorJörg Sommrey <28217714+jo-37@users.noreply.github.com>2020-07-18 11:34:52 +0200
committerJörg Sommrey <28217714+jo-37@users.noreply.github.com>2020-07-18 11:35:50 +0200
commit855e3e841ae7446c3142b9cbe73ac0d774900107 (patch)
tree1cd4d8dd61c1299686e19b02c36aa63d994c7a8c /challenge-069
parentdbb3e271ea9b4068fc0671d225cda8510bc52d8d (diff)
downloadperlweeklychallenge-club-855e3e841ae7446c3142b9cbe73ac0d774900107.tar.gz
perlweeklychallenge-club-855e3e841ae7446c3142b9cbe73ac0d774900107.tar.bz2
perlweeklychallenge-club-855e3e841ae7446c3142b9cbe73ac0d774900107.zip
avoid some string copy operations
Diffstat (limited to 'challenge-069')
-rwxr-xr-xchallenge-069/jo-37/perl/ch-2.pl34
1 files changed, 21 insertions, 13 deletions
diff --git a/challenge-069/jo-37/perl/ch-2.pl b/challenge-069/jo-37/perl/ch-2.pl
index c5c2c72c78..80ccc6f05f 100755
--- a/challenge-069/jo-37/perl/ch-2.pl
+++ b/challenge-069/jo-37/perl/ch-2.pl
@@ -30,10 +30,10 @@ use Benchmark qw(cmpthese timeit);
# with a single switch/reverse operation.
#
sub sn_extend {
- # first arg: S(k)
- # prevent copying S(k) by aliasing it to $_
+ # first arg: ref to S(k)
+ # make $_ an alias to sk
local $_;
- *_ = \shift;
+ *_ = shift;
# second arg: l
# get loop limit from l
my $upper = int 2**(shift() - 1) - 1;
@@ -46,7 +46,8 @@ sub sn_extend {
$sl .= $_ . ($i % 2) . $rsw;
$sl .= substr $sl, $i, 1 if $i < $upper;
}
- $sl;
+ # avoid copying the result
+ \$sl;
}
# Build S(n) by repeating sn_extend() with variable parametrization.
@@ -73,7 +74,7 @@ sub sn_build (&$$) {
# perform parametrized extension of S(k) -> S(k+l)
# until the next step would exceed the target order
- my ($cum, $next, $s) = (0, $iterate->(), '');
+ my ($cum, $next, $s) = (0, $iterate->(), \'');
while ($cum + $_ <= $n) {
$s = sn_extend($s, $_);
$cum += $_;
@@ -81,8 +82,8 @@ sub sn_build (&$$) {
$next = $iterate->();
}
- # get missing part of S(n) if necessary
- $cum == $n ? $s : sn_extend $s, $n - $cum
+ # get missing part of S(n) if necessary and dereference the result
+ $cum == $n ? $$s : ${sn_extend $s, $n - $cum}
}
# Benchmarks are disabled by default
@@ -91,12 +92,12 @@ SKIP: {
for my $n (5, 10, 15, 20) {
# It turns out that the doubling rule outperforms
# the others by increasing magnitude and the single-steping
- # iterator performs poorly.
+ # iterator lags behind when n > 5.
print "\nn=$n\n";
cmpthese(-1, {
std => sub {sn_build {1} 1, $n},
double => sub {sn_build {2 * $_} 1, $n},
- single => sub {sn_build {$n} $n, $n},
+ single => sub {sn_build {0} $n + 1, $n},
});
}
}
@@ -145,8 +146,15 @@ sub sn_print {
}
}
-# As the challenge says "generate SN", but not "print" or "store",
-# the following might count as a valid solution to "generate S40":
+# Demo for S10
+open my $fh, '>', \my $s10 or die;
+sn_print $fh, sn(5), 5;
+close $fh;
+is $s10, sn(10), 'S10 from sn_print';
+
+# As the challenge says "generate SN", but not "store it",
+# the following might count as a valid solution to the task of "generate
+# S40".
SKIP: {
skip "S40";
open my $null, '>', '/dev/null' or die;
@@ -161,8 +169,8 @@ SKIP: {
# With the single-stepping rule it is possible to create each SI(i)
# with a very simple recursive procedure. The required heap size is
# O(1) and the stack size is O(n) for S(n). But, as this procedure
-# is painfully slow, it is of no practical relevance. However,
-# here it is:
+# becomes painfully slow for larger n, it is of no practical relevance.
+# However, here it is:
sub sn_i {
my $i = shift;
if ($i % 2 == 0) {