blob: 6fccc59edda9355ea28ff5b9e4d0f1641f40a4b3 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
#!/usr/local/bin/perl
use strict;
use warnings;
use feature qw(say);
use Test::More;
use Benchmark qw(cmpthese);
my @answer = qw(9999
0 0 0 2 0 5 0 6 3 7
0 15 0 9 8 14 0 20 0 21
);
is( chowla_map($_), $answer[ $_ ] ) foreach 1..20;
is( chowla_for($_), $answer[ $_ ] ) foreach 1..20;
done_testing();
## We will quickly run benchmarking...
## This suggests the for loop to be approximately 40%
## faster than the map solution...
## It is also 9 characters shorter...
cmpthese(1_000_000, {
'Map' => sub { chowla_map($_) foreach 1..20; },
'For' => sub { chowla_for($_) foreach 1..20; },
});
##
## Rate Map For
## Map 59524/s -- -26%
## For 79936/s 34% --
##
## First attempt - the one-liner is to write this as a map,
## we add $t at the end which is the value returned
sub chowla_map {
my ($t,$n) = (0,@_);
( map { (($n%$_) || ($t+=$_)) && () } 2..$n>>1 ), $t;
}
## This time we won't write this as a nasty map/reduce solution...
##
## Just a for loop;
##
## Notes:
## * To allow for an "unless" in a postfix loop, we rewrite this
## by noting:
## unless( $condition ) { fun(); }
## can be rewritten as:
## ($condition)||($fun())
## * in perl `foreach` and `for` are synonymous - so we can shorten
## Finally a quick "shortening" - if there is no specific return
## statement - we can just omit the return in the last statement...
sub chowla_for {
my($t,$n)=(0,@_);
($n%$_)||($t+=$_) for 2..$n>>1;
$t;
}
|