aboutsummaryrefslogtreecommitdiff
path: root/challenge-146/james-smith
diff options
context:
space:
mode:
authorJames Smith <js5@sanger.ac.uk>2022-01-05 12:22:37 +0000
committerGitHub <noreply@github.com>2022-01-05 12:22:37 +0000
commit76b07dfb47075f3c677e0e32a751d0ff22ec2d4d (patch)
treef7be0a89f08029bcd9b428502986730d365d2e1d /challenge-146/james-smith
parentd6c169bd464d2cd85804ea60f4fb7130734f0262 (diff)
downloadperlweeklychallenge-club-76b07dfb47075f3c677e0e32a751d0ff22ec2d4d.tar.gz
perlweeklychallenge-club-76b07dfb47075f3c677e0e32a751d0ff22ec2d4d.tar.bz2
perlweeklychallenge-club-76b07dfb47075f3c677e0e32a751d0ff22ec2d4d.zip
Update README.md
Diffstat (limited to 'challenge-146/james-smith')
-rw-r--r--challenge-146/james-smith/README.md56
1 files changed, 38 insertions, 18 deletions
diff --git a/challenge-146/james-smith/README.md b/challenge-146/james-smith/README.md
index 5636403eb1..a0c9ed8cc0 100644
--- a/challenge-146/james-smith/README.md
+++ b/challenge-146/james-smith/README.md
@@ -14,13 +14,13 @@ You can find the solutions here on github at:
https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-146/james-smith
-# Challenge 1 - 10001st Prime Number
+# Challenge 1 - 10,001st Prime Number
-***Write a script to generate the 10001st prime number.***
+***Write a script to generate the 10,001st prime number.***
## The solution
-We could use a Prime module, but finding primes is not that difficult so we will roll our own generator:
+We could use a Prime module, but finding primes is not that difficult so we will roll our own generator.
```perl
my($c,@p)=(5,3);
@@ -30,19 +30,18 @@ for(;@p<10000;$c+=2){
say$p[-1];
```
-The crux of the code is in the `for @` line. This sees if a given odd number is prime.
+The crux of the code is in the `for @p` line. This sees if a given odd number is prime.
We loop through all the primes up to and including the square root of the value we are checking.
If we don't find a prime factor by then we push the new value to the primes list, and go on to
-try the next number. If we find a
-factor we skip the rest of the loop and go on to try the next number.
+try the next number. If we find a factor we skip the rest of the loop and go on to try the next number.
-We stop when we have 10,000 records in the array (as we don't include the prime number 2 in the list),
-so the last element is the 10,001st prime.
+We stop when we have 10,000 records in the array (as we don't include the prime number 2 in the list - we
+explicitly exclude even numbers in the list we search over), so the last element is the 10,001st prime.
# Challenge 2 - Curious Fraction Tree
-***Can't really describe this - best to look at the image on the website at https://theweeklychallenge.org/blog/perl-weekly-challenge-146/.***
+***The tree below is defined by the following rules. For a fraction `a/b` the children are `a/(b+a)` & `(a+b)/b`. Given a node in the tree `n/m` we need to find the pate back up to the root node.***
```
1/1
@@ -63,30 +62,51 @@ so the last element is the 10,001st prime.
1/5 5/4 4/7 7/3 3/8 8/5 5/7 7/2 2/7 7/5 5/8 8/3 3/7 7/4 4/5 5/1
```
-For a given node `n/d` the children are `n/(n+d)` and `(n+d)/d`.
-
## The solution
-We note that the left-child is always less than one, the right child is always greater than 1.
-
+We note if the node is `N/D` and the parent node is `n/d`:
* To get the parent of the left child we note that `n+d = D` and `n = N`, so the parent denominator is `N-D` and numerator doesn't change
-* To get the parent of a right child we note that `n = N+D` and `d = D`, so the parent numerator is `N-D` and denominator doesn't change.
+* To get the parent of the right child we note that `n = N+D` and `d = D`, so the parent numerator is `N-D` and denominator doesn't change.
* For all nodes the numerator/denominator are co-prime.
-If it is a member of the tree we repeat until both `n` & `d` are 1. If the node is such that the numbers aren't coprime we eventually stop when
-We repeat this until we get to the top of the tree where both the denominator and numerator are less than 2. (In the tree is always 1/1) as all tree members have co-prime numerators and denominators. Other values end when the numerator is 0.
+We repeat this until `n` and `d` are the same - in the tree above both will have a value of `1`. If the initial numbers of not co-prime. The function stops when `n` and `d` are both the greatest common divisor of `n` and `d`.
The `stringify` function just converts the tree into a single string (list of fractions) so we can test the tree code.
```perl
sub tree {
my@tr=[my($n,$d)=@_];
- push@tr,$d>$n?[$n,$d-=$n]:[$n-=$d,$d]while$n*$d>1;
+ push@tr,$d>$n?[$n,$d-=$n]:[$n-=$d,$d]while$n-$d;
\@tr;
}
sub stringify {
"@{[map{join'/',@{$_}}@{$_[0]}]}";
}
-```
+sub tree_expanded {
+ my ($n,$d) = @_;
+ my $traverse = [ [ $n, $d ] ];
+ while( $n != $d ) {
+ if($d>$n) {
+ $d -= $n;
+ } else {
+ $n -= $d;
+ }
+ push @{$traverse}, [ $n, $d ];
+ }
+ return $traverse;
+}
+
+sub stringify_expanded {
+ my traverse = $_[0]; ## Ref passed
+ return join ' ',
+ map { $_->[0].'/'.$_->[1] }
+ @{ $traverse };
+}
+```
+**Notes**
+ * In the tree function we work with an array, and return it's reference (the last result is returned if no explicit `return` is given, so if you are returning from the last command in the function you do not have to include the `return` keyword.) This just makes for shorter code.
+ * Rather than using an `if/else` we use a ternary ` ? : ` to implement the same switch - and we update `$d` and `$n` when we create the new element to the array. This allows us to embed the code in a postfix `while`.
+ * Rather than using `$n==$d` we use `$n-$d` to save 1 byte but these are essentially the same in an if statement.
+ * In `stringify` we use a number of tricks for compactness. Rather than using explicit `$n.'/'.$d` we note that we can rewrite as a join. But where we want to join on `" "` we can use the fact that if you embed an array in a string "@a" it does an implicit join on `" "`. You can then embed any code within a string by wrapping it in `@{[` & `]}`