-
Notifications
You must be signed in to change notification settings - Fork 34
/
smarandache_function.pl
executable file
·102 lines (72 loc) · 1.83 KB
/
smarandache_function.pl
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#!/usr/bin/perl
# Daniel "Trizen" Șuteu
# License: GPLv3
# Date: 17 September 2016
# Website: https://github.com/trizen
# A decently efficient algorithm for computing the results of the Kempner-Smarandache function.
# See also: https://projecteuler.net/problem=549
# https://en.wikipedia.org/wiki/Kempner_function
# https://mathworld.wolfram.com/SmarandacheFunction.html
# ∑S(i) for 2 ≤ i ≤ 10^2 == 2012
# ∑S(i) for 2 ≤ i ≤ 10^6 == 64938007616
# ∑S(i) for 2 ≤ i ≤ 10^8 == 476001479068717
use utf8;
use 5.010;
use strict;
use warnings;
use ntheory qw(vecsum vecmax factor_exp factorialmod is_prime);
binmode(STDOUT, ':utf8');
my %cache;
sub smarandache {
my ($n) = @_;
return $n if is_prime($n);
my @f = factor_exp($n);
my $Ω = vecsum(map { $_->[1] } @f);
(@f == $Ω)
&& return $f[-1][0];
if (@f == 1) {
my $ϕ = $f[0][0];
($Ω <= $ϕ)
&& return $ϕ * $Ω;
exists($cache{$n})
&& return $cache{$n};
my $m = $ϕ * $Ω;
while (factorialmod($m - $ϕ, $n) == 0) {
$m -= $ϕ;
}
return ($cache{$n} = $m);
}
vecmax(map { $_->[1] == 1 ? $_->[0] : smarandache($_->[0]**$_->[1]) } @f);
}
#
## Tests
#
#<<<
my @tests = (
[40, 5],
[72, 6],
[1234, 617],
[5224832089, 164],
[688 * 2**15, 43],
[891, 11],
[704, 11],
);
#>>>
foreach my $test (@tests) {
my ($n, $r) = @{$test};
my $s = smarandache($n);
say "S($n) = $s";
if ($s != $r) {
warn "\tHowever, that is incorrect! (expected: $r)";
}
}
print "\n";
my $sum = 0;
my $limit = 10**2;
for my $n (2 .. $limit) {
$sum += smarandache($n);
}
say "∑S(i) for 2 ≤ i ≤ $limit == $sum";
if ($limit == 100 and $sum != 2012) {
warn "However, that is incorrect (expected: 2012)!";
}