aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordcw <d.white@imperial.ac.uk>2021-11-21 22:25:01 +0000
committerdcw <d.white@imperial.ac.uk>2021-11-21 22:25:01 +0000
commit9b869e910aa83dff00bee8d1769f86d4c993b497 (patch)
tree0bb02ae8b926aa76ff2504faf658e0e5d639c54b
parent6e68f355029fe1ab7246eabada8b99271a0eb657 (diff)
downloadperlweeklychallenge-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/README67
-rw-r--r--challenge-139/duncan-c-white/perl/MakePrimes.pm91
-rwxr-xr-xchallenge-139/duncan-c-white/perl/ch-1.pl56
-rwxr-xr-xchallenge-139/duncan-c-white/perl/ch-2.pl120
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";