aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordcw <d.white@imperial.ac.uk>2021-10-17 22:57:12 +0100
committerdcw <d.white@imperial.ac.uk>2021-10-17 22:57:12 +0100
commite66cf656367950f8484bd2a1545d09917c9b4b96 (patch)
tree14c61c1da02458318c35ea2bca317e60ee5674a2
parent78cc5db60b6a54cd365b67b17013b72db7ed4268 (diff)
downloadperlweeklychallenge-club-e66cf656367950f8484bd2a1545d09917c9b4b96.tar.gz
perlweeklychallenge-club-e66cf656367950f8484bd2a1545d09917c9b4b96.tar.bz2
perlweeklychallenge-club-e66cf656367950f8484bd2a1545d09917c9b4b96.zip
imported my solutions to this week's tasks
-rw-r--r--challenge-134/duncan-c-white/README62
-rwxr-xr-xchallenge-134/duncan-c-white/perl/ch-1.pl69
-rwxr-xr-xchallenge-134/duncan-c-white/perl/ch-2.pl102
3 files changed, 206 insertions, 27 deletions
diff --git a/challenge-134/duncan-c-white/README b/challenge-134/duncan-c-white/README
index 7c8d08653f..83854546f8 100644
--- a/challenge-134/duncan-c-white/README
+++ b/challenge-134/duncan-c-white/README
@@ -1,44 +1,52 @@
-TASK #1 - Integer Square Root
+TASK #1 - Pandigital Numbers
-You are given a positive integer $N.
+Write a script to generate first 5 Pandigital Numbers in base 10.
-Write a script to calculate the integer square root of the given number.
+As per the wikipedia, it says:
-Please avoid using a built-in function. Find out more about it:
+A pandigital number is an integer that in a given base has among its
+significant digits each digit used in the base at least once.
+The smallest base 10 pandigital number is 1023456789, and subsequent
+ones are lexicographic permutations, ie. 1023456798, 1023456879...
-https://en.wikipedia.org/wiki/Integer_square_root
+MY NOTES: Basically just needs a standard lexicographic permutation algorithm,
+with the initial value to permute being 1023456789.
-Examples
+TASK #2 - Distinct Terms Count
- Input: $N = 10
- Output: 3
+You are given 2 positive numbers, $m and $n.
- Input: $N = 27
- Output: 5
+Write a script to generate multiplication table and display count of distinct terms.
- Input: $N = 85
- Output: 9
+Example 1
- Input: $N = 101
- Output: 10
+Input: $m = 3, $n = 3
+Output:
-MY NOTES: Pretty easy as the Wikipedia page shows a C implementation
+ x | 1 2 3
+ --+------
+ 1 | 1 2 3
+ 2 | 2 4 6
+ 3 | 3 6 9
+Distinct Terms: 1, 2, 3, 4, 6, 9
+Count: 6
-TASK #2 - Smith Numbers
+Example 2
-Write a script to generate first 10 Smith Numbers in base 10.
+Input: $m = 3, $n = 5
+Output:
-According to Wikipedia:
+ x | 1 2 3 4 5
+ --+--------------
+ 1 | 1 2 3 4 5
+ 2 | 2 4 6 8 10
+ 3 | 3 6 9 12 15
-"In number theory, a Smith number is a composite number for which, in
-a given number base, the sum of its digits is equal to the sum of the
-digits in its prime factorization in the given number base."
+Distinct Terms: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15
+Count: 11
-MY NOTES: Ok, an example in the Wikipedia clarifies this:
- 4937775 = 3**1 5**2 658371 (prime factors)
- 4 + 9 + 3 + 7 + 7 + 7 + 5 = 42
- 3 x· 1 + 5x 2 + (6 + 5 + 8 + 3 + 7) x 1 = 42 too
-
-Should be quite straightforward.
+MY NOTES: Pretty easy, the distinct terms just need a set (hash) as usual.
+The tricky bit is the pretty layout of the multiplication table, especially
+getting the correct column widths..
diff --git a/challenge-134/duncan-c-white/perl/ch-1.pl b/challenge-134/duncan-c-white/perl/ch-1.pl
new file mode 100755
index 0000000000..30f2d76e2d
--- /dev/null
+++ b/challenge-134/duncan-c-white/perl/ch-1.pl
@@ -0,0 +1,69 @@
+#!/usr/bin/perl
+#
+# TASK #1 - Pandigital Numbers
+#
+# Write a script to generate first 5 Pandigital Numbers in base 10.
+#
+# As per the wikipedia, it says:
+#
+# A pandigital number is an integer that in a given base has among its
+# significant digits each digit used in the base at least once.
+# The smallest base 10 pandigital number is 1023456789, and subsequent
+# ones are lexicographic permutations, ie. 1023456798, 1023456879...
+#
+# MY NOTES: Basically just needs a standard lexicographic permutation algorithm,
+# with the initial value to permute being 1023456789.
+#
+
+use strict;
+use warnings;
+use feature 'say';
+use Getopt::Long;
+use Function::Parameters;
+#use Data::Dumper;
+
+#
+# my $next = next_perm( $val );
+# Find and return the next permutation in lexicographic order
+# of $val. Return undef is $val is the last permutation (in order).
+# Algorithm treats $val as an array of digits a[n]:
+# 1. Find the largest index k such that a[k] < a[k + 1]. If no such index exists,
+# the permutation is the last permutation.
+# 2. Find the largest index l greater than k such that a[k] < a[l].
+# 3. Swap the value of a[k] with that of a[l].
+# 4. Reverse the sequence from a[k + 1] up to and including the final element a[n].
+#
+fun next_perm( $val )
+{
+ my @a = split( //, $val );
+ my( $k, $l );
+ my $n = @a-1;
+ for( $k=$n-1; $k>=0 && $a[$k]>=$a[$k+1]; $k-- )
+ {
+ }
+ return undef if $k<0;
+ for( $l=$n; $l>$k && $a[$k]>=$a[$l]; $l-- )
+ {
+ }
+ ( $a[$k], $a[$l] ) = ( $a[$l], $a[$k] );
+
+ # reverse a[k+1]..a[n]
+ @a[$k+1..$n] = reverse @a[$k+1..$n];
+
+ return join( '', @a );
+}
+
+
+my $debug=0;
+die "Usage: first-N-base-10-pandigital-numbers [N, default 5]\n" unless
+ GetOptions( "debug"=>\$debug ) && @ARGV<2;
+my $firstn = @ARGV == 1 ? shift @ARGV : 5;
+
+my $pandigital = "1023456789";
+
+for( my $i=1; $i<=$firstn; $i++ )
+{
+ die "fallen off last perm\n" unless defined $pandigital;
+ say $pandigital;
+ $pandigital = next_perm( $pandigital );
+}
diff --git a/challenge-134/duncan-c-white/perl/ch-2.pl b/challenge-134/duncan-c-white/perl/ch-2.pl
new file mode 100755
index 0000000000..db5613df26
--- /dev/null
+++ b/challenge-134/duncan-c-white/perl/ch-2.pl
@@ -0,0 +1,102 @@
+#!/usr/bin/perl
+#
+# TASK #2 - Distinct Terms Count
+#
+# You are given 2 positive numbers, $m and $n.
+#
+# Write a script to generate multiplication table and display count of distinct terms.
+#
+# Example 1
+#
+# Input: $m = 3, $n = 3
+# Output:
+#
+# x | 1 2 3
+# --+------
+# 1 | 1 2 3
+# 2 | 2 4 6
+# 3 | 3 6 9
+#
+# Distinct Terms: 1, 2, 3, 4, 6, 9
+# Count: 6
+#
+# Example 2
+#
+# Input: $m = 3, $n = 5
+# Output:
+#
+# x | 1 2 3 4 5
+# --+--------------
+# 1 | 1 2 3 4 5
+# 2 | 2 4 6 8 10
+# 3 | 3 6 9 12 15
+#
+# Distinct Terms: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15
+# Count: 11
+#
+# MY NOTES: Pretty easy, the distinct terms just need a set (hash) as usual.
+# The tricky bit is the pretty layout of the multiplication table, especially
+# getting the correct column widths..
+#
+
+use strict;
+use warnings;
+use feature 'say';
+use Function::Parameters;
+use Getopt::Long;
+use Data::Dumper;
+
+my $debug = 0;
+
+die "Usage: distinct-terms-count [-d|--debug] M N\n"
+ unless GetOptions( "debug"=>\$debug ) && @ARGV==2;
+my( $m, $n ) = @ARGV;
+my $table = form_table( $m, $n );
+say $table;
+
+# Build the distinct values.. messy to do this while formatting the table..
+my %distinct;
+for( my $i=1; $i<=$m; $i++ )
+{
+ for( my $j=1; $j<=$n; $j++ )
+ {
+ $distinct{$i*$j}++;
+ }
+}
+my @distinct = sort { $a <=> $b } keys %distinct;
+my $count = @distinct;
+
+say "Distinct Terms: ". join(', ', @distinct);
+say "Count: $count";
+
+
+#
+# my $table = form_table( $m, $n );
+# Form a neatly formatted times table for $m rows x $n columns,
+# and return the single $m+2 line string.
+#
+fun form_table( $m, $n )
+{
+ my $width = 1 + int( log($n*$m)/log(10) );
+ my $firstw = 1 + int(log($m)/log(10));
+
+ my @result;
+
+ my $row = sprintf("%${firstw}s", "x") . " | ";
+ $row .= sprintf("%${firstw}d ", 1 );
+ $row .= sprintf("%${width}d ", $_ ) for 2..$n;
+ push @result, $row;
+
+ $row = '-'x($firstw+1)."+".('-'x($firstw+$width*($n-1)+$n));
+ push @result, $row;
+
+ for( my $i=1; $i<=$m; $i++ )
+ {
+ $row = sprintf("%${firstw}d", $i). " | ";
+ $row .= sprintf("%${firstw}d ", $i );
+ $row .= sprintf("%${width}d ", $i*$_ ) for 2..$n;
+ push @result, $row;
+ }
+
+ return join("\n", @result);
+}