diff options
| author | James Smith <js5@sanger.ac.uk> | 2022-01-05 12:22:37 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-01-05 12:22:37 +0000 |
| commit | 76b07dfb47075f3c677e0e32a751d0ff22ec2d4d (patch) | |
| tree | f7be0a89f08029bcd9b428502986730d365d2e1d /challenge-146/james-smith | |
| parent | d6c169bd464d2cd85804ea60f4fb7130734f0262 (diff) | |
| download | perlweeklychallenge-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.md | 56 |
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 `@{[` & `]}` |
