|
8 | 8 | }
|
9 | 9 |
|
10 | 10 | sub count-smartly(Int \A, Int \B --> Int) {
|
11 |
| - # uses the same algorithm as polettix' solution |
12 |
| - |
13 |
| - my %seen-bases; |
14 |
| - my $seen-values = [+] gather { |
15 |
| - |
16 |
| - # visit bases which are powers of preceeding ones |
17 |
| - for 2..sqrt(A).Int -> \root { |
18 |
| - next if %seen-bases{root}; |
19 |
| - |
20 |
| - my %seen-exponents; |
21 |
| - my @powers = root, * * root ...^ * > A; |
22 |
| - |
23 |
| - for @powers Z 1..* -> \base, \exp { |
24 |
| - next if %seen-bases{base}; |
25 |
| - |
26 |
| - # mark powers of \base according to their exponent |
27 |
| - # relative to \root |
28 |
| - %seen-exponents{(2..B) >>*>> exp} = True xx *; |
29 |
| - |
30 |
| - # avoid double-counting |
31 |
| - %seen-bases{base} = True; |
32 |
| - } |
33 |
| - |
34 |
| - take +%seen-exponents; |
| 11 | + my (%powers, %count); |
| 12 | + |
| 13 | + # find bases which are powers of a preceeding root base |
| 14 | + # store decomposition into base and exponent relative to root |
| 15 | + for 2..Int(sqrt A) -> \a { |
| 16 | + for 2..* Z a**2, a**3, a**4 ...^ * > A -> \e, \p { |
| 17 | + %powers{a} //= (a) => 1; |
| 18 | + %powers{p} //= (a) => e; |
35 | 19 | }
|
| 20 | + } |
36 | 21 |
|
| 22 | + # count duplicates |
| 23 | + for %powers.values -> \p { |
| 24 | + for 2..B -> \e { |
| 25 | + # raise to power e |
| 26 | + # classify by root and relative exponent |
| 27 | + ++%count{p.key => p.value * e} |
| 28 | + } |
37 | 29 | }
|
38 | 30 |
|
39 |
| - # without duplicates, the result would be (A - 1) * (B - 1) |
40 |
| - (A - 1 - %seen-bases) * (B - 1) + $seen-values |
| 31 | + # add +%count as one of the duplicates needs to be kept |
| 32 | + return (A - 1) * (B - 1) + %count - [+] %count.values; |
41 | 33 | }
|
42 | 34 |
|
43 | 35 | sub bench(|) {
|
|
47 | 39 | return result, round (end - start) * 1000;
|
48 | 40 | }
|
49 | 41 |
|
50 |
| -sub MAIN(Int $A = 100, Int $B = 100, Bool :$verify) { |
| 42 | +multi MAIN(Int $N, Bool :$verify) { |
| 43 | + nextwith($N, $N, :$verify) |
| 44 | +} |
| 45 | + |
| 46 | +multi MAIN(Int $A = 100, Int $B = 100, Bool :$verify) { |
51 | 47 | &count-smartly.wrap(&bench);
|
52 | 48 | &count-naively.wrap(&bench);
|
53 | 49 |
|
|
0 commit comments