aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad S Anwar <Mohammad.Anwar@yahoo.com>2022-07-25 01:21:29 +0100
committerGitHub <noreply@github.com>2022-07-25 01:21:29 +0100
commit7f43710833ae0bcf6e2dc923378c0ae5df2934db (patch)
tree60ac47f211a54629aac4d19f130da33e03ff6fca
parent588154e83ece05031c0d2f613a66829138cb56e9 (diff)
parent5badff2e0666b32a31c5704e6d54d1990bfcdad4 (diff)
downloadperlweeklychallenge-club-7f43710833ae0bcf6e2dc923378c0ae5df2934db.tar.gz
perlweeklychallenge-club-7f43710833ae0bcf6e2dc923378c0ae5df2934db.tar.bz2
perlweeklychallenge-club-7f43710833ae0bcf6e2dc923378c0ae5df2934db.zip
Merge pull request #6494 from dcw803/master
solutions to ch#'174 plus belated attempts at ch#172 and 173
-rw-r--r--challenge-172/duncan-c-white/C/Makefile16
-rw-r--r--challenge-172/duncan-c-white/C/README7
-rw-r--r--challenge-172/duncan-c-white/C/args.c136
-rw-r--r--challenge-172/duncan-c-white/C/args.h6
-rw-r--r--challenge-172/duncan-c-white/C/ch-1.c109
-rw-r--r--challenge-172/duncan-c-white/C/ch-2.c108
-rw-r--r--challenge-172/duncan-c-white/C/primes.c67
-rw-r--r--challenge-172/duncan-c-white/C/primes.h1
-rw-r--r--challenge-172/duncan-c-white/README43
-rw-r--r--challenge-172/duncan-c-white/perl/MakePrimes.pm90
-rwxr-xr-xchallenge-172/duncan-c-white/perl/ch-1.pl68
-rwxr-xr-xchallenge-172/duncan-c-white/perl/ch-2.pl63
-rw-r--r--challenge-173/duncan-c-white/C/.cbuild3
-rw-r--r--challenge-173/duncan-c-white/C/Makefile14
-rw-r--r--challenge-173/duncan-c-white/C/README9
-rw-r--r--challenge-173/duncan-c-white/C/args.c174
-rw-r--r--challenge-173/duncan-c-white/C/args.h7
-rw-r--r--challenge-173/duncan-c-white/C/ch-1.c91
-rw-r--r--challenge-173/duncan-c-white/C/ch-2.c58
-rw-r--r--challenge-173/duncan-c-white/README51
-rwxr-xr-xchallenge-173/duncan-c-white/perl/ch-1.pl90
-rwxr-xr-xchallenge-173/duncan-c-white/perl/ch-2.pl59
-rw-r--r--challenge-174/duncan-c-white/C/.cbuild2
-rw-r--r--challenge-174/duncan-c-white/C/Makefile14
-rw-r--r--challenge-174/duncan-c-white/C/README12
-rw-r--r--challenge-174/duncan-c-white/C/args.c174
-rw-r--r--challenge-174/duncan-c-white/C/args.h7
-rw-r--r--challenge-174/duncan-c-white/C/ch-1.c88
-rw-r--r--challenge-174/duncan-c-white/C/ch-1a.c116
-rw-r--r--challenge-174/duncan-c-white/README60
-rw-r--r--challenge-174/duncan-c-white/perl/Perms.pm46
-rwxr-xr-xchallenge-174/duncan-c-white/perl/ch-1.pl60
-rwxr-xr-xchallenge-174/duncan-c-white/perl/ch-1a.pl62
-rwxr-xr-xchallenge-174/duncan-c-white/perl/ch-1b.pl79
-rwxr-xr-xchallenge-174/duncan-c-white/perl/ch-1c.pl75
-rwxr-xr-xchallenge-174/duncan-c-white/perl/ch-1d.pl79
-rwxr-xr-xchallenge-174/duncan-c-white/perl/ch-1e.pl83
-rwxr-xr-xchallenge-174/duncan-c-white/perl/ch-1f.pl84
-rwxr-xr-xchallenge-174/duncan-c-white/perl/ch-1g.pl85
-rwxr-xr-xchallenge-174/duncan-c-white/perl/ch-2.pl77
-rwxr-xr-xchallenge-174/duncan-c-white/perl/timeall5
41 files changed, 2421 insertions, 57 deletions
diff --git a/challenge-172/duncan-c-white/C/Makefile b/challenge-172/duncan-c-white/C/Makefile
new file mode 100644
index 0000000000..c1c8318a24
--- /dev/null
+++ b/challenge-172/duncan-c-white/C/Makefile
@@ -0,0 +1,16 @@
+BUILD = ch-1 ch-2
+CC = gcc
+CFLAGS = -Wall # -g
+LDLIBS = -lm
+
+all: $(BUILD)
+
+clean:
+ /bin/rm -f $(BUILD) *.o core a.out
+
+primes.o: primes.c
+
+ch-1: ch-1.o primes.o args.o
+ch-1.o: ch-1.c args.h
+ch-2: ch-2.o args.o
+ch-2.o: ch-2.c args.h
diff --git a/challenge-172/duncan-c-white/C/README b/challenge-172/duncan-c-white/C/README
new file mode 100644
index 0000000000..931c4d8879
--- /dev/null
+++ b/challenge-172/duncan-c-white/C/README
@@ -0,0 +1,7 @@
+Thought I'd also have a go at translating ch-1.pl and ch-2.pl into C..
+
+Both C versions produce identical (non-debugging) output to my Perl originals
+
+ch-1.c uses primes.[ch], a prime number generator module that I wrote ages ago,
+and I've finally split out the command-line argument processing code into
+args.[ch].
diff --git a/challenge-172/duncan-c-white/C/args.c b/challenge-172/duncan-c-white/C/args.c
new file mode 100644
index 0000000000..73a471464a
--- /dev/null
+++ b/challenge-172/duncan-c-white/C/args.c
@@ -0,0 +1,136 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+
+
+bool debug = false;
+
+
+// process_flag_noarg( name, argc, argv );
+// Process the -d flag, and check that there are no
+// remaining arguments.
+void process_flag_noarg( char *name, int argc, char **argv )
+{
+ int arg=1;
+ if( argc>1 && strcmp( argv[arg], "-d" ) == 0 )
+ {
+ debug = true;
+ arg++;
+ }
+
+ int left = argc-arg;
+ if( left != 0 )
+ {
+ fprintf( stderr, "Usage: %s [-d]\n", name );
+ exit(1);
+ }
+}
+
+
+// process_onenumarg( name, argc, argv, &n );
+// Process the -d flag, and check that there is a single
+// remaining numeric argument, putting it into n
+void process_onenumarg( char *name, int argc, char **argv, int *n )
+{
+ int arg=1;
+ if( argc>1 && strcmp( argv[arg], "-d" ) == 0 )
+ {
+ debug = true;
+ arg++;
+ }
+
+ int left = argc-arg;
+ if( left != 1 )
+ {
+ fprintf( stderr, "Usage: %s [-d] n\n", name );
+ exit(1);
+ }
+
+ // element is in argv[arg]
+
+ if( debug )
+ {
+ printf( "debug: remaining arguments are in arg=%d, "
+ "firstn=%s\n", arg, argv[arg] );
+ }
+
+ *n = atoi( argv[arg] );
+}
+
+
+// process_twonumargs( name, argc, argv, &m, &n );
+// Process the -d flag, and check that there are 2
+// remaining numeric arguments, putting them into m and n
+void process_twonumargs( char *name, int argc, char **argv, int *m, int *n )
+{
+ int arg=1;
+ if( argc>1 && strcmp( argv[arg], "-d" ) == 0 )
+ {
+ debug = true;
+ arg++;
+ }
+
+ int left = argc-arg;
+ if( left != 2 )
+ {
+ fprintf( stderr, "Usage: %s [-d] m n\n", name );
+ exit(1);
+ }
+
+ // elements are in argv[arg] and argv[arg+1]
+
+ if( debug )
+ {
+ printf( "debug: remaining arguments are in arg=%d, "
+ "firstn=%s, secondn=%s\n",
+ arg, argv[arg], argv[arg+1] );
+ }
+
+ *m = atoi( argv[arg++] );
+ *n = atoi( argv[arg] );
+}
+
+// int arr[100];
+// int nel = process_listnumargs( name, argc, argv, arr, 100 );
+// Process the -d flag, and check that there are >= 2
+// remaining numeric arguments, putting them into arr[0..nel-1]
+// and returning nel.
+int process_listnumargs( char *name, int argc, char **argv, int *arr, int maxel )
+{
+ int arg=1;
+ if( argc>1 && strcmp( argv[arg], "-d" ) == 0 )
+ {
+ debug = true;
+ arg++;
+ }
+
+ int left = argc-arg;
+ if( left < 2 )
+ {
+ fprintf( stderr, "Usage: %s [-d] list_of_numeric_args\n", name );
+ exit(1);
+ }
+ if( left > maxel )
+ {
+ fprintf( stderr, "%s: more than %d args\n", name, maxel );
+ exit(1);
+ }
+
+ // elements are in argv[arg], argv[arg+1]...
+
+ if( debug )
+ {
+ printf( "debug: remaining arguments are in arg=%d, "
+ "firstn=%s, secondn=%s..\n",
+ arg, argv[arg], argv[arg+1] );
+ }
+
+ int nel = 0;
+ for( int i=arg; i<argc; i++ )
+ {
+ arr[nel++] = atoi( argv[i] );
+ }
+ arr[nel] = -1;
+ return nel;
+}
diff --git a/challenge-172/duncan-c-white/C/args.h b/challenge-172/duncan-c-white/C/args.h
new file mode 100644
index 0000000000..b3e4227183
--- /dev/null
+++ b/challenge-172/duncan-c-white/C/args.h
@@ -0,0 +1,6 @@
+extern bool debug;
+
+extern void process_flag_noarg( char * name, int argc, char ** argv );
+extern void process_onenumarg( char * name, int argc, char ** argv, int * n );
+extern void process_twonumargs( char * name, int argc, char ** argv, int * m, int * n );
+extern int process_listnumargs( char * name, int argc, char ** argv, int * arr, int maxel );
diff --git a/challenge-172/duncan-c-white/C/ch-1.c b/challenge-172/duncan-c-white/C/ch-1.c
new file mode 100644
index 0000000000..95c43e5d3e
--- /dev/null
+++ b/challenge-172/duncan-c-white/C/ch-1.c
@@ -0,0 +1,109 @@
+/*
+ * TASK 1 - Prime Partition
+ *
+ * GUEST LANGUAGE: THIS IS THE C VERSION OF ch-1.pl.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+//#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include "args.h"
+#include "primes.h"
+
+
+
+#define MAXSTRINGLEN 800
+typedef char string[MAXSTRINGLEN];
+
+
+#define MAXPRIMES 512
+
+
+int main( int argc, char **argv )
+{
+ int m, n;
+ process_twonumargs( "prime-partition", argc, argv, &m, &n );
+
+ // get all primes less than m
+ int numprimes;
+ int *primes = primes_upto( m, &numprimes );
+ if( debug )
+ {
+ printf( "found %d primes, %d, %d, %d...%d\n",
+ numprimes, primes[0], primes[1], primes[2],
+ primes[numprimes-1] );
+ }
+ assert( numprimes < MAXPRIMES );
+
+ string pps = ""; // single string "pp1 or pp2 ..."
+
+ int two2n = 1<<numprimes;
+
+ for( int i=1; i<two2n; i++ )
+ {
+ int chosen[MAXPRIMES];
+ int nchosen = 0;
+ int sum = 0;
+ int mask = two2n>>1;
+ for( int pos=0; pos<numprimes; pos++ )
+ {
+ if( (i&mask) )
+ {
+ chosen[nchosen++] = primes[pos];
+ sum += primes[pos];
+ #if 0
+ if( debug )
+ {
+ printf(
+ "debug: i=%d, chosen %d, sum %d\n",
+ i, primes[pos], sum );
+ }
+ #endif
+ }
+ mask >>= 1;
+ }
+ #if 0
+ if( debug )
+ {
+ printf( "debug: i=%d, nchosen=%d, sum=%d\n",
+ i, nchosen, sum );
+ }
+ #endif
+
+ if( sum == m && nchosen == n )
+ {
+ string buf = "";
+ char *p = buf;
+ for( int i=0; i<n; i++ )
+ {
+ sprintf( p, "%d, ", chosen[i] );
+ p += strlen(p);
+ }
+ p[strlen(p)-2] = '\0';
+ if( debug )
+ {
+ printf( "debug: i=%d: found a pp: %s\n", i, buf );
+ }
+ int len = strlen(pps);
+ assert( len + strlen(buf) + 5 < MAXSTRINGLEN );
+ strcat( pps, buf );
+ strcat( pps, " or " );
+ }
+ }
+
+ // remove trailing " or "..
+ int len = strlen(pps);
+ if( len>0 )
+ {
+ pps[len-4] = '\0';
+ }
+ printf( "%s\n", pps );
+
+ return 0;
+}
diff --git a/challenge-172/duncan-c-white/C/ch-2.c b/challenge-172/duncan-c-white/C/ch-2.c
new file mode 100644
index 0000000000..86aea9c9f3
--- /dev/null
+++ b/challenge-172/duncan-c-white/C/ch-2.c
@@ -0,0 +1,108 @@
+/*
+ * Task 2 - Five-number Summary
+ *
+ * GUEST LANGUAGE: THIS IS THE C VERSION OF ch-2.pl.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include "args.h"
+
+
+//
+// double med = median( arr[], nel );
+// Calculate the median value in the sorted array arr[0..nel-1].
+//
+double median( int *arr, int nel )
+{
+ int midpos = nel/2;
+ double median = nel%2 == 0 ?
+ (arr[midpos-1]+arr[midpos])/2.0 :
+ arr[midpos];
+ return median;
+}
+
+
+int intcompare( const void *p1, const void *p2 )
+{
+ // The actual arguments to this function are "pointers to
+ // pointers to char", but strcmp(3) arguments are "pointers
+ // to char", hence the following cast plus dereference */
+
+ int a = *((int *)p1);
+ int b = *((int *)p2);
+ return a - b;
+}
+
+
+void prarr( int *arr, int nel )
+{
+ for( int i=0; i<nel; i++ )
+ {
+ printf( "%d, ", arr[i] );
+ }
+ putchar('\n');
+}
+
+
+#define MAXDATA 100
+
+int main( int argc, char **argv )
+{
+ int arr[MAXDATA];
+ int nel = process_listnumargs( "five-number-summary",
+ argc, argv, arr, MAXDATA );
+
+ // sort arr[0..nel-1] numerically
+ qsort( arr, nel, sizeof(int), &intcompare );
+
+ if( debug )
+ {
+ printf( "debug: sorted " );
+ prarr( arr, nel );
+ }
+
+ double medn = median( arr, nel );
+
+ int midpos = nel/2;
+ if( debug )
+ {
+ printf( "debug: median=%.2f, midpos=%d\n", medn, midpos );
+ }
+
+ // h1: first half of arr[]
+ int h1nel = midpos;
+ int *h1 = arr;
+
+ // h2: second half of arr[]
+ if( nel%2 != 0 ) midpos++;
+ int *h2 = arr+midpos;
+ int h2nel = nel-midpos;
+
+ if( debug )
+ {
+ printf( "debug: h1 = " );
+ prarr( h1, h1nel );
+ printf( "debug: h2 = " );
+ prarr( h2, h2nel );
+ }
+
+ double firstq = median( h1, h1nel );
+ double thirdq = median( h2, h2nel );
+
+ double min = arr[0];
+ double max = arr[nel-1];
+
+ printf( " %5.1f\n", medn );
+ printf( "%5.1f %5.1f\n", firstq, thirdq );
+ printf( "%5.1f %5.1f\n", min, max );
+
+ return 0;
+}
diff --git a/challenge-172/duncan-c-white/C/primes.c b/challenge-172/duncan-c-white/C/primes.c
new file mode 100644
index 0000000000..9e9d0ba0fb
--- /dev/null
+++ b/challenge-172/duncan-c-white/C/primes.c
@@ -0,0 +1,67 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <math.h>
+
+
+// int *primes = primes_upto(n,&numprimes);
+// Generate a dynamic array of integers containing
+// all primes up to $n. The array is zero-terminated.
+// We also set numprimes to the number of primes found.
+// The caller should free(primes) when they've finished
+// using it.
+//
+int * primes_upto( int n, int *numprimep )
+{
+ bool *isprime = (bool *) malloc( (n+1) * sizeof(bool) );
+ assert( isprime != NULL );
+
+ int i;
+ for( i=1; i<=n; i++ )
+ {
+ isprime[i] = 1; // initially
+ }
+
+ int upper = (int)(sqrt((double)(n)));
+ //printf( "debug: n=%d, upper=%d\n", n, upper );
+ for( i=2; i<=upper; i++ )
+ {
+ if( isprime[i] )
+ {
+ //printf( "debug: crossing out multiples of %d\n", i );
+ int j;
+ for( j=i*i; j<=n; j+=i )
+ {
+ isprime[j] = 0;
+ }
+ }
+ }
+
+ // count how many primes there are
+ int np = 0;
+ for( i=2; i<=n; i++ )
+ {
+ if( isprime[i] )
+ {
+ np++;
+ }
+ }
+ *numprimep = np;
+
+ // dynamically allocate an array of np+1 ints, and fill it in
+ int *primes = malloc( (np+1) * sizeof(int) );
+ int p = 0;
+ for( i=2; i<=n; i++ )
+ {
+ if( isprime[i] )
+ {
+ primes[p++] = i;
+ }
+ }
+ primes[p] = 0;
+
+ free( isprime );
+
+ return primes;
+}
diff --git a/challenge-172/duncan-c-white/C/primes.h b/challenge-172/duncan-c-white/C/primes.h
new file mode 100644
index 0000000000..d9fd437aa7
--- /dev/null
+++ b/challenge-172/duncan-c-white/C/primes.h
@@ -0,0 +1 @@
+extern int * primes_upto( int n, int * numprimep );
diff --git a/challenge-172/duncan-c-white/README b/challenge-172/duncan-c-white/README
index 755694b9fc..604f28c0b7 100644
--- a/challenge-172/duncan-c-white/README
+++ b/challenge-172/duncan-c-white/README
@@ -1,33 +1,38 @@
-Task 1: Abundant Number
+Task 1: Prime Partition
-Write a script to generate first 20 Abundant Odd Numbers.
+You are given two positive integers, $m and $n.
-According to wikipedia: A number n for which the sum of proper divisors
-(divisors from 1 but less than n) s(n) > n.
+Write a script to find out the Prime Partition of the given number $m that
+contains $n elements. No duplicates allowed.
-For example, 945 is the first Abundant Odd Number.
+For example,
-Sum of divisors:
-1 + 3 + 5 + 7 + 9 + 15 + 21 + 27 + 35 + 45 + 63 + 105 + 135 + 189 + 315 = 975
+ Input: $m = 18, $n = 2
+ Output: 5, 13 or 7, 11
-MY NOTES: ok, sounds easy, and at least it's nowt to do with Primes:-)
+ Input: $m = 19, $n = 3
+ Output: 3, 5, 11
+
+MY NOTES: ok, sounds quite easy, even if it is to do with Primes. Without
+duplicates means that each prime p < m is either present or absent in a
+given partition, so we can use our old trick of having a counting loop from
+0..2**(nitems)-1 and compute the sum of just those items selected by the
+binary bits of the count that are 1 (then check that the sum is $m and
+the number of elements being summed is $n)
GUEST LANGUAGE: As a bonus, I also had a go at translating ch-1.pl
into C (look in the C directory for that).
-Task 2: First-class Function
-
-Create sub compose($f, $g) which takes in two parameters $f and $g as
-subroutine refs and returns subroutine ref i.e. compose($f, $g)->($x)
-= $f->($g->($x))
+Task 2: Five-number Summary
-e.g.
+You are given an array of integers.
-$f = (one or more parameters function)
-$g = (one or more parameters function)
+Write a script to compute the five-number summary of the given set of integers.
-$h = compose($f, $g)
-$f->($g->($x,$y, ..)) == $h->($x, $y, ..) for any $x, $y, ...
+You can find the definition and example in the wikipedia page:
+ https://en.wikipedia.org/wiki/Five-number_summary
-MY NOTES: An interesting question at last. Think it's quite easy..
+MY NOTES: Nice and simple: sort the data, pick the median, first and third
+quartile values. Note that the median can be the average (mean) of the
+two central values if the #values is even.
diff --git a/challenge-172/duncan-c-white/perl/MakePrimes.pm b/challenge-172/duncan-c-white/perl/MakePrimes.pm
new file mode 100644
index 0000000000..e268fa06a3
--- /dev/null
+++ b/challenge-172/duncan-c-white/perl/MakePrimes.pm
@@ -0,0 +1,90 @@
+#
+# 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-172/duncan-c-white/perl/ch-1.pl b/challenge-172/duncan-c-white/perl/ch-1.pl
new file mode 100755
index 0000000000..d2b3daf950
--- /dev/null
+++ b/challenge-172/duncan-c-white/perl/ch-1.pl
@@ -0,0 +1,68 @@
+#!/usr/bin/perl
+#
+# Task 1: Prime Partition
+#
+# You are given two positive integers, $m and $n.
+#
+# Write a script to find out the Prime Partition of the given number $m that
+# contains $n elements. No duplicates allowed.
+#
+# For example,
+#
+# Input: $m = 18, $n = 2
+# Output: 5, 13 or 7, 11
+#
+# Input: $m = 19, $n = 3
+# Output: 3, 5, 11
+#
+# MY NOTES: ok, sounds quite easy, even if it is to do with Primes. Without
+# duplicates means that each prime p < m is either present or absent in a
+# given partition, so we can use our old trick of having a counting loop from
+# 0..2**(nitems)-1 and compute the sum of just those items selected by the
+# binary bits of the count that are 1 (then check that the sum is $m and
+# the number of elements being summed is $n)
+#
+# GUEST LANGUAGE: As a bonus, I also had a go at translating ch-1.pl
+# into C (look in the C directory for that).
+#
+
+use strict;
+use warnings;
+use feature 'say';
+use Getopt::Long;
+use Data::Dumper;
+use List::Util qw(sum0);
+
+use lib qw(.);
+use MakePrimes;
+
+my $debug=0;
+die "Usage: prime-partition [--debug] M N\n"
+ unless GetOptions( "debug"=>\$debug ) && @ARGV==2;
+my( $m, $n ) = @ARGV;
+
+my @primes = primes_upto( $m-1 );
+my $nitems = @primes;
+
+my @pp; # array of prime partitions, each a string
+
+my $two2n = 2**$nitems;
+
+for( my $i=0; $i<$two2n; $i++ )
+{
+ my $b = sprintf("%0${nitems}b", $i );
+ my @select = split( //, $b );
+
+ my @chosen = map { $primes[$_] } grep { $select[$_] } 0..$nitems-1;
+ my $sum = sum0(@chosen);
+ #say "$i: b=$b, select=", join(',',@select),
+ # ", chosen=", join(',',@chosen),
+ # ", sum=$sum" if $debug;
+ next unless $sum == $m;
+ next unless @chosen == $n;
+ say "$i: b=$b, found a pp: ", join(',',@chosen) if $debug;
+ push @pp, join( ', ', @chosen);
+}
+
+my $str = join( ' or ', @pp );
+say $str;
diff --git a/challenge-172/duncan-c-white/perl/ch-2.pl b/challenge-172/duncan-c-white/perl/ch-2.pl
new file mode 100755
index 0000000000..06618cae8d
--- /dev/null
+++ b/challenge-172/duncan-c-white/perl/ch-2.pl
@@ -0,0 +1,63 @@
+#!/usr/bin/perl
+#
+# Task 2: Five-number Summary
+#
+# You are given an array of integers. Write a script to compute the
+# five-number summary of the given set of integers.
+# You can find the definition and example in the wikipedia page:
+# https://en.wikipedia.org/wiki/Five-number_summary
+#
+# MY NOTES: Nice and simple: sort the data, pick the median, first and third
+# quartile values. Note that the median can be the average (mean) of the
+# two central values if the #values is even.
+#
+
+use strict;
+use warnings;
+use feature 'say';
+use Getopt::Long;
+use Data::Dumper;
+
+my $debug=0;
+die "Usage: five-number-summary [--debug] list_of_ints\n"
+ unless GetOptions( "debug"=>\$debug ) && @ARGV>1;
+
+my @n = sort { $a <=> $b } @ARGV;
+say "debug: sorted ", join(',', @n ) if $debug;
+
+
+#
+# my $median = median( @n );
+# Calculate the median value in the sorted array @n.
+#
+sub median
+{
+ my( @n ) = @_;
+ my $midpos = int(@n/2);
+ my $median = @n%2 == 0 ? ($n[$midpos-1]+$n[$midpos])/2 : $n[$midpos];
+ return $median;
+}
+
+
+my $median = median( @n );
+
+my $midpos = int(@n/2);
+say "debug: midpos=$midpos" if $debug;
+
+my @h1 = @n[0..$midpos-1];
+
+$midpos++ if @n%2 != 0;
+my @h2 = @n[$midpos..@n-1];
+
+say "debug: h1 = ", join(',',@h1), ", h2 = ", join(',',@h2)
+ if $debug;
+
+my $firstq = median( @h1 );
+my $thirdq = median( @h2 );
+
+my $min = $n[0];
+my $max = $n[-1];
+
+printf " %5.1f\n", $median;
+printf "%5.1f %5.1f\n", $firstq, $thirdq;
+printf "%5.1f %5.1f\n", $min, $max;
diff --git a/challenge-173/duncan-c-white/C/.cbuild b/challenge-173/duncan-c-white/C/.cbuild
index 7171ba4c65..fce622d376 100644
--- a/challenge-173/duncan-c-white/C/.cbuild
+++ b/challenge-173/duncan-c-white/C/.cbuild
@@ -1,3 +1,4 @@
-BUILD = ch-1
+BUILD = ch-1 ch-2
CFLAGS = -Wall
+LDFLAGS = -lgmp
#CFLAGS = -g
diff --git a/challenge-173/duncan-c-white/C/Makefile b/challenge-173/duncan-c-white/C/Makefile
new file mode 100644
index 0000000000..9d1b99a602
--- /dev/null
+++ b/challenge-173/duncan-c-white/C/Makefile
@@ -0,0 +1,14 @@
+BUILD = ch-1 ch-2
+CC = gcc
+CFLAGS = -Wall -g
+LDLIBS = -lm -lgmp
+
+all: $(BUILD)
+