← Index
NYTProf Performance Profile   « line view »
For v10.pl
  Run on Sun Jan 5 18:02:42 2020
Reported on Sun Jan 5 18:02:56 2020

Filename/homes/dcw/public_html/PSD/article13/v10.pl
StatementsExecuted 10774263 statements in 4.87s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
1114.87s4.87smain::::findall main::findall
1112.10ms3.15msmain::::BEGIN@32 main::BEGIN@32
1111.23ms4.40msmain::::BEGIN@31 main::BEGIN@31
1111.11ms1.11msmain::::BEGIN@30 main::BEGIN@30
111233µs253µsmain::::BEGIN@29 main::BEGIN@29
2421208µs208µsmain::::CORE:say main::CORE:say (opcode)
2804137µs37µsmain::::CORE:match main::CORE:match (opcode)
121129µs29µsmain::::suset main::suset
11114µs19µsmain::::show_seqs main::show_seqs
1119µs9µsmain::::BEGIN@28 main::BEGIN@28
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# optimization v10: more efficient reuse of arrays in new findall() 5.0s
20# refactoring v9: merge outer for loop and lengthen() into findall 5.8s
21# optimization v8: alter used set rather than rebuild it 5.8s
22# optimization v7: seqs->sus (don't rebuild used set each time) 6.0s
23# optimization v6: complete reimplementation, iterative version 7.9s
24# ...
25# optimization v1: baseline code before starting to optimize: 32.6s.
26#
27
28228µs19µs
# spent 9µs within main::BEGIN@28 which was called: # once (9µs+0s) by main::NULL at line 28
use v5.10; # to get "say"
# spent 9µs making 1 call to main::BEGIN@28
292148µs2255µs
# spent 253µs (233+20) within main::BEGIN@29 which was called: # once (233µs+20µs) by main::NULL at line 29
use strict;
# spent 253µs making 1 call to main::BEGIN@29 # spent 2µs making 1 call to strict::import
3021.05ms21.12ms
# spent 1.11ms (1.11+5µs) within main::BEGIN@30 which was called: # once (1.11ms+5µs) by main::NULL at line 30
use warnings;
# spent 1.11ms making 1 call to main::BEGIN@30 # spent 4µs making 1 call to warnings::import
31254µs24.51ms
# spent 4.40ms (1.23+3.17) within main::BEGIN@31 which was called: # once (1.23ms+3.17ms) by main::NULL at line 31
use Function::Parameters;
# spent 4.40ms making 1 call to main::BEGIN@31 # spent 107µs making 1 call to Function::Parameters::import
322218µs23.16ms
# spent 3.15ms (2.10+1.05) within main::BEGIN@32 which was called: # once (2.10ms+1.05ms) by main::NULL at line 32
use Data::Dumper;
# spent 3.15ms making 1 call to main::BEGIN@32 # spent 12µs making 1 call to Exporter::import
33
341500nsmy $debug = @ARGV>0;
35
3613µsmy @words = qw(audino bagon baltoy banette bidoof braviary bronzor carracosta
37 charmeleon cresselia croagunk darmanitan deino emboar emolga
38 exeggcute gabite girafarig gulpin haxorus heatmor heatran ivysaur
39 jellicent jumpluff kangaskhan kricketune landorus ledyba loudred
40 lumineon lunatone machamp magnezone mamoswine nosepass petilil
41 pidgeotto pikachu pinsir poliwrath poochyena porygon2 porygonz
42 registeel relicanth remoraid rufflet sableye scolipede scrafty
43 seaking sealeo silcoon simisear snivy snorlax spoink starly
44 tirtouga trapinch treecko tyrogue vigoroth vulpix wailord
45 wartortle whismur wingull yamask);
46#@words = qw(hello ollie excellent thanks shelter runaround set to);
47
481100nsmy %sw; # hash from letter L to list of word nos of words STARTING with L
49
50my @stopword;# list of stop word nos (word nos of words with no words going
51 # "out" from them onto another word, ie. word numbers N where
52 # no other word starts with the last letter of word N)
53
54my %ew; # hash from letter L to list of word nos of words ENDING with L
55
56my @inword; # array from word no N to array of wordnos of words going "in"
57 # to word N, i.e. ending with the first letter of word N
58 # if there are no such words, then []
59
60# build %sw
611800nsforeach my $wn (0..$#words)
62{
63707µs my $word = $words[$wn];
647043µs709µs $word =~ /^(.)/;
# spent 9µs making 70 calls to main::CORE:match, avg 123ns/call
65708µs my $firstletter = $1;
667012µs $sw{$firstletter} //= [];
677017µs push @{$sw{$firstletter}}, $wn;
68}
69#die Dumper \%sw;
70
71# build %ew
721400nsforeach my $wn (0..$#words)
73{
74707µs my $word = $words[$wn];
757042µs7010µs $word =~ /(.)$/;
# spent 10µs making 70 calls to main::CORE:match, avg 144ns/call
76707µs my $lastletter = $1;
777011µs $ew{$lastletter} //= [];
787016µs push @{$ew{$lastletter}}, $wn;
79}
80#die Dumper \%ew;
81
82# build @stopword, using %sw
831400nsforeach my $wn (0..$#words)
84{
85706µs my $word = $words[$wn];
867040µs7010µs $word =~ /(.)$/;
# spent 10µs making 70 calls to main::CORE:match, avg 146ns/call
87707µs my $lastletter = $1;
88709µs my $aref = $sw{$lastletter} // [];
897012µs push @stopword, $wn if @$aref==0;
90}
91#die Dumper [ map { $words[$_] } @stopword ];
92
93# build @inword, using %ew
941200nsforeach my $wn (0..$#words)
95{
96706µs my $word = $words[$wn];
977039µs708µs $word =~ /^(.)/;
# spent 8µs making 70 calls to main::CORE:match, avg 111ns/call
98707µs my $firstletter = $1;
99709µs my $aref = $ew{$firstletter} // [];
1007012µs $inword[$wn]= $aref;
101}
102#die Dumper \@inword;
103
104# No longer need %sw or %ew.. only @inword and @stopword
105
10617µs14.87smy @sus = findall();
# spent 4.87s making 1 call to main::findall
107
108#show_seqs( @sus );
109
110# show just one of the longest sequences
11113µs119µsshow_seqs( @sus[0..0] );
# spent 19µs making 1 call to main::show_seqs
112
1131100nsexit 0;
114
- -
117#
118# my @suset = suset( $wno );
119# Form a SUset in which all word nos are unused, except $wno.
120#
121
# spent 29µs within main::suset which was called 12 times, avg 2µs/call: # 12 times (29µs+0s) by main::findall at line 157, avg 2µs/call
fun suset( $wno )
122362µs{
123128µs my @suset = (0) x scalar(@words);
12412700ns $suset[$wno] = 1;
1251220µs return @suset;
126146µs14µs}
# spent 4µs making 1 call to Function::Parameters::_register_info
127
128
129#
130# show_seqs( @sus );
131# Show the sequences (as words, not word nos)
132#
133
# spent 19µs (14+4) within main::show_seqs which was called: # once (14µs+4µs) by main::RUNTIME at line 111
fun show_seqs( @sus )
1341500ns{
13512µs foreach my $su (@sus)
136 {
1371300ns my( $s, $u ) = @$su;
13819µs my $str = join( ',', map { $words[$_] } @$s );
13916µs14µs say $str;
# spent 4µs making 1 call to main::CORE:say
140 }
1411108µs13µs}
# spent 3µs making 1 call to Function::Parameters::_register_info
142
143
144#
145# my @sus = findall();
146# Find all sequences, starting with sequences of length 1 (stop words),
147# then working back, i.e. prepending words onto the front of existing
148# sequences. Delivers the list of all maximal-length sequences, each
149# as a (sequence,usedset) pair.
150#
151
# spent 4.87s (4.87+233µs) within main::findall which was called: # once (4.87s+233µs) by main::RUNTIME at line 106
fun findall( )
1521200ns{
1531100ns my $sus; # all SUs for sequences of length N,
154 # each entry is a [ seqarrayref, usedarrayref ] pair
155
156 # convert each stopword wordno into a SU pair, building a list
1571321µs1229µs $sus = [ map { [ [ $_ ], [ suset($_) ] ] } @stopword ];
# spent 29µs making 12 calls to main::suset, avg 2µs/call
158
159118µs for( my $N=1 ; ; $N++)
160 {
1612312µs my $nseq = @$sus;
16223327µs23204µs say "Have $nseq sequences of length $N";
# spent 204µs making 23 calls to main::CORE:say, avg 9µs/call
163 #show_seqs( @$sus );
164
165 # Take @$sus, a list of SUs of length N and ending in a
166 # stopword, and try to lengthen them all backwards, ie.
167 # prepend a word number to the start of each sequence.
168
169 # If this is possible, ie. if there is at least one extensible
170 # SU, then change $sus to be the new, longer SUlist (all of
171 # length N+1 now), and carry on looping. Else break out.
172
1732313µs my $new = []; # new list of SUs
174
1752343µs foreach my $su (@$sus) # foreach current SU
176 {
1771346584279ms my( $s, $used ) = @$su;
1781346584175ms my $list = $inword[$s->[0]]; # list of word nos into s[0]
1791346584661ms foreach my $wno (grep { ! $used->[$_] } @$list)
180 {
181 # make a single length N+1 sequence, cons(wno,oldseq)
1821346572367ms my @oneseq = @$s;
1831346572313ms unshift @oneseq, $wno;
184
185 # alter the used array, marking $wno used.
186134657289.5ms $used->[$wno] = 1;
187
188 # it's a new SU!
18913465721.56s push @$new, [ \@oneseq, [ @$used ] ];
190 #say "debug: ", Dumper(\@oneseq) if $N==22;
191
192 # alter used back
1931346572230ms $used->[$wno] = 0;
194 }
195 }
196236µs last unless @$new;
197221.18s $sus = $new;
198 }
19911.40ms return @$sus;
200141µ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 (500ns+0s) by constant::BEGIN@24 at line 33 of constant.pm # once (400ns+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 37µs within main::CORE:match which was called 280 times, avg 131ns/call: # 70 times (10µs+0s) by main::RUNTIME at line 86, avg 146ns/call # 70 times (10µs+0s) by main::RUNTIME at line 75, avg 144ns/call # 70 times (9µs+0s) by main::RUNTIME at line 64, avg 123ns/call # 70 times (8µs+0s) by main::RUNTIME at line 97, avg 111ns/call
sub main::CORE:match; # opcode
# spent 208µs within main::CORE:say which was called 24 times, avg 9µs/call: # 23 times (204µs+0s) by main::findall at line 162, avg 9µs/call # once (4µs+0s) by main::show_seqs at line 139
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