aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Smith <js5@sanger.ac.uk>2022-03-29 11:41:36 +0100
committerGitHub <noreply@github.com>2022-03-29 11:41:36 +0100
commitbc9b0e54a56462b7f4a07e4fd2e9a80ff62c99a0 (patch)
tree2ae34d903eac08440f03df4e81c7718107a46688
parent8d41fc3e8f2cae880c358387a43cf6838afa4e62 (diff)
downloadperlweeklychallenge-club-bc9b0e54a56462b7f4a07e4fd2e9a80ff62c99a0.tar.gz
perlweeklychallenge-club-bc9b0e54a56462b7f4a07e4fd2e9a80ff62c99a0.tar.bz2
perlweeklychallenge-club-bc9b0e54a56462b7f4a07e4fd2e9a80ff62c99a0.zip
Update README.md
-rw-r--r--challenge-158/james-smith/README.md42
1 files changed, 37 insertions, 5 deletions
diff --git a/challenge-158/james-smith/README.md b/challenge-158/james-smith/README.md
index c365e9e1ce..44218f126a 100644
--- a/challenge-158/james-smith/README.md
+++ b/challenge-158/james-smith/README.md
@@ -24,19 +24,34 @@ We loop through each prime p, work out the digit sum (by repeated modulo 10/divi
We craft this as two loops - an outer `for` loop and an inner `do {} while`.
```perl
+use Math::Prime::Util qw(next_prime is_prime);
+
sub additive_primes {
my @res;
- for( my $p = 2; my $s=0, (my $q=$p)<=$N; $p = next_prime $p ) {
- do { $s += $q%10 } while $q = int $q/10;
- push @res, $p if is_prime $s;
+ for(
+ my $p = 2 ;
+ my $s = 0, ( my $q = $p ) <= $N;
+ (is_prime $s) && (push @res, $p), $p = next_prime $p
+ ) {
+ do { $s += $q % 10 } while $q = int $q / 10;
}
@res;
}
```
+## Output
+```
+2, 3, 5, 7, 11, 23, 29, 41, 43, 47, 61, 67, 83, 89
+```
+## Notes
+ * We use a C-style `for` loop, with it's three parts *initialization*, *condition* and *increment*.
+ * The *condition* and *increment* statements are complicated, each with two parts separated by `,`s.
+ * The *condition* block is called at the start of each loop, and so we use it to initialise the variables as the loop, as well as checking the condition.
+ * The *increment* block is called at the end of the loop and so stores the value of `$p` if it is an additive prime, then it increments the loop with the next prime.
+ * Rather than doing a split and sum we use repeated dividing and summing, as it is more efficient around 20-30% more efficient. The increased performance is probably due to avoiding the "duality" of perl variables storing numbers as numbers/strings.
# Challenge 2 - First Series Cuban Primes
-***Write a script to compute first series Cuban Primes <= 1000. (First series cuban primes have the form `3x^2+3x+1`)***
+***Write a script to compute first series Cuban Primes <= 1000. (First series cuban primes have the form `((x+1)^3-x^3)/(x+1-x)` = `3x^2+3x+1`)***
## The solution
@@ -46,9 +61,26 @@ We output each value which in turn is prime.
```perl
(is_prime $_) && say while $N >= ($_ = 3*$x*++$x+1);
```
-### Notes
+## Output
+```
+7, 19, 37, 61, 127, 271, 331, 397, 547, 631, 919
+```
+## Notes
* As we use `$_` as our temporary variable we can use `say` by itself to output it.
* We use our common trick of `(condition) && (command)` to work as an `command if(condition)` which can be embedded in a postfix loop.
* There is a "trick" as we increment `$x` half way through the calculation of `$_`.
* `$_ = 3*$x**2 + 3*$x + 1` => `$_ = 3 * $x * ($x+1) + 1` => `$_ = 3 * $x * ++$x + 1`
* We can replace the `$x+1` by the pre increment operator `++$x` so this becomes `3 * $x * ++$x + 1`.
+
+## Aside
+
+Second series cuban primes have the form `((x+2)^3-x^3)/(x+2-x)` = `3x^2+3.2x+4`. We can tweak the code to give:
+
+```perl
+(is_prime $_) && say while $N >= ($_ = 3 * $x * (2 + $x++) + 4);
+```
+
+which outputs:
+```
+13, 109, 193, 433, 769
+```