← Index
NYTProf Performance Profile   « line view »
For v9.pl
  Run on Sun Jan 5 18:04:27 2020
Reported on Sun Jan 5 18:04:41 2020

Filename/homes/dcw/public_html/PSD/article13/v9.pl
StatementsExecuted 10774263 statements in 5.85s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
1115.84s5.84smain::::findall main::findall
1112.11ms3.15msmain::::BEGIN@31 main::BEGIN@31
1111.27ms4.43msmain::::BEGIN@30 main::BEGIN@30
1111.14ms1.14msmain::::BEGIN@29 main::BEGIN@29
111234µs254µsmain::::BEGIN@28 main::BEGIN@28
2421199µs199µsmain::::CORE:say main::CORE:say (opcode)
2804160µs60µsmain::::CORE:match main::CORE:match (opcode)
121130µs30µsmain::::suset main::suset
11118µs23µsmain::::show_seqs main::show_seqs
1119µs9µsmain::::BEGIN@27 main::BEGIN@27
1114µs4µsUNIVERSAL::::VERSIONUNIVERSAL::VERSION (xsub)
3311µs1µsInternals::::SvREADONLYInternals::SvREADONLY (xsub)
111400ns400nsmro::::method_changed_in mro::method_changed_in (xsub)
0000s0smain::::RUNTIME main::RUNTIME
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1#!/usr/bin/perl
2#
3# Challenge 1: "Generate a longest sequence of the following "English Pokemon"
4# names where each name starts with the last letter of the previous name:
5#
6# audino bagon baltoy banette bidoof braviary bronzor carracosta
7# charmeleon cresselia croagunk darmanitan deino emboar emolga
8# exeggcute gabite girafarig gulpin haxorus heatmor heatran ivysaur
9# jellicent jumpluff kangaskhan kricketune landorus ledyba loudred
10# lumineon lunatone machamp magnezone mamoswine nosepass petilil
11# pidgeotto pikachu pinsir poliwrath poochyena porygon2 porygonz
12# registeel relicanth remoraid rufflet sableye scolipede scrafty
13# seaking sealeo silcoon simisear snivy snorlax spoink starly
14# tirtouga trapinch treecko tyrogue vigoroth vulpix wailord
15# wartortle whismur wingull yamask"
16#
17# My notes: Clearly defined, nice, potentially tricky, let's do it.
18#
19# refactoring v9: merge outer for loop and lengthen() into findall 5.7s
20# optimization v8: alter used set rather than rebuild it 5.8s
21# optimization v7: seqs->sus (don't rebuild used set each time) 6.0s
22# optimization v6: complete reimplementation, iterative version 7.9s
23# ...
24# optimization v1: baseline code before starting to optimize: 32.6s.
25#
26
27226µs19µs
# spent 9µs within main::BEGIN@27 which was called: # once (9µs+0s) by main::NULL at line 27
use v5.10; # to get "say"
# spent 9µs making 1 call to main::BEGIN@27
282149µs2256µs
# spent 254µs (234+20) within main::BEGIN@28 which was called: # once (234µs+20µs) by main::NULL at line 28
use strict;
# spent 254µs making 1 call to main::BEGIN@28 # spent 2µs making 1 call to strict::import
2921.08ms21.15ms
# spent 1.14ms (1.14+5µs) within main::BEGIN@29 which was called: # once (1.14ms+5µs) by main::NULL at line 29
use warnings;
# spent 1.14ms making 1 call to main::BEGIN@29 # spent 3µs making 1 call to warnings::import
30254µs24.54ms
# spent 4.43ms (1.27+3.16) within main::BEGIN@30 which was called: # once (1.27ms+3.16ms) by main::NULL at line 30
use Function::Parameters;
# spent 4.43ms making 1 call to main::BEGIN@30 # spent 107µs making 1 call to Function::Parameters::import
312218µs23.16ms
# spent 3.15ms (2.11+1.04) within main::BEGIN@31 which was called: # once (2.11ms+1.04ms) by main::NULL at line 31
use Data::Dumper;
# spent 3.15ms making 1 call to main::BEGIN@31 # spent 12µs making 1 call to Exporter::import
32
331500nsmy $debug = @ARGV>0;
34
3513µsmy @words = qw(audino bagon baltoy banette bidoof braviary bronzor carracosta
36 charmeleon cresselia croagunk darmanitan deino emboar emolga
37 exeggcute gabite girafarig gulpin haxorus heatmor heatran ivysaur
38 jellicent jumpluff kangaskhan kricketune landorus ledyba loudred
39 lumineon lunatone machamp magnezone mamoswine nosepass petilil
40 pidgeotto pikachu pinsir poliwrath poochyena porygon2 porygonz
41 registeel relicanth remoraid rufflet sableye scolipede scrafty
42 seaking sealeo silcoon simisear snivy snorlax spoink starly
43 tirtouga trapinch treecko tyrogue vigoroth vulpix wailord
44 wartortle whismur wingull yamask);
45#@words = qw(hello ollie excellent thanks shelter runaround set to);
46
471100nsmy %sw; # hash from letter L to list of word nos of words STARTING with L
48
49my @stopword;# list of stop word nos (word nos of words with no words going
50 # "out" from them onto another word, ie. word numbers N where
51 # no other word starts with the last letter of word N)
52
53my %ew; # hash from letter L to list of word nos of words ENDING with L
54
55my @inword; # array from word no N to array of wordnos of words going "in"
56 # to word N, i.e. ending with the first letter of word N
57 # if there are no such words, then []
58
59# build %sw
601800nsforeach my $wn (0..$#words)
61{
62706µs my $word = $words[$wn];
637051µs7016µs $word =~ /^(.)/;
# spent 16µs making 70 calls to main::CORE:match, avg 234ns/call
64709µs my $firstletter = $1;
657011µs $sw{$firstletter} //= [];
667018µs push @{$sw{$firstletter}}, $wn;
67}
68#die Dumper \%sw;
69
70# build %ew
711400nsforeach my $wn (0..$#words)
72{
73707µs my $word = $words[$wn];
747055µs7016µs $word =~ /(.)$/;
# spent 16µs making 70 calls to main::CORE:match, avg 234ns/call
75708µs my $lastletter = $1;
767011µs $ew{$lastletter} //= [];
777018µs push @{$ew{$lastletter}}, $wn;
78}
79#die Dumper \%ew;
80
81# build @stopword, using %sw
821400nsforeach my $wn (0..$#words)
83{
84705µs my $word = $words[$wn];
857046µs7014µs $word =~ /(.)$/;
# spent 14µs making 70 calls to main::CORE:match, avg 203ns/call
86707µs my $lastletter = $1;
877010µs my $aref = $sw{$lastletter} // [];
887013µs push @stopword, $wn if @$aref==0;
89}
90#die Dumper [ map { $words[$_] } @stopword ];
91
92# build @inword, using %ew
931200nsforeach my $wn (0..$#words)
94{
95706µs my $word = $words[$wn];
967043µs7013µs $word =~ /^(.)/;
# spent 13µs making 70 calls to main::CORE:match, avg 186ns/call
97707µs my $firstletter = $1;
98709µs my $aref = $ew{$firstletter} // [];
997014µs $inword[$wn]= $aref;
100}
101#die Dumper \@inword;
102
103# No longer need %sw or %ew.. only @inword and @stopword
104
10515.52ms15.84smy @sus = findall();
# spent 5.84s making 1 call to main::findall
106
107#show_seqs( @sus );
108
109# show just one of the longest sequences
11014µs123µsshow_seqs( @sus[0..0] );
# spent 23µs making 1 call to main::show_seqs
111
1121100nsexit 0;
113
- -
116#
117# my @suset = suset( $wno );
118# Form a SUset in which all word nos are unused, except $wno.
119#
120
# spent 30µs within main::suset which was called 12 times, avg 3µs/call: # 12 times (30µs+0s) by main::findall at line 156, avg 3µs/call
fun suset( $wno )
121363µs{
1221211µs my @suset = (0) x scalar(@words);
12312800ns $suset[$wno] = 1;
1241219µs return @suset;
125151µs14µs}
# spent 4µs making 1 call to Function::Parameters::_register_info
126
127
128#
129# show_seqs( @sus );
130# Show the sequences (as words, not word nos)
131#
132
# spent 23µs (18+5) within main::show_seqs which was called: # once (18µs+5µs) by main::RUNTIME at line 110
fun show_seqs( @sus )
1331400ns{
13412µs foreach my $su (@sus)
135 {
1361500ns my( $s, $u ) = @$su;
137111µs my $str = join( ',', map { $words[$_] } @$s );
13818µs15µs say $str;
# spent 5µs making 1 call to main::CORE:say
139 }
1401109µs13µs}
# spent 3µs making 1 call to Function::Parameters::_register_info
141
142
143#
144# my @sus = findall();
145# Find all sequences, starting with sequences of length 1 (stop words),
146# then working back, i.e. prepending words onto the front of existing
147# sequences. Delivers the list of all maximal-length sequences, each
148# as a (sequence,usedset) pair.
149#
150
# spent 5.84s (5.84+224µs) within main::findall which was called: # once (5.84s+224µs) by main::RUNTIME at line 105
fun findall( )
1511200ns{
1521100ns my @sus; # all SUs for sequences of length N,
153 # each entry is a [ seqarrayref, usedarrayref ] pair
154
155 # convert each stopword wordno into a SU pair, building a list
1561322µs1230µs @sus = map { [ [ $_ ], [ suset($_) ] ] } @stopword;
# spent 30µs making 12 calls to main::suset, avg 3µs/call
157
158121µs for( my $N=1 ; ; $N++)
159 {
1602316µs my $nseq = @sus;
16123351µs23194µs say "Have $nseq sequences of length $N";
# spent 194µs making 23 calls to main::CORE:say, avg 8µs/call
162 #show_seqs( @sus );
163
164 # Take @sus, a list of SUs of length N and ending in a
165 # stopword, and try to lengthen them all backwards, ie.
166 # prepend a word number to the start of each sequence.
167
168 # If this is possible, ie. if there is at least one extensible
169 # SU, then change @sus to be the new, longer SUlist (all of
170 # length N+1 now), and carry on looping. Else break out.
171
172234µs my @new; # new list of SUs
173
1742316µs foreach my $su (@sus) # foreach current SU
175 {
1761346584335ms my( $s, $used ) = @$su;
1771346584204ms my $list = $inword[$s->[0]]; # word nos into s[0]
1781346584614ms foreach my $wno (grep { ! $used->[$_] } @$list)
179 {
180 # make a single length N+1 sequence, cons(wno,oldseq)
1811346572444ms my @oneseq = @$s;
1821346572344ms unshift @oneseq, $wno;
183
184 # alter the used array, marking $wno used.
185134657291.6ms $used->[$wno] = 1;
186
187 # it's a new SU!
18813465721.94s push @new, [ \@oneseq, [ @$used ] ];
189 #say "debug: ", Dumper(\@oneseq) if $N==22;
190
191 # alter used back
1921346572230ms $used->[$wno] = 0;
193 }
194 }
1952310µs last unless @new;
196221.64s @sus = @new;
197 }
1981169µs return @sus;
199140µs13µs}
# spent 3µs making 1 call to Function::Parameters::_register_info
 
# spent 1µs within Internals::SvREADONLY which was called 3 times, avg 333ns/call: # once (600ns+0s) by constant::BEGIN@24 at line 33 of constant.pm # once (300ns+0s) by constant::import at line 164 of constant.pm # once (100ns+0s) by constant::BEGIN@24 at line 34 of constant.pm
sub Internals::SvREADONLY; # xsub
# spent 4µs within UNIVERSAL::VERSION which was called: # once (4µs+0s) by Function::Parameters::BEGIN@7 at line 24 of Scalar/Util.pm
sub UNIVERSAL::VERSION; # xsub
# spent 60µs within main::CORE:match which was called 280 times, avg 214ns/call: # 70 times (16µs+0s) by main::RUNTIME at line 74, avg 234ns/call # 70 times (16µs+0s) by main::RUNTIME at line 63, avg 234ns/call # 70 times (14µs+0s) by main::RUNTIME at line 85, avg 203ns/call # 70 times (13µs+0s) by main::RUNTIME at line 96, avg 186ns/call
sub main::CORE:match; # opcode
# spent 199µs within main::CORE:say which was called 24 times, avg 8µs/call: # 23 times (194µs+0s) by main::findall at line 161, avg 8µs/call # once (5µs+0s) by main::show_seqs at line 138
sub main::CORE:say; # opcode
# spent 400ns within mro::method_changed_in which was called: # once (400ns+0s) by constant::import at line 198 of constant.pm
sub mro::method_changed_in; # xsub