diff options
| author | Mohammad S Anwar <Mohammad.Anwar@yahoo.com> | 2019-09-23 11:12:49 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-09-23 11:12:49 +0100 |
| commit | 98a7ab6ebfcfa9425fbff18eef43b77d3ba64d5b (patch) | |
| tree | ea153095bac5e294192b7e5744ec96c3d0517fa3 /challenge-025 | |
| parent | 9a7a969ebcb0058362faadd2a4df13f8289dc41c (diff) | |
| parent | b809d0e1f86602649b6468d305a2023c5c9571f8 (diff) | |
| download | perlweeklychallenge-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
Diffstat (limited to 'challenge-025')
20 files changed, 3112 insertions, 29 deletions
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 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 v1: baseline code before starting to optimize: 32.6s. +# + +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); + +say "Pokemon names starting with c:"; +my @startwords = grep { /^c/ } @words; +say for @startwords; diff --git a/challenge-025/duncan-c-white/perl5/v1.pl b/challenge-025/duncan-c-white/perl5/v1.pl new file mode 100755 index 0000000000..b48b6a28b5 --- /dev/null +++ b/challenge-025/duncan-c-white/perl5/v1.pl @@ -0,0 +1,102 @@ +#!/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 v1: baseline code before starting to optimize: 32.6s. +# + +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); + +my %sw; # hash from letter to list of words starting with that letter. + +foreach my $word (@words) +{ + $word =~ /^(.)/; + my $letter = $1; + $sw{$letter} //= []; + push @{$sw{$letter}}, $word; +} + +#die Dumper \%sw; + +my @longseq = (); # longest sequence found so far.. + +# search for sequences starting with each word in turn.. +foreach my $sw (@words) +{ + findseq( $sw, () ); +} + +my $longest = @longseq; + +print "\nlongest sequence is length $longest: @longseq\n"; +exit 0; + + +# +# findseq( $currw, @seq ); +# Find all sequences of words from $currw onwards, +# given that we've already visited words in @seq, +# and update the global @longseq if any sequences +# we find are longer than that. +# +fun findseq( $currw, @seq ) +{ + push @seq, $currw; # extend @seq sequence + + my %used = map { $_ => 1 } @seq; # convert to set + + $currw =~ /(.)$/; # find the last letter of currw + my $lastletter = $1; + + my $nextw = $sw{$lastletter}; # all words starting with lastletter + if( defined $nextw ) # if there are any, try each word + { + foreach my $nextword (@$nextw) + { + findseq( $nextword, @seq ) + unless $used{$nextword}; + } + } else # @seq is finished + { + #print "found sequence @seq\n"; + my $len = @seq; + if( $len > @longseq ) + { + print "longest seq so far (len $len): @seq\n" if $debug; + @longseq = @seq; + } + } +} diff --git a/challenge-025/duncan-c-white/perl5/v15.pl b/challenge-025/duncan-c-white/perl5/v15.pl new file mode 100755 index 0000000000..156466391f --- /dev/null +++ b/challenge-025/duncan-c-white/perl5/v15.pl @@ -0,0 +1,224 @@ +#!/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. +# + +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 @outword; # array from word no N to array of wordnos of words going "out" + # from word N, i.e. starting with the last letter of word N + # if there are no such words, then [] + +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 @outword and @stopword, using %sw +foreach my $wn (0..$#words) +{ + my $word = $words[$wn]; + $word =~ /(.)$/; + my $lastletter = $1; + my $aref = $sw{$lastletter} // []; + $outword[$wn]= $aref; + push @stopword, $wn if @$aref==0; +} +#die Dumper \@outword; +#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.. + +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. +# +fun findall( ) +{ + my @sus; # array of two SU lists, sus[curr] stores the current + # list of all SUs for sequences of length N, + # sus[1-curr] builds the NEW list of + # all SUs for sequences of length N+1 + # each SU entry is a [ seqarrayref, usedarrayref ] pair + my $N = 1; # length starts at 1 and is increased.. + my $curr = 0; # start using sus[0] for curr, sus[1] for new.. + + # convert each stopword word no into a SU pair + @sus = ( [], [] ); + @{$sus[0]} = map { [ [ $_ ], [ suset($_) ] ] } @stopword; + + for(;;) + { + my $currsus = $sus[$curr]; + #die Dumper $currsus; + my $nseq = @$currsus; + print "Have $nseq sequences of length $N\n"; + #show_sus( @$currsus ); + + # + # Now let's take every SU (sequence and used set) in + # sus[curr], and lengthen them (storing the results + # in sus[1-curr]), prepending a word number to the start + # of each sequence. This will be possible unless all + # sequences in sus[curr] are already at their maximal + # length - when that happens, we break out of the loop. + # + + my $newsus = $sus[1-$curr]; + @$newsus = (); + foreach my $su (@$currsus) # foreach current SU + { + my( $s, $used ) = @$su; + my $firstwno = $s->[0]; + + # list of word nos into s[0] + my $list = $inword[$firstwno]; + + foreach my $wno (grep { ! $used->[$_] } @$list) + { + # make length N+1 sequence, cons(wno,oldseq) + my @oneseq = @$s; + unshift @oneseq, $wno; + + # alter the used array, marking $wno used. + $used->[$wno] = 1; + + # it's a whole new SU! + push @$newsus, [ \@oneseq, [ @$used ] ]; + + # alter used back + $used->[$wno] = 0; + } + } + last if @$newsus == 0; + $N++; + $curr = 1-$curr; + } + + # now extract and return all the maximal length sequences + + my $currsus = $sus[$curr]; + return map { $_->[0] } @$currsus; +} + + + +# +# my @suset = suset( $wno ); +# Form a SUset in which all word nos are unused, except $wno. +# +fun suset( $wno ) +{ + my @suset = (0) x scalar(@words); + $suset[$wno] = 1; + return @suset; +} + + +# +# show_sus( @sus ); +# Show the sequences (as words, not word nos) contained in SUlist @sus +# +fun show_sus( @sus ) +{ + foreach my $s (@sus) + { + my $str = join( ',', map { $words[$_->[0]] } @$s ); + print "$str\n"; + } +} + + +# +# show_seqs( @seqs ); +# Show the sequences (as words, not word nos) +# +fun show_seqs( @seqs ) +{ + foreach my $s (@seqs) + { + my $str = join( ',', map { $words[$_] } @$s ); + print "$str\n"; + } +} diff --git a/challenge-025/duncan-c-white/perl5/v16-with-histo.pl b/challenge-025/duncan-c-white/perl5/v16-with-histo.pl new file mode 100755 index 0000000000..0a9650debb --- /dev/null +++ b/challenge-025/duncan-c-white/perl5/v16-with-histo.pl @@ -0,0 +1,278 @@ +#!/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. +# + +use v5.10; # to get "say" +use strict; +use warnings; +use Function::Parameters; +use Data::Dumper; +use FindBin qw($Bin); + +use lib "$Bin/../lib"; +use lib "$ENV{HOME}/lib"; +use lib "."; +use Histo; + +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 @outword; # array from word no N to array of wordnos of words going "out" + # from word N, i.e. starting with the last letter of word N + # if there are no such words, then [] + +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 @outword and @stopword, using %sw +foreach my $wn (0..$#words) +{ + my $word = $words[$wn]; + $word =~ /(.)$/; + my $lastletter = $1; + my $aref = $sw{$lastletter} // []; + + # need to exclude $wn from @w if present + my @w = grep { $_ ne $wn } @$aref; + + $outword[$wn]= \@w; + push @stopword, $wn if @w==0; +} +#die Dumper \@outword; +#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} // []; + + # need to exclude $wn from @w if present + my @w = grep { $_ ne $wn } @$aref; + + $inword[$wn]= \@w; +} +#die Dumper \@inword; + +# No longer need %sw or %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. +# +fun findall( ) +{ + my @sus; # array of two SU lists, sus[curr] stores the current + # list of all SUs for sequences of length N, + # sus[1-curr] builds the NEW list of + # all SUs for sequences of length N+1 + # each SU entry is now a triple: + # [ firstwno, seqstr, usedarrayref ] + # (where the sequence is now seqstr, a single string + # comprising the comma-separated list of word nos, + # always starting with firstwno) + my $N = 1; # length starts at 1 and is increased.. + my $curr = 0; # start using sus[0] for curr, sus[1] for new.. + + # convert each stopword word no into a SU triple + @sus = ( [], [] ); + @{$sus[0]} = map { [ $_, $_, [ suset($_) ] ] } @stopword; + + my $maxnused = 0; + my $total = 0; + my $outer = 0; + my $inner = 0; + my %freq; + + my $histo = Histo->new( BINWIDTH => 1 ); + my $histo2 = Histo->new( BINWIDTH => 1 ); + + for(;;) + { + my $currsus = $sus[$curr]; + #die Dumper $currsus; + my $nseq = @$currsus; + print "Have $nseq sequences of length $N\n"; + #show_sus( @$currsus ); + + # + # Now let's take every SU (firstwno/sequence/used set) in + # sus[curr], and lengthen them (storing the results + # in sus[1-curr]), prepending a word number to the start + # of each sequence. This will be possible unless all + # sequences in sus[curr] are already at their maximal + # length - when that happens, we break out of the loop. + # + my $newsus = $sus[1-$curr]; + @$newsus = (); + foreach my $su (@$currsus) # foreach current SU + { + my( $firstwno, $s, $used ) = @$su; + + # find the list of word nos into firstwno + my $list = $inword[$firstwno]; + +$total += @$list; +$outer++; + +my $nused = my @u = grep { $used->[$_] } @$list; +$maxnused = $nused if $nused > $maxnused; +#warn "found $nused used (@u), list=@$list, with firstwno=$firstwno, s=$s!!\n" if $nused > 0; +#warn "all $nused used (@u), list=@$list, with firstwno=$firstwno, s=$s!!\n" if $nused>0 && $nused == @$list; + + # for each unused word no going into firstwno + $histo2->add( scalar(@$list) ); + my @x = grep { ! $used->[$_] } @$list; + # want histogram scalar(@x) + $histo->add( scalar(@x) ); + $freq{ scalar(@x) }++; + + foreach my $wno (@x) + { + $inn |
