diff options
| author | drbaggy <js5@sanger.ac.uk> | 2021-11-16 07:10:11 +0000 |
|---|---|---|
| committer | drbaggy <js5@sanger.ac.uk> | 2021-11-16 07:10:11 +0000 |
| commit | 61b0eefa32e40d06de6dd0ab71c5079b9c9c5b6d (patch) | |
| tree | 212882b150d30d6ae83c76ca1bf8e116337c448d | |
| parent | 539750d62489e789280ec4d15a528f353e0c3baf (diff) | |
| download | perlweeklychallenge-club-61b0eefa32e40d06de6dd0ab71c5079b9c9c5b6d.tar.gz perlweeklychallenge-club-61b0eefa32e40d06de6dd0ab71c5079b9c9c5b6d.tar.bz2 perlweeklychallenge-club-61b0eefa32e40d06de6dd0ab71c5079b9c9c5b6d.zip | |
sol to 139
| -rw-r--r-- | challenge-139/james-smith/README.md | 88 | ||||
| -rw-r--r-- | challenge-139/james-smith/blog.txt | 1 | ||||
| -rw-r--r-- | challenge-139/james-smith/perl/ch-1.pl | 25 | ||||
| -rw-r--r-- | challenge-139/james-smith/perl/ch-2.pl | 25 |
4 files changed, 57 insertions, 82 deletions
diff --git a/challenge-139/james-smith/README.md b/challenge-139/james-smith/README.md index fa191ce639..ae4b2357ff 100644 --- a/challenge-139/james-smith/README.md +++ b/challenge-139/james-smith/README.md @@ -1,4 +1,4 @@ -# Perl Weekly Challenge #138 +# Perl Weekly Challenge #139 You can find more information about this weeks, and previous weeks challenges at: @@ -10,93 +10,17 @@ submit solutions in whichever language you feel comfortable with. You can find the solutions here on github at: -https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-138/james-smith/perl +https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-139/james-smith/perl -# Task 1 - Workdays +# Task 1 - JortSort -***Write a script to calculate the total number of workdays in the given year. (Monday to Friday) - -## Notes - -There are either 260, 261, 262 workdays in a calendar year. - -* In a normal year there is 261 workdays unless the year both starts and finishes on a weekend (i.e. there are 260 workdays if the year starts on a Saturday or Sunday); -* In a leap year there is only 260 working days if Jan 1st is a Saturday & Dec 31st is a Sunday; 261 if Jan 1st is a Sunday or Dec 31st is a Saturday, 262 otherwise. +***You are given a list of numbers. Write a script to implement JortSort. It should return true/false depending if the given list of numbers are already sorted.*** ## The solution -So we basically need 2 pieces of information given a year? - - * Is it a leap year - * What is the first day of the year. - -We can then use a look up table which stores the number of working days (over 260) for non leap years and for leap years: - -| | Sun | Mon | Tue | Wed | Thu | Fri | Sat | -| ----------------------- | --: | --: | --: | --: | --: | --: | --: | -| **day no** | 0 | 1 | 2 | 3 | 4 | 5 | 6 | -| **#days non-leap year** | 0 | 1 | 1 | 1 | 1 | 1 | 0 | -| **#days leap year** | 1 | 2 | 2 | 2 | 2 | 1 | 0 | - -We break this calculation into 3 functions: - - * `work_days` - this does the look up - * `leap_year` - tests for leap year - * `zellers_congruence_jan_1` - uses Zeller's congruence to work out first day of the year {works for the Gregorian calendar} - -All of which -```perl -my @EXTRA_WORKDAYS = ( [0,1,1,1,1,1,0], [1,2,2,2,2,1,0] ); - -sub leap_year { - $_[0]&3 || (!($_[0]%100) && $_[0]%400) ? 0 : 1; -} -sub zellers_congruence_jan_1 { - ( 1 + $_[0]%100 + ($_[0]%100>>2) - ($_[0]/100<<1) + ($_[0]/400>>0) ) % 7; -} - -sub work_days { - 260 + $EXTRA_WORKDAYS[ leap_year $_[0] ][ zellers_congruence_jan_1 $_[0] - 1 ]; -} +# Task 2 - Long Primes -``` - -# Task 2 - Split Number - -***You are given a perfect square, Write a script to figure out if the square root the given number is same as sum of 2 or more splits of the given number.*** +***Write a script to generate first 5 Long Primes. A prime number `p` is called Long Prime if `1/p` has an infinite decimal expansion repeating every `p-1` digits.*** ## Solution -We use recursion to simplify the problem - first we note that for the sqrt to be the sum of splits of the number then there are always 2 sums except in two trivial cases 0 & 1 (`n^2 = n`) so we can check this in the first wrapper function. - -As the first stage in the loop requires some "setup" - we write a wrapper function that: - - * Checks for the edge case of 0/1; - * Passes in the square root of `$n` as the total we need to compare against in the more generic `split_no` function which works out if there is a way of summing groups of digits. - -`split_no` does all the hard work. - -It takes 2 parameters - the sum required add a string of digits. We call the function recursively - - * If the the string of digits is empty we have reached the end - and check to see if the remaining sum is zero. - * If sum is less than 0 then we return 0 - no match. - * If not we split the string into 2 pieces in all ways possible and call the function. - * We reduce the sum required by the first part of the string; - * And pass the second part of the string as the string of digits. - -```perl -sub check_square { - return $_[0] <= 1 ? 0 : split_no( sqrt($_[0]), $_[0] ); -} - -sub split_no { - my( $sum, $str ) = @_; - return 0 if $sum < 0; - return 0 if $str eq '' && $sum; - return 1 if $str eq ''; - return 1 if grep { split_no( ($sum - substr $str,$_) , substr $str, 0, $_ ) } - 0 .. -1 + length $str; - return 0; -} - -``` diff --git a/challenge-139/james-smith/blog.txt b/challenge-139/james-smith/blog.txt new file mode 100644 index 0000000000..6a2d58b005 --- /dev/null +++ b/challenge-139/james-smith/blog.txt @@ -0,0 +1 @@ +https://github.com/drbaggy/perlweeklychallenge-club/new/master/challenge-139/james-smith diff --git a/challenge-139/james-smith/perl/ch-1.pl b/challenge-139/james-smith/perl/ch-1.pl new file mode 100644 index 0000000000..2a4f349ec4 --- /dev/null +++ b/challenge-139/james-smith/perl/ch-1.pl @@ -0,0 +1,25 @@ +#!/usr/local/bin/perl + +use strict; + +use warnings; +use feature qw(say); +use Test::More; +use Benchmark qw(cmpthese timethis); +use Data::Dumper qw(Dumper); + +my @TESTS = ( + [ [1..5], 1 ], + [ [1,3,2,4,5], 0 ], +); + +is( in_order(@{$_->[0]}), $_->[1] ) foreach @TESTS; + +done_testing(); + +sub in_order { + my $p = shift; + ($p>$_) ? (return 0) : ($p=$_) foreach @_; + return 1; +} + diff --git a/challenge-139/james-smith/perl/ch-2.pl b/challenge-139/james-smith/perl/ch-2.pl new file mode 100644 index 0000000000..5f3150a086 --- /dev/null +++ b/challenge-139/james-smith/perl/ch-2.pl @@ -0,0 +1,25 @@ +#!/usr/local/bin/perl + +use strict; + +use warnings; +use feature qw(say); + +my( $N, $p, @primes, @long_primes ) = + ( @ARGV ? $ARGV[0] : 5, 1, 2 ); + +O: while( (@long_primes < $N) && ($p += 2) ) { + ($p % $_) || (next O) for @primes; ## next if not prime... + push @long_primes, $p if $p - rec_len($p) == 1; + push @primes, $p; +} + +say $_ for @long_primes; + +sub rec_len { + my( $D, $N, $s ) = ( shift, 1, '' ); + ($s,$N) = $D>$N ? ($s.0, $N.0) + : ($s.int($N/$D),($N%$D).0) for 0 .. 2*$D; + $s =~ m{(\d+?)\1+$}; + length $1; +} |
