aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad S Anwar <Mohammad.Anwar@yahoo.com>2019-09-23 11:12:49 +0100
committerGitHub <noreply@github.com>2019-09-23 11:12:49 +0100
commit98a7ab6ebfcfa9425fbff18eef43b77d3ba64d5b (patch)
treeea153095bac5e294192b7e5744ec96c3d0517fa3
parent9a7a969ebcb0058362faadd2a4df13f8289dc41c (diff)
parentb809d0e1f86602649b6468d305a2023c5c9571f8 (diff)
downloadperlweeklychallenge-club-98a7ab6ebfcfa9425fbff18eef43b77d3ba64d5b.tar.gz
perlweeklychallenge-club-98a7ab6ebfcfa9425fbff18eef43b77d3ba64d5b.tar.bz2
perlweeklychallenge-club-98a7ab6ebfcfa9425fbff18eef43b77d3ba64d5b.zip
Merge pull request #660 from dcw803/master
hi manwar, forgot to submit PR last night
-rw-r--r--challenge-024/duncan-c-white/README55
-rwxr-xr-xchallenge-024/duncan-c-white/perl5/ch-1.sh11
-rwxr-xr-xchallenge-024/duncan-c-white/perl5/ch-2.pl115
-rw-r--r--challenge-024/duncan-c-white/perl5/docs/times-0014
-rw-r--r--challenge-024/duncan-c-white/perl5/docs/times-0027
-rw-r--r--challenge-024/duncan-c-white/perl5/docs/times-0034
-rw-r--r--challenge-024/duncan-c-white/perl5/docs/times-00410
-rw-r--r--challenge-024/duncan-c-white/perl5/docs/times-0054
-rw-r--r--challenge-024/duncan-c-white/perl5/docs/times-0066
-rw-r--r--challenge-024/duncan-c-white/perl5/docs/times-0077
-rw-r--r--challenge-024/duncan-c-white/perl5/docs/times-0086
-rw-r--r--challenge-024/duncan-c-white/perl5/docs/times-0098
-rw-r--r--challenge-024/duncan-c-white/perl5/docs/times-01011
-rw-r--r--challenge-024/duncan-c-white/perl5/docs/times-0116
-rw-r--r--challenge-025/duncan-c-white/README52
-rw-r--r--challenge-025/duncan-c-white/blog.txt1
-rwxr-xr-xchallenge-025/duncan-c-white/perl5/ch-1.pl212
-rwxr-xr-xchallenge-025/duncan-c-white/perl5/v0.pl44
-rwxr-xr-xchallenge-025/duncan-c-white/perl5/v1.pl102
-rwxr-xr-xchallenge-025/duncan-c-white/perl5/v15.pl224
-rwxr-xr-xchallenge-025/duncan-c-white/perl5/v16-with-histo.pl278
-rwxr-xr-xchallenge-025/duncan-c-white/perl5/v16.pl227
-rwxr-xr-xchallenge-025/duncan-c-white/perl5/v17.pl220
-rwxr-xr-xchallenge-025/duncan-c-white/perl5/v18.pl219
-rwxr-xr-xchallenge-025/duncan-c-white/perl5/v19.pl214
-rwxr-xr-xchallenge-025/duncan-c-white/perl5/v2.pl106
-rwxr-xr-xchallenge-025/duncan-c-white/perl5/v20.pl212
-rwxr-xr-xchallenge-025/duncan-c-white/perl5/v3.pl108
-rwxr-xr-xchallenge-025/duncan-c-white/perl5/v4.pl115
-rwxr-xr-xchallenge-025/duncan-c-white/perl5/v5.pl125
-rwxr-xr-xchallenge-025/duncan-c-white/perl5/v6.pl127
-rwxr-xr-xchallenge-025/duncan-c-white/perl5/v7.pl178
-rwxr-xr-xchallenge-025/duncan-c-white/perl5/v8.pl191
-rwxr-xr-xchallenge-025/duncan-c-white/perl5/v9.pl186
-rw-r--r--challenge-026/duncan-c-white/README57
-rwxr-xr-xchallenge-026/duncan-c-white/perl5/ch-1.pl38
-rwxr-xr-xchallenge-026/duncan-c-white/perl5/ch-2.pl38
37 files changed, 3436 insertions, 92 deletions
diff --git a/challenge-024/duncan-c-white/README b/challenge-024/duncan-c-white/README
index 4cd2bbfe01..926e2938aa 100644
--- a/challenge-024/duncan-c-white/README
+++ b/challenge-024/duncan-c-white/README
@@ -1,36 +1,37 @@
-Challenge 1: "Create a script that prints nth order forward difference
-series. You should be a able to pass the list of numbers and order number
-as command line parameters. Let me show you with an example:
+Challenge 1: "Create a smallest script in terms of size that on
+execution doesn't throw any error. The script doesn't have to do anything
+special. You could even come up with smallest one-liner."
-Suppose we have list (X) of numbers: 5, 9, 2, 8, 1, 6 and we would like
-to create 1st order forward difference series (Y). So using the formula
-Y(i) = X(i+1) - X(i), we get the following numbers: (9-5), (2-9), (8-2),
-(1-8), (6-1), ie 4, -7, 6, -7, 5.
-If you noticed, it has one less number than the original series.
-Similarly you can generate the 2nd order forward difference series like:
-(-7-4), (6+7), (-7-6), (5+7) => -11, 13, -13, 12.
+My notes: Umm, if it doesn't have to do anything special, and we want it to
+be tiny, does it have to do anything at all? Why not write the shortest
+Perl one-liner: perl -e 1:-)
-My notes: Clearly defined, very easy - let's have a go..
+Challenge 2: "Create a script to implement full text search functionality
+using Inverted Index. According to wikipedia:
-Challenge 2: "Create a script that prints Prime Decomposition of a
-given number. The prime decomposition of a number is defined as a list
-of prime numbers which when all multiplied together, are equal to that
-number. For example, the Prime decomposition of 228 is 2,2,3,19 as 228 =
-2 * 2 * 3 * 19."
+In computer science, an inverted index (also referred to as a
+postings file or inverted file) is a database index storing
+a mapping from content, such as words or numbers, to its
+locations in a table, or in a document or a set of documents
+(named in contrast to a forward index, which maps from documents
+to content). The purpose of an inverted index is to allow fast
+full-text searches, at a cost of increased processing when a
+document is added to the database."
-My notes: So, prime factors then. Very easy again. In fact, haven't I
-already solved this in one of the other prime-based questions?
+My notes: One extreme to the other, an inverted index might be quite a
+lot of work. Most especially, it would need an index-creator/updater
+and a search-using-index tool. Also, the wikipedia article says that
+some inverted indexes are:
+wordindocument: word -> set of document (names or numbers),
-Challenge 3: "Write a script to use Random Poems API:
-https://www.poemist.com/api/v1/randompoems
-This is the easiset API, I have come across so far. You don't need API
-key for this. They have only route to work with (GET). The API task is
-optional but we would love to see your solution."
+whereas others are:
-My notes: ok, even I can't argue that obtaining an API key for an API
-I will literally never use again is too much hassle - when I don't need
-an API key, and the whole program appears to be an LWP::Simple get..
+wordwhereindocuments: word -> set of (document, position)
-update: well, apart from the Unicode in the response, complicating life.
+(or perhaps set of word -> set of document -> list of position)
+
+Knowing the positions of each word in each document allows us to
+search for several words "near to each other", so that's very useful.
+But does the question want us to do that or not? Minimalism says not:-)
diff --git a/challenge-024/duncan-c-white/perl5/ch-1.sh b/challenge-024/duncan-c-white/perl5/ch-1.sh
new file mode 100755
index 0000000000..37c2dec647
--- /dev/null
+++ b/challenge-024/duncan-c-white/perl5/ch-1.sh
@@ -0,0 +1,11 @@
+#!/bin/sh -
+#
+# Challenge 1: "Create a smallest script in terms of size that on
+# execution doesn't throw any error. The script doesn't have to do anything
+# special. You could even come up with smallest one-liner."
+#
+# My notes: Umm, if it doesn't have to do anything special, and we want it to
+# be tiny, does it have to do anything at all? Why not write the shortest
+# Perl one-liner: perl -e 1:-)
+#
+perl -e 1
diff --git a/challenge-024/duncan-c-white/perl5/ch-2.pl b/challenge-024/duncan-c-white/perl5/ch-2.pl
new file mode 100755
index 0000000000..47ea06621e
--- /dev/null
+++ b/challenge-024/duncan-c-white/perl5/ch-2.pl
@@ -0,0 +1,115 @@
+#!/usr/bin/perl
+#
+# Challenge 2: "Create a script to implement full text search functionality
+# using Inverted Index.. a database index storing a mapping from content,
+# such as words or numbers, to its locations in a set of documents.
+# The purpose of an inverted index is to allow fast full-text searches,
+# at a cost of increased processing when a document is added to the database."
+#
+# My notes: One extreme to the other, an inverted index might be quite a
+# lot of work. It needs an index-creator/updater mode, and a
+# search-using-index mode.
+# Let's use a dbm file to store the index, specifically:
+#
+# wordindocument: word -> set of document names, stored as a sorted list
+#
+
+use v5.10; # for "say"
+use strict;
+use warnings;
+use Function::Parameters;
+use DB_File;
+use Data::Dumper;
+
+my $usage = "Usage: ch-2.pl i[ndex] DOCUMENT[s],\n".
+ "or: ch-2.pl s[earch] keywords\n".
+ "or: ch-2.pl l[ist]\n";
+die $usage unless @ARGV > 0;
+
+my %index;
+tie %index, 'DB_File', "index" || die "ch-2.pl: can't tie to index\n";
+
+my $mode = shift @ARGV;
+if( $mode =~ /^i/i )
+{
+ die $usage unless @ARGV;
+ add( @ARGV );
+} elsif( $mode =~ /^s/i )
+{
+ die $usage unless @ARGV;
+ my %docs = search( @ARGV );
+ my $docstr = join( ',', sort keys %docs );
+ print "documents containing @ARGV: $docstr\n";
+} elsif( $mode =~ /^l/i )
+{
+ while( my $w = each %index )
+ {
+ print "$w: $index{$w}\n";
+ }
+} else
+{
+ die $usage;
+}
+untie %index;
+
+
+#
+# addwordtoindex( $w, $filename );
+# Word $w occurs in file $filename, add this to the index.
+#
+fun addwordtoindex( $w, $filename )
+{
+ my $docset = $index{$w} // "";
+ my %s = map { $_ => 1 } split( /,/, $docset );
+ $s{$filename}++;
+ $index{$w} = join(',', sort keys %s);
+}
+
+
+#
+# add( @filenames );
+# Add each document named in @filename to the index.
+#
+fun add( @filename )
+{
+ foreach my $file (@filename)
+ {
+ open( my $infh, '<', $file ) || next;
+ my %set; # words in this file
+ while( <$infh> )
+ {
+ chomp;
+ my @wd = split( /\s+/ );
+ foreach my $w (@wd)
+ {
+ $w =~ s/[\.,;:!?"'({\[]+$//;
+ next if $set{$w}++;
+ addwordtoindex( $w, $file );
+ }
+ }
+ close( $infh );
+ }
+}
+
+#
+# my %docs = search( @word );
+# Search for documents containing all the words in @word.
+# using set intersection.. return a document set.
+#
+fun search( @word )
+{
+ @word = grep { defined $index{$_} } @word;
+ my $w = shift @word;
+ my %docset = map { $_ => 1 } split(/,/, $index{$w});
+ print "$w in $index{$w}\n";
+ foreach my $w (@word)
+ {
+ my %set2 = map { $_ => 1 } split(/,/, $index{$w});
+ print "$w in $index{$w}\n";
+ foreach my $w (keys %docset)
+ {
+ delete $docset{$w} unless $set2{$w};
+ }
+ }
+ return %docset;
+}
diff --git a/challenge-024/duncan-c-white/perl5/docs/times-001 b/challenge-024/duncan-c-white/perl5/docs/times-001
new file mode 100644
index 0000000000..722d22229a
--- /dev/null
+++ b/challenge-024/duncan-c-white/perl5/docs/times-001
@@ -0,0 +1,4 @@
+What do I mean about honesty and logic? The frontrunner in the race
+for Downing Street offered a masterclass in his lack of it during the
+referendum: "My policy on cake is pro having it and pro eating it."
+Boris: You can't.
diff --git a/challenge-024/duncan-c-white/perl5/docs/times-002 b/challenge-024/duncan-c-white/perl5/docs/times-002
new file mode 100644
index 0000000000..75366081a0
--- /dev/null
+++ b/challenge-024/duncan-c-white/perl5/docs/times-002
@@ -0,0 +1,7 @@
+The Archangel Gabriel couldn't have delivered Mrs May's famous
+"Brexit that works for everyone" promise. It will become fashionable
+in columns like these to identify things she could have done to get
+her deal through, and the time (always yesterday) when she could have
+done them. And I can believe that with Mr Gove's persuasiveness or Mr
+Johnson's amiable bombast, a different prime minister might just have
+pushed something like her deal over the line.
diff --git a/challenge-024/duncan-c-white/perl5/docs/times-003 b/challenge-024/duncan-c-white/perl5/docs/times-003
new file mode 100644
index 0000000000..8dffb9be2a
--- /dev/null
+++ b/challenge-024/duncan-c-white/perl5/docs/times-003
@@ -0,0 +1,4 @@
+But - have we all forgotten? - her deal is for the 22-month transition
+period, not for Britain's final status outside the EU. So we'd now
+be in that transition period, still tearing ourselves apart, for it's
+really only about the final status that Brexiteers and Remainers disagree.
diff --git a/challenge-024/duncan-c-white/perl5/docs/times-004 b/challenge-024/duncan-c-white/perl5/docs/times-004
new file mode 100644
index 0000000000..1d8b2a5356
--- /dev/null
+++ b/challenge-024/duncan-c-white/perl5/docs/times-004
@@ -0,0 +1,10 @@
+And so to the logic. It's possible to believe (as I don't) that Brexit
+could lead us to glory: but only after a "clean" exit from the EU
+and the ties that come with membership. And it's possible to believe
+(as I do) that we are wiser to remain. But to believe we could benefit
+from being half-in, half-out defies logic. The ties of membership,
+or half-membership, are what real Leavers believe hold us back. Real
+Remainers, meanwhile, share their horror at subjecting ourselves to
+rules we've lost the right to shape. The illogic of compromise that
+delivers the worst of both worlds would defeat Gabriel, defeated Mrs May,
+and will defeat whoever succeeds her.
diff --git a/challenge-024/duncan-c-white/perl5/docs/times-005 b/challenge-024/duncan-c-white/perl5/docs/times-005
new file mode 100644
index 0000000000..a8202dd0c2
--- /dev/null
+++ b/challenge-024/duncan-c-white/perl5/docs/times-005
@@ -0,0 +1,4 @@
+And so to honesty. Somebody has to square with the British people. She
+never would. It is about Remain or Leave. We loop back to 2016, but this
+time with a much clearer grasp of what "Leave" means. Isn't the
+Gordian knot cut by putting the question again?
diff --git a/challenge-024/duncan-c-white/perl5/docs/times-006 b/challenge-024/duncan-c-white/perl5/docs/times-006
new file mode 100644
index 0000000000..84e60d366b
--- /dev/null
+++ b/challenge-024/duncan-c-white/perl5/docs/times-006
@@ -0,0 +1,6 @@
+And here, I don't mean to queer Mr Johnson's pitch by putting the wind
+up his Brexiteer supporters, but must mention one faint hope: a reason
+for hoping a Johnson premiership would not end in calamity. My Times
+colleague Rachel Sylvester discussed it in these pages on Tuesday. Mr
+Johnson might be capable of ratting on his promise to take us out of
+the EU - and getting away with it.
diff --git a/challenge-024/duncan-c-white/perl5/docs/times-007 b/challenge-024/duncan-c-white/perl5/docs/times-007
new file mode 100644
index 0000000000..6aff7a66c7
--- /dev/null
+++ b/challenge-024/duncan-c-white/perl5/docs/times-007
@@ -0,0 +1,7 @@
+The arguments against his suitability are too many for a comprehensive
+list. Casual disregard for the truth; reckless caprice; lazy disregard for
+detail; weak negotiating skills (as Whitehall knows); moral turpitude
+which perhaps we should overlook in politics but which has been so
+destructive of others' lives that I cannot forget it; and his failure
+as foreign secretary to achieve anything but an extension of his notoriety
+beyond our own shores.
diff --git a/challenge-024/duncan-c-white/perl5/docs/times-008 b/challenge-024/duncan-c-white/perl5/docs/times-008
new file mode 100644
index 0000000000..47e3a38702
--- /dev/null
+++ b/challenge-024/duncan-c-white/perl5/docs/times-008
@@ -0,0 +1,6 @@
+The man's a rascal. But like many rascals he's capable of a big
+decision. It's possible to imagine him telling the country that this
+Brexit business has got into such a poisonous muddle that we need to rip
+it up and start again: to revoke Article 50, or refer back to the people,
+or both. He might escape with his life. A Hunt, a Gove, a Hancock or a
+Javid wouldn't.
diff --git a/challenge-024/duncan-c-white/perl5/docs/times-009 b/challenge-024/duncan-c-white/perl5/docs/times-009
new file mode 100644
index 0000000000..e1aa54a521
--- /dev/null
+++ b/challenge-024/duncan-c-white/perl5/docs/times-009
@@ -0,0 +1,8 @@
+Be clear: whoever takes over will soon enough need to be very, very
+bold, one way or the other. Would-be Tory leaders will shortly be wooing
+supporters with a promise to "go back to Brussels" for a better deal,
+threatening no-deal Brexit if they don't. Whoever wins will then have
+to try. They'll return empty-handed. What then? Here's Mr Johnson,
+speaking in Switzerland today: "We will leave the EU on October 31,
+deal or no deal ... The way to get a good deal is to prepare for a no
+deal. To get things done you need to be prepared to walk away."
diff --git a/challenge-024/duncan-c-white/perl5/docs/times-010 b/challenge-024/duncan-c-white/perl5/docs/times-010
new file mode 100644
index 0000000000..6baa07a886
--- /dev/null
+++ b/challenge-024/duncan-c-white/perl5/docs/times-010
@@ -0,0 +1,11 @@
+This week the Institute for Government published an important report,
+suggesting that a PM intent on a no-deal Brexit could thwart parliament by
+a lightning decision to do it without MPs' say-so. Be warned, would-be
+prime ministers: this would be nuclear, a coup against representative
+democracy and a breach of our unwritten constitution. This way, infamy
+lies. Gangrene would follow such an amputation. Don't even think
+about it.
+
+That leaves a referendum, a revocation, a general election, or all
+three. Theresa May's departing tears are unlikely to be the last shed
+at Downing Street's door.
diff --git a/challenge-024/duncan-c-white/perl5/docs/times-011 b/challenge-024/duncan-c-white/perl5/docs/times-011
new file mode 100644
index 0000000000..0103b56f15
--- /dev/null
+++ b/challenge-024/duncan-c-white/perl5/docs/times-011
@@ -0,0 +1,6 @@
+Boris Johnson is enough of a rascal to rat on Brexit
+
+Matthew Parris
+
+The frontrunner for No 10 might be the only candidate who'd get away
+with ripping up Article 50 and starting again.
diff --git a/challenge-025/duncan-c-white/README b/challenge-025/duncan-c-white/README
index 4cd2bbfe01..49002c5fc3 100644
--- a/challenge-025/duncan-c-white/README
+++ b/challenge-025/duncan-c-white/README
@@ -1,36 +1,30 @@
-Challenge 1: "Create a script that prints nth order forward difference
-series. You should be a able to pass the list of numbers and order number
-as command line parameters. Let me show you with an example:
+Challenge 1: "Generate a longest sequence of the following "English Pokemon"
+ names where each name starts with the last letter of the previous name:
-Suppose we have list (X) of numbers: 5, 9, 2, 8, 1, 6 and we would like
-to create 1st order forward difference series (Y). So using the formula
-Y(i) = X(i+1) - X(i), we get the following numbers: (9-5), (2-9), (8-2),
-(1-8), (6-1), ie 4, -7, 6, -7, 5.
-If you noticed, it has one less number than the original series.
-Similarly you can generate the 2nd order forward difference series like:
-(-7-4), (6+7), (-7-6), (5+7) => -11, 13, -13, 12.
+ audino bagon baltoy banette bidoof braviary bronzor carracosta
+ charmeleon cresselia croagunk darmanitan deino emboar emolga
+ exeggcute gabite girafarig gulpin haxorus heatmor heatran ivysaur
+ jellicent jumpluff kangaskhan kricketune landorus ledyba loudred
+ lumineon lunatone machamp magnezone mamoswine nosepass petilil
+ pidgeotto pikachu pinsir poliwrath poochyena porygon2 porygonz
+ registeel relicanth remoraid rufflet sableye scolipede scrafty
+ seaking sealeo silcoon simisear snivy snorlax spoink starly
+ tirtouga trapinch treecko tyrogue vigoroth vulpix wailord
+ wartortle whismur wingull yamask"
-My notes: Clearly defined, very easy - let's have a go..
+My notes: Clearly defined, nice, potentially tricky, let's have a go -
+ and try some optimization experiments.
-Challenge 2: "Create a script that prints Prime Decomposition of a
-given number. The prime decomposition of a number is defined as a list
-of prime numbers which when all multiplied together, are equal to that
-number. For example, the Prime decomposition of 228 is 2,2,3,19 as 228 =
-2 * 2 * 3 * 19."
+Challenge 2: "Create script to implement Chaocipher. Please checkout
+https://en.wikipedia.org/wiki/Chaocipher for more information."
-My notes: So, prime factors then. Very easy again. In fact, haven't I
-already solved this in one of the other prime-based questions?
+My notes: That wikipedia page is very light on details, but refers you
+to the following PDF document for a full explanation:
+http://www.chaocipher.com/ActualChaocipher/Chaocipher-Revealed-Algorithm.pdf
-Challenge 3: "Write a script to use Random Poems API:
-https://www.poemist.com/api/v1/randompoems
-This is the easiset API, I have come across so far. You don't need API
-key for this. They have only route to work with (GET). The API task is
-optional but we would love to see your solution."
-
-My notes: ok, even I can't argue that obtaining an API key for an API
-I will literally never use again is too much hassle - when I don't need
-an API key, and the whole program appears to be an LWP::Simple get..
-
-update: well, apart from the Unicode in the response, complicating life.
+reading that, it gives a clear description of the algorithm. but then
+shows you the canonical solution - in beautifully clean Perl 5. So, umm,
+what is the point in me doing it again?
+I already solved this in one of the other prime-based questions?
diff --git a/challenge-025/duncan-c-white/blog.txt b/challenge-025/duncan-c-white/blog.txt
new file mode 100644
index 0000000000..03df97d466
--- /dev/null
+++ b/challenge-025/duncan-c-white/blog.txt
@@ -0,0 +1 @@
+https://www.doc.ic.ac.uk/~dcw/PSD/article13/
diff --git a/challenge-025/duncan-c-white/perl5/ch-1.pl b/challenge-025/duncan-c-white/perl5/ch-1.pl
new file mode 100755
index 0000000000..a8dc4aa651
--- /dev/null
+++ b/challenge-025/duncan-c-white/perl5/ch-1.pl
@@ -0,0 +1,212 @@
+#!/usr/bin/perl
+#
+# Challenge 1: "Generate a longest sequence of the following "English Pokemon"
+# names where each name starts with the last letter of the previous name:
+#
+# audino bagon baltoy banette bidoof braviary bronzor carracosta
+# charmeleon cresselia croagunk darmanitan deino emboar emolga
+# exeggcute gabite girafarig gulpin haxorus heatmor heatran ivysaur
+# jellicent jumpluff kangaskhan kricketune landorus ledyba loudred
+# lumineon lunatone machamp magnezone mamoswine nosepass petilil
+# pidgeotto pikachu pinsir poliwrath poochyena porygon2 porygonz
+# registeel relicanth remoraid rufflet sableye scolipede scrafty
+# seaking sealeo silcoon simisear snivy snorlax spoink starly
+# tirtouga trapinch treecko tyrogue vigoroth vulpix wailord
+# wartortle whismur wingull yamask"
+#
+# My notes: Clearly defined, nice, potentially tricky, let's do it.
+#
+# optimization v20: turned for loop that pushes into push map...
+#
+
+use v5.10; # to get "say"
+use strict;
+use warnings;
+use Function::Parameters;
+use Data::Dumper;
+
+my $debug = @ARGV>0;
+
+my @words = qw(audino bagon baltoy banette bidoof braviary bronzor carracosta
+ charmeleon cresselia croagunk darmanitan deino emboar emolga
+ exeggcute gabite girafarig gulpin haxorus heatmor heatran ivysaur
+ jellicent jumpluff kangaskhan kricketune landorus ledyba loudred
+ lumineon lunatone machamp magnezone mamoswine nosepass petilil
+ pidgeotto pikachu pinsir poliwrath poochyena porygon2 porygonz
+ registeel relicanth remoraid rufflet sableye scolipede scrafty
+ seaking sealeo silcoon simisear snivy snorlax spoink starly
+ tirtouga trapinch treecko tyrogue vigoroth vulpix wailord
+ wartortle whismur wingull yamask);
+#@words = qw(hello ollie excellent thanks shelter runaround set to);
+
+#die scalar(@words);
+
+my %sw; # hash from letter L to list of word nos of words STARTING with L
+
+my @stopword;# list of stop word nos (word nos of words with no outwords)
+
+my %ew; # hash from letter L to list of word nos of words ENDING with L
+
+my @inword; # array from word no N to array of wordnos of words going "in"
+ # to word N, i.e. ending with the first letter of word N
+ # if there are no such words, then []
+
+# build %sw
+foreach my $wn (0..$#words)
+{
+ my $word = $words[$wn];
+ $word =~ /^(.)/;
+ my $firstletter = $1;
+ $sw{$firstletter} //= [];
+ push @{$sw{$firstletter}}, $wn;
+}
+#die Dumper \%sw;
+
+# build %ew
+foreach my $wn (0..$#words)
+{
+ my $word = $words[$wn];
+ $word =~ /(.)$/;
+ my $lastletter = $1;
+ $ew{$lastletter} //= [];
+ push @{$ew{$lastletter}}, $wn;
+}
+#die Dumper \%ew;
+
+# build @stopword, using %sw
+foreach my $wn (0..$#words)
+{
+ my $word = $words[$wn];
+ $word =~ /(.)$/;
+ my $lastletter = $1;
+ my $aref = $sw{$lastletter} // [];
+ push @stopword, $wn if @$aref==0;
+}
+#die Dumper [ map { $words[$_] } @stopword ];
+
+# build @inword, using %ew
+foreach my $wn (0..$#words)
+{
+ my $word = $words[$wn];
+ $word =~ /^(.)/;
+ my $firstletter = $1;
+ my $aref = $ew{$firstletter} // [];
+ $inword[$wn]= $aref;
+}
+#die Dumper \@inword;
+
+# No longer need %sw or %ew..
+undef %sw;
+undef %ew;
+
+my @seqs = findall();
+
+show_seqs( @seqs ) if $debug;
+
+exit 0;
+
+
+#
+# my @seqs = findall();
+# Find all sequences, starting with sequences of length 1 (stop words),
+# then working back, i.e. prepending words onto the front of existing
+# sequences.
+# Delivers the list of all maximal-length sequences, each sequence is
+# a comma-separated string of word numbers.
+#
+fun findall()
+{
+ my $currpaths = []; # list of all paths for sequences of length N
+ # each path entry is now a triple:
+ # [ inwordarrayref, seqstr, availarrayref ]
+ # note that seqstr, representing the sequence,
+ # is asingle string comprising the
+ # comma-separated list of word nos
+ my $N = 1; # length starts at 1 and is increased..
+
+ # convert each stopword word no into a path triple
+ @$currpaths = map { [ $inword[$_], $_, availset($_) ] } @stopword;
+ #die Dumper $currpaths;
+
+ for(;;)
+ {
+ #die Dumper $currpaths;
+ my $nseq = @$currpaths;
+ print "Have $nseq sequences of length $N\n";
+ #show_paths( @$currpaths );
+
+ #
+ # Now let's take every path of length N,
+ # and lengthen them to length n+1, by prepending a
+ # word number to the start of each sequence. This will
+ # be possible unless all sequences in currpaths are
+ # already at their maximal length - when that happens,
+ # we break out of the loop.
+ #
+ my $newpaths = []; # paths of length N+1
+ foreach my $path (@$currpaths) # foreach current path
+ {
+ my( $inwords, $s, $avail ) = @$path;
+
+ # extend path s by each unused word no in the inwords
+ push @$newpaths,
+ map {
+ # word no $_ no longer available.
+ my $newavail = $avail;
+ substr( $newavail, $_, 1 ) = 0;
+
+ # build a whole new path, length N+1
+ [ $inword[$_], "$_,$s", $newavail ]
+ }
+ grep { substr($avail,$_,1) eq '1' } @$inwords;
+ }
+ last if @$newpaths == 0;
+ $N++;
+ $currpaths = $newpaths;
+ #die Dumper $currpaths;
+ }
+
+ # now extract and return all the maximal length sequences
+ return map { $_->[1] } @$currpaths;
+}
+
+
+
+#
+# my $set = availset( $wno );
+# Form a set in which all word nos are available, except $wno.
+#
+fun availset( $wno )
+{
+ my $set = 1 x scalar(@words);
+ substr( $set, $wno, 1 ) = 0;
+ return $set;
+}
+
+
+#
+# show_paths( @paths );
+# Show the sequences (as words, not word nos) contained in @paths
+#
+fun show_paths( @paths )
+{
+ foreach my $p (@paths)
+ {
+ my $str = join( ',', map { $words[$_] } split(/,/,$p->[1]) );
+ say $str;
+ }
+}
+
+
+#
+# show_seqs( @seqs );
+# Show the sequence of word numbers (as words, not word nos)
+#
+fun show_seqs( @seqs )
+{
+ foreach my $s (@seqs)
+ {
+ my $str = join( ',', map { $words[$_] } split(/,/,$s) );
+ say $str;
+ }
+}
diff --git a/challenge-025/duncan-c-white/perl5/v0.pl b/challenge-025/duncan-c-white/perl5/v0.pl
new file mode 100755
index 0000000000..8172dd4212
--- /dev/null
+++ b/challenge-025/duncan-c-white/perl5/v0.pl
@@ -0,0 +1,44 @@
+#!/usr/bin/perl
+#
+# Challenge 1: "Generate a longest sequence of the following "English Pokemon"
+# names where each name starts with the last letter of the previous name:
+#
+# audino bagon baltoy banette bidoof braviary bronzor carracosta
+# charmeleon cresselia croagunk darmanitan deino emboar emolga
+# exeggcute gabite girafarig gulpin haxorus heatmor heatran ivysaur
+# jellicent jumpluff kan