← Index
NYTProf Performance Profile   « line view »
For v7.pl
  Run on Fri Jan 3 17:50:04 2020
Reported on Fri Jan 3 17:50:20 2020

Filename/homes/dcw/public_html/PSD/article13/v7.pl
StatementsExecuted 12121005 statements in 5.97s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
23115.97s5.97smain::::lengthen main::lengthen
1112.81ms4.19msmain::::BEGIN@29 main::BEGIN@29
1111.59ms5.48msmain::::BEGIN@28 main::BEGIN@28
1111.31ms1.32msmain::::BEGIN@27 main::BEGIN@27
111274µs302µsmain::::BEGIN@26 main::BEGIN@26
2421212µs212µsmain::::CORE:say main::CORE:say (opcode)
2804192µs92µsmain::::CORE:match main::CORE:match (opcode)
121141µs41µsmain::::suset main::suset
11118µs23µsmain::::show_seqs main::show_seqs
11110µs10µsmain::::BEGIN@25 main::BEGIN@25
1115µs5µsUNIVERSAL::::VERSIONUNIVERSAL::VERSION (xsub)
3311µs1µsInternals::::SvREADONLYInternals::SvREADONLY (xsub)
111500ns500nsmro::::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 v7: seqs->sus (don't rebuild used set each time) 6.0s
20# optimization v6: complete reimplementation, iterative version 7.9s
21# ...
22# optimization v1: baseline code before starting to optimize: 32.6s.
23#
24
25228µs110µs
# spent 10µs within main::BEGIN@25 which was called: # once (10µs+0s) by main::NULL at line 25
use v5.10; # to get "say"
# spent 10µs making 1 call to main::BEGIN@25
262175µs2304µs
# spent 302µs (274+27) within main::BEGIN@26 which was called: # once (274µs+27µs) by main::NULL at line 26
use strict;
# spent 302µs making 1 call to main::BEGIN@26 # spent 2µs making 1 call to strict::import
2721.25ms21.32ms
# spent 1.32ms (1.31+6µs) within main::BEGIN@27 which was called: # once (1.31ms+6µs) by main::NULL at line 27
use warnings;
# spent 1.32ms making 1 call to main::BEGIN@27 # spent 4µs making 1 call to warnings::import
28264µs25.62ms
# spent 5.48ms (1.59+3.89) within main::BEGIN@28 which was called: # once (1.59ms+3.89ms) by main::NULL at line 28
use Function::Parameters;
# spent 5.48ms making 1 call to main::BEGIN@28 # spent 141µs making 1 call to Function::Parameters::import
292384µs24.21ms
# spent 4.19ms (2.81+1.38) within main::BEGIN@29 which was called: # once (2.81ms+1.38ms) by main::NULL at line 29
use Data::Dumper;
# spent 4.19ms making 1 call to main::BEGIN@29 # spent 16µs making 1 call to Exporter::import
30
3111µsmy $debug = @ARGV>0;
32
3316µsmy @words = qw(audino bagon baltoy banette bidoof braviary bronzor carracosta
34 charmeleon cresselia croagunk darmanitan deino emboar emolga
35 exeggcute gabite girafarig gulpin haxorus heatmor heatran ivysaur
36 jellicent jumpluff kangaskhan kricketune landorus ledyba loudred
37 lumineon lunatone machamp magnezone mamoswine nosepass petilil
38 pidgeotto pikachu pinsir poliwrath poochyena porygon2 porygonz
39 registeel relicanth remoraid rufflet sableye scolipede scrafty
40 seaking sealeo silcoon simisear snivy snorlax spoink starly
41 tirtouga trapinch treecko tyrogue vigoroth vulpix wailord
42 wartortle whismur wingull yamask);
43#@words = qw(hello ollie excellent thanks shelter runaround set to);
44
451200nsmy %sw; # hash from letter L to list of word nos of words STARTING with L
46
47my @stopword;# list of stop word nos (word nos of words with no words going
48 # "out" from them onto another word, ie. word numbers N where
49 # no other word starts with the last letter of word N)
50
51my %ew; # hash from letter L to list of word nos of words ENDING with L
52
53my @inword; # array from word no N to array of wordnos of words going "in"
54 # to word N, i.e. ending with the first letter of word N
55 # if there are no such words, then []
56
57# build %sw
5812µsforeach my $wn (0..$#words)
59{
60709µs my $word = $words[$wn];
617063µs7017µs $word =~ /^(.)/;
# spent 17µs making 70 calls to main::CORE:match, avg 243ns/call
627011µs my $firstletter = $1;
637016µs $sw{$firstletter} //= [];
647022µs push @{$sw{$firstletter}}, $wn;
65}
66#die Dumper \%sw;
67
68# build %ew
691700nsforeach my $wn (0..$#words)
70{
717011µs my $word = $words[$wn];
727080µs7027µs $word =~ /(.)$/;
# spent 27µs making 70 calls to main::CORE:match, avg 389ns/call
737013µs my $lastletter = $1;
747017µs $ew{$lastletter} //= [];
757030µs push @{$ew{$lastletter}}, $wn;
76}
77#die Dumper \%ew;
78
79# build @stopword, using %sw
8011µsforeach my $wn (0..$#words)
81{
827012µs my $word = $words[$wn];
837083µs7028µs $word =~ /(.)$/;
# spent 28µs making 70 calls to main::CORE:match, avg 396ns/call
847013µs my $lastletter = $1;
857016µs my $aref = $sw{$lastletter} // [];
867031µs push @stopword, $wn if @$aref==0;
87}
88#die Dumper [ map { $words[$_] } @stopword ];
89
90# build @inword, using %ew
911900nsforeach my $wn (0..$#words)
92{
93709µs my $word = $words[$wn];
947066µs7020µs $word =~ /^(.)/;
# spent 20µs making 70 calls to main::CORE:match, avg 284ns/call
957011µs my $firstletter = $1;
967016µs my $aref = $ew{$firstletter} // [];
977021µs $inword[$wn]= $aref;
98}
99#die Dumper \@inword;
100
101# No longer need %sw or %ew..
102
1031200nsmy $N = 1; # length starts at 1 and is increased..
104
1051100nsmy @sus; # all SUs for sequences of length N,
106 # each entry is a [ seqarrayref, usedarrayref ] pair
107
108# convert each stopword wordno into a SU pair, building a list of them all
1091330µs1241µs@sus = map { [ [ $_ ], [ suset($_) ] ] } @stopword;
# spent 41µs making 12 calls to main::suset, avg 3µs/call
110
1111100nsfor(;;)
112{
1132313µs my $nseq = @sus;
11423267µs23206µs say "Have $nseq sequences of length $N";
# spent 206µs making 23 calls to main::CORE:say, avg 9µs/call
115 #show_seqs( @sus );
1162353µs235.97s my $ok = lengthen( \@sus, $N );
# spent 5.97s making 23 calls to main::lengthen, avg 259ms/call
117237µslast unless $ok;
1182212µs $N++;
119}
120
121#show_seqs( @sus );
122
123# show just one of the longest sequences
12413µs123µsshow_seqs( @sus[0..0] );
# spent 23µs making 1 call to main::show_seqs
125
12610sexit 0;
127
128
129#
130# my @suset = suset( $wno );
131# Form a SUset in which all word nos are unused, except $wno.
132#
133
# spent 41µs within main::suset which was called 12 times, avg 3µs/call: # 12 times (41µs+0s) by main::RUNTIME at line 109, avg 3µs/call
fun suset( $wno )
134364µs{
1351212µs my @suset = (0) x scalar(@words);
136121µs $suset[$wno] = 1;
1371228µs return @suset;
138193µs17µs}
# spent 7µs making 1 call to Function::Parameters::_register_info
139
140
141#
142# show_seqs( @sus );
143# Show the sequences (as words, not word nos)
144#
145
# spent 23µs (18+5) within main::show_seqs which was called: # once (18µs+5µs) by main::RUNTIME at line 124
fun show_seqs( @sus )
1461500ns{
14712µs foreach my $su (@sus)
148 {
1491400ns my( $s, $u ) = @$su;
150111µs my $str = join( ',', map { $words[$_] } @$s );
15119µs15µs say $str;
# spent 5µs making 1 call to main::CORE:say
152 }
1531210µs16µs}
# spent 6µs making 1 call to Function::Parameters::_register_info
154
155
156#
157# my $ok = lengthen( $sus, $N );
158# Take $sus, a reference of a list of SUs, where each SU is a
159# [ sequence, usedset ] pair, and each sequence is of length N and
160# ends in a stopword, and try to lengthen them all backwards, ie.
161# prepending a word number to the start of each sequence.
162# If this is possible, then @$sus is altered to deliver the new, longer
163# SUlist (all of length N+1 now), and 1 is returned. Otherwise, if
164# lengthening is not possible, leave @$sus alone, and return 0.
165#
166
# spent 5.97s within main::lengthen which was called 23 times, avg 259ms/call: # 23 times (5.97s+0s) by main::RUNTIME at line 116, avg 259ms/call
fun lengthen( $sus, $N )
1676931µs{
168234µs my @new; # new list of SUs
169
17023117µs foreach my $su (@$sus) # foreach current SU
171 {
1721346584321ms my( $s, $used ) = @$su;
1731346584209ms my $firstwno = $s->[0];
1741346584109ms my $list = $inword[$firstwno]; # list of word nos into s[0]
175
1761346584563ms foreach my $wno (grep { ! $used->[$_] } @$list)
177 {
178 # make a single length N+1 sequence, cons(wno,oldseq)
1791346572453ms my @oneseq = @$s;
1801346572354ms unshift @oneseq, $wno;
181
182 # make an altered used array, with one more used.
18313465721.64s my @newu = @$used;
184134657288.4ms $newu[$wno] = 1;
185
186 # it's a new SU!
1871346572537ms push @new, [ \@oneseq, \@newu ];
188 #say "debug: ", Dumper(\@oneseq) if $N==22;
189 }
190 }
191238µs if( @new )
192 {
193221.53s @$sus = @new;
19422167ms return 1;
195 }
19613µs return 0;
197183µs15µs}
# spent 5µs making 1 call to Function::Parameters::_register_info
 
# spent 1µs within Internals::SvREADONLY which was called 3 times, avg 467ns/call: # once (900ns+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 5µs within UNIVERSAL::VERSION which was called: # once (5µs+0s) by Function::Parameters::BEGIN@7 at line 24 of Scalar/Util.pm
sub UNIVERSAL::VERSION; # xsub
# spent 92µs within main::CORE:match which was called 280 times, avg 328ns/call: # 70 times (28µs+0s) by main::RUNTIME at line 83, avg 396ns/call # 70 times (27µs+0s) by main::RUNTIME at line 72, avg 389ns/call # 70 times (20µs+0s) by main::RUNTIME at line 94, avg 284ns/call # 70 times (17µs+0s) by main::RUNTIME at line 61, avg 243ns/call
sub main::CORE:match; # opcode
# spent 212µs within main::CORE:say which was called 24 times, avg 9µs/call: # 23 times (206µs+0s) by main::RUNTIME at line 114, avg 9µs/call # once (5µs+0s) by main::show_seqs at line 151
sub main::CORE:say; # opcode
# spent 500ns within mro::method_changed_in which was called: # once (500ns+0s) by constant::import at line 198 of constant.pm
sub mro::method_changed_in; # xsub