diff options
| author | dcw <d.white@imperial.ac.uk> | 2021-11-21 22:25:01 +0000 |
|---|---|---|
| committer | dcw <d.white@imperial.ac.uk> | 2021-11-21 22:25:01 +0000 |
| commit | 9b869e910aa83dff00bee8d1769f86d4c993b497 (patch) | |
| tree | 0bb02ae8b926aa76ff2504faf658e0e5d639c54b | |
| parent | 6e68f355029fe1ab7246eabada8b99271a0eb657 (diff) | |
| download | perlweeklychallenge-club-9b869e910aa83dff00bee8d1769f86d4c993b497.tar.gz perlweeklychallenge-club-9b869e910aa83dff00bee8d1769f86d4c993b497.tar.bz2 perlweeklychallenge-club-9b869e910aa83dff00bee8d1769f86d4c993b497.zip | |
imported my solutions to this week's challenges.. enjoyed both..
| -rw-r--r-- | challenge-139/duncan-c-white/README | 67 | ||||
| -rw-r--r-- | challenge-139/duncan-c-white/perl/MakePrimes.pm | 91 | ||||
| -rwxr-xr-x | challenge-139/duncan-c-white/perl/ch-1.pl | 56 | ||||
| -rwxr-xr-x | challenge-139/duncan-c-white/perl/ch-2.pl | 120 |
4 files changed, 294 insertions, 40 deletions
diff --git a/challenge-139/duncan-c-white/README b/challenge-139/duncan-c-white/README index 168bfb1a4f..d2eacb517a 100644 --- a/challenge-139/duncan-c-white/README +++ b/challenge-139/duncan-c-white/README @@ -1,58 +1,45 @@ -TASK #1 - Workdays +TASK #1 - JortSort -You are given a year, $year in 4-digits form. +You are given a list of numbers. -Write a script to calculate the total number of workdays in the given year. -For the task, we consider, Monday - Friday as workdays. +Write a script to implement JortSort. It should return true/false +depending if the given list of numbers are already sorted. -Example 1 - - Input: $year = 2021 - Output: 261 - -Example 2 - - Input: $year = 2020 - Output: 262 - -MY NOTES: Pretty easy. Essentially: iterate over all days in $year, inc -count if day_of_week(that day) is a week day (Mon..Fri). Date::Simple -looks like it can do everything we need. +Example 1: + Input: @n = (1,2,3,4,5) + Output: 1 -TASK #2 - Split Number + Since the array is sorted, it prints 1. -You are given a perfect square. +Example 2: -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. + Input: @n = (1,3,2,4,5) + Output: 0 -Example 1 + Since the array is NOT sorted, it prints 0. - Input: $n = 81 - Output: 1 +MY NOTES: Very easy. Don't know what "JortSort" means, but this is +just the linear "IsSorted" function.. - Since, sqrt(81) = 8 + 1 -Example 2 +TASK #2 - Long Primes - Input: $n = 9801 - Output: 1 +Write a script to generate first 5 Long Primes. - Since, sqrt(9801) = 98 + 0 + 1 +A prime number (p) is called Long Prime if (1/p) has an infinite decimal expansion repeating every (p-1) digits. -Example 3 +Example - Input: $n = 36 - Output: 0 + 7 is a long prime since 1/7 = 0.142857142857... + The repeating part (142857) size is 6 i.e. one less than the prime number 7. - Since, sqrt(36) != 3 + 6 + Also 17 is a long prime since 1/17 = 0.05882352941176470588235294117647... + The repeating part (0588235294117647) size is 16 i.e. one less than the prime number 17. -MY NOTES: Sounds pretty easy. The only tricky part is identifying all -distinct "splits" of the number. Is there a "binary counting" method, -where bit i being true means: split the number between digit i and i+1? + Another example, 2 is not a long prime as 1/2 = 0.5. + There is no repeating part in this case. -BONUS: I was interested in how many perfect squares do have this "split -summing to the sqrt" property, so I added tabulate-split-sums which -tries the first N perfect squares, and prints out those that do have -this property. 81 is the first, 100 the second, 1296 the third etc.. +MY NOTES: Sounds pretty easy. First generate some primes (have code to do that using Sieve of + Erathosthenes). Then check each prime p to see if 1/p's 2*p long decimal fraction + contains the same sequence p-1 digits long. diff --git a/challenge-139/duncan-c-white/perl/MakePrimes.pm b/challenge-139/duncan-c-white/perl/MakePrimes.pm new file mode 100644 index 0000000000..7261977c57 --- /dev/null +++ b/challenge-139/duncan-c-white/perl/MakePrimes.pm @@ -0,0 +1,91 @@ +# +# mkprimes module (converted from mkprimes.c) +# + +use strict; +use warnings; +use Function::Parameters; + + +my $debug = 0; +my @foundprimes; # remember all primes we've found.. + + +# +# my @primes = primes_upto( $n ); +# Find all primes up to N; return a list of all such primes +# (note that 1 is not usually considered a prime) +# +fun primes_upto( $n ) +{ + my @isprime; + + for( my $i=1; $i<=$n; $i++ ) + { + $isprime[$i] = 1; # initially + } + + # now sieve the non-primes out.. + my $upper = int(sqrt($n)); + printf( "debug: n=%d, upper=%d\n", $n, $upper ) if $debug; + for( my $i=2; $i<=$upper; $i++ ) + { + if( $isprime[$i] ) + { + #printf( "debug: crossing out multiples of %d\n", $i ); + for( my $j=$i*$i; $j<=$n; $j+=$i ) + { + $isprime[$j] = 0; + } + } + } + + # after sieving, extract the primes + my @primes = grep { $isprime[$_] } 2..$n; + + # remember them + @foundprimes = @primes; + + return @primes; +} + + +# +# my @moreprimes = more_primes( $n, $m ); +# Need more primes! Have @foundprimes up to $n, but need +# to sieve primes from $n+1..$m, so re-sieve, return +# a list of all new primes (in the range $n+1..$m) that we find. +# +fun more_primes( $n, $m ) +{ + my %isprime; + + print "finding more primes from ", $n+1, "..$m\n"; + + for( my $i=$n+1; $i<=$m; $i++ ) + { + $isprime{$i} = 1; # pre-sieving + } + + # now sieve the non-primes out.. + foreach my $prime (@foundprimes) + { + # find first multiple of $prime > $n + my $mult = $prime * (int($n/$prime)+1); + + #print "debug: xo multiples of $prime from $mult to $m\n"; + + for( my $j=$mult; $j<=$m; $j+=$prime ) + { + delete $isprime{$j}; + } + } + + # after sieving, extract the primes + my @primes = grep { $isprime{$_} } $n+1..$m; + push @foundprimes, @primes; + return @primes; +} + + +1; diff --git a/challenge-139/duncan-c-white/perl/ch-1.pl b/challenge-139/duncan-c-white/perl/ch-1.pl new file mode 100755 index 0000000000..e48ccf3a5a --- /dev/null +++ b/challenge-139/duncan-c-white/perl/ch-1.pl @@ -0,0 +1,56 @@ +#!/usr/bin/perl +# +# TASK #1 - JortSort +# +# 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. +# +# Example 1: +# +# Input: @n = (1,2,3,4,5) +# Output: 1 +# +# Since the array is sorted, it prints 1. +# +# Example 2: +# +# Input: @n = (1,3,2,4,5) +# Output: 0 +# +# Since the array is NOT sorted, it prints 0. +# +# MY NOTES: Very easy. Don't know what "JortSort" means, but this is +# just the linear "IsSorted" function.. +# + +use strict; +use warnings; +use feature 'say'; +use Getopt::Long; +use Function::Parameters; +#use Data::Dumper; + + +my $debug=0; +die "Usage: is-sorted list(numbers)\n" unless + GetOptions( "debug"=>\$debug ) && @ARGV>0; + +# +# my $issorted = issorted( @a ); +# Return 1 iff @a is already sorted. 0 otherwise. +# +fun issorted( @a ) +{ + foreach my $i (0..$#a-1) + { + return 0 if $a[$i] > $a[$i+1]; + } + return 1; +} + + +my @x = @ARGV; +my $issorted = issorted( @x ); +say $issorted; diff --git a/challenge-139/duncan-c-white/perl/ch-2.pl b/challenge-139/duncan-c-white/perl/ch-2.pl new file mode 100755 index 0000000000..88126e9fa9 --- /dev/null +++ b/challenge-139/duncan-c-white/perl/ch-2.pl @@ -0,0 +1,120 @@ +#!/usr/bin/perl +# +# TASK #2 - Long Primes +# +# 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. +# +# Example +# +# 7 is a long prime since 1/7 = 0.142857142857... +# The repeating part (142857) size is 6 i.e. one less than the prime number 7. +# +# Also 17 is a long prime since 1/17 = 0.05882352941176470588235294117647... +# The repeating part (0588235294117647) size is 16 i.e. one less than the prime number 17. +# +# Another example, 2 is not a long prime as 1/2 = 0.5. +# There is no repeating part in this case. +# +# MY NOTES: Sounds pretty easy. First generate some primes (have code to do that using Sieve of +# Erathosthenes). Then check each prime p to see if 1/p's 2*p long decimal fraction +# repeats after p-1 digits (and doesn't repeat after any shorter digit sequence) +# + +use strict; +use warnings; +use feature 'say'; +use Function::Parameters; +use Getopt::Long; +use Data::Dumper; +use List::Util qw(sum); + +use lib qw(.); +use MakePrimes; + +my $debug = 0; + +die "Usage: first-n-long-primes [-d|--debug] N\n" + unless GetOptions( "debug"=>\$debug ) && @ARGV==1; +my $n = shift @ARGV // 5; + +my @primes = primes_upto( 20*$n ); # complete guess + +# +# my @d = divide1divP( $ndigits, $p ); +# Compute and return the first $ndigits of the 1/$p decimal fraction +# (purely the 0.ddddddddd part) as an array of digits. +# +fun divide1divP( $ndigits, $p ) +{ + my $numer = 1; + my @d; + foreach my $i (1..$ndigits) + { + $numer *= 10; + my $x = int($numer/$p); + #say "debug: numer=$numer, p=$p, digit=$x"; + push @d, $x; + $numer -= $x*$p; + } + return @d; +} + + +# +# my $repeatN = repeateveryN( $n, @d ); +# Return 1 iff the sequence @d (at least 2*$n elements long) +# repeats every $n elements; 0 otherwise. +# +fun repeatN( $n, @d ) +{ + die "repeatN($n): n<1\n" if $n<1; + my $l = @d; + die "repeatN($n): sequence not long enough: length $l" + unless $l >= 2*$n; + + foreach my $i ($n..$l-1) + { + return 0 unless $d[$i%$n] == $d[$i]; + } + #say "sequence ".join(',',@d)." repeats every $n digits"; + return 1; +} + + +# +# my $islong = longprime($p); +# Return 1 iff 1/p's 2*p digit long decimal fraction +# repeats the same sequence after p-1 digits (and +# doesn't repeat after any shorter sequence). +# +fun longprime( $p ) +{ + say "checking longprime $p" if $debug; + my @d = divide1divP( 2*$p, $p ); + #say "decimal fraction is @d"; + + return 0 unless repeatN( $p-1, @d ); # fail unless it repeats every $p-1 digits + foreach my $i (1..$p-2) # fail if it repeats any shorter num digits + { + return 0 if repeatN( $i, @d ); + } + return 1; +} + + +my @longprimes; +my $l=0; +foreach my $p (@primes) +{ + if( longprime($p) ) + { + push @longprimes, $p; + $l = @longprimes; + say "$p is longprime; length $l" if $debug; + } + last if $l==$n; +} +my $len = @longprimes; +say "First $len long primes: @longprimes"; |
