← Index
NYTProf Performance Profile   « line view »
For v5.pl
  Run on Sun Sep 22 16:32:09 2019
Reported on Sun Sep 22 16:32:53 2019

Filename/homes/dcw/src/perl/weeklychallenge/perlweeklychallenge-club/challenge-025/duncan-c-white/perl5/v5.pl
StatementsExecuted 42822429 statements in 12.2s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
50160782112.2s12.2smain::::findseq main::findseq (recurses: max depth 22, inclusive time 165s)
1111.38ms4.85msmain::::BEGIN@33 main::BEGIN@33
1111.27ms1.28msmain::::BEGIN@32 main::BEGIN@32
111277µs303µsmain::::BEGIN@31 main::BEGIN@31
1402131µs31µsmain::::CORE:match main::CORE:match (opcode)
11118µs18µsmain::::CORE:print main::CORE:print (opcode)
11113µs13µsmain::::BEGIN@30 main::BEGIN@30
1114µs4µsUNIVERSAL::::VERSIONUNIVERSAL::VERSION (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 v5: major data structure changes: used word numbers not
20# words in several places, used arrays not hashes 12.0s
21# optimization v4: instead of extracting the last letter of each word,
22# precalculate %lw: word->last letter of word 14.8s
23# optimization v3: instead of cloning the used set to modify it,
24# modify it, pass it, and then change it back 21.1s
25# optimization v2: instead of recalculating the "used set" each time,
26# pass it around, modifying it as we go 28.8s
27# optimization v1: baseline code before starting to optimize: 32.6s.
28#
29
30234µs113µs
# spent 13µs within main::BEGIN@30 which was called: # once (13µs+0s) by main::NULL at line 30
use v5.10; # to get "say"
# spent 13µs making 1 call to main::BEGIN@30
312184µs2306µs
# spent 303µs (277+26) within main::BEGIN@31 which was called: # once (277µs+26µs) by main::NULL at line 31
use strict;
# spent 303µs making 1 call to main::BEGIN@31 # spent 2µs making 1 call to strict::import
3221.20ms21.28ms
# spent 1.28ms (1.27+6µs) within main::BEGIN@32 which was called: # once (1.27ms+6µs) by main::NULL at line 32
use warnings;
# spent 1.28ms making 1 call to main::BEGIN@32 # spent 4µs making 1 call to warnings::import
332271µs24.97ms
# spent 4.85ms (1.38+3.47) within main::BEGIN@33 which was called: # once (1.38ms+3.47ms) by main::NULL at line 33
use Function::Parameters;
# spent 4.85ms making 1 call to main::BEGIN@33 # spent 126µs making 1 call to Function::Parameters::import
34#use Data::Dumper;
35
361600nsmy $debug = @ARGV>0;
37
3813µsmy @words = qw(audino bagon baltoy banette bidoof braviary bronzor carracosta
39 charmeleon cresselia croagunk darmanitan deino emboar emolga
40 exeggcute gabite girafarig gulpin haxorus heatmor heatran ivysaur
41 jellicent jumpluff kangaskhan kricketune landorus ledyba loudred
42 lumineon lunatone machamp magnezone mamoswine nosepass petilil
43 pidgeotto pikachu pinsir poliwrath poochyena porygon2 porygonz
44 registeel relicanth remoraid rufflet sableye scolipede scrafty
45 seaking sealeo silcoon simisear snivy snorlax spoink starly
46 tirtouga trapinch treecko tyrogue vigoroth vulpix wailord
47 wartortle whismur wingull yamask);
48#@words = qw(hello ollie excellent thanks shelter runaround set to);
49
501100nsmy %sw; # hash from letter to list of word nos starting with that letter.
51
52my %snew;# hash from letter to whether or not there ARE any words starting
53 # with that latter; 0 for no, 1 for yes.
54
55my @lw; # mapping from word no to last letter of word.
56
571900nsforeach my $letter ('a'..'z')
58{
59268µs $snew{$letter} = 0;
60}
61
621800nsforeach my $wordno (0..$#words)
63{
64708µs my $word = $words[$wordno];
657052µs7016µs $word =~ /^(.)/;
# spent 16µs making 70 calls to main::CORE:match, avg 230ns/call
66709µs my $letter = $1;
677012µs $sw{$letter} //= [];
687012µs push @{$sw{$letter}}, $wordno;
69707µs $snew{$letter} = 1;
70
717046µs7015µs $word =~ /(.)$/;
# spent 15µs making 70 calls to main::CORE:match, avg 209ns/call
727023µs $lw[$wordno] = $1;
73}
74
75#die Dumper \%sw;
76#die Dumper \%snew;
77#die Dumper \@lw;
78
791200nsmy @longseq = (); # longest sequence found so far..
80
81# search for sequences starting with each word in turn..
821600nsforeach my $sw (0..$#words)
83{
8470172µs7012.2s findseq( $sw, [ (0) x scalar(@words)], () );
# spent 12.2s making 70 calls to main::findseq, avg 175ms/call
85}
86
871200nsmy $longest = @longseq;
8815µs@longseq = map { $words[$_] } @longseq;
89
90126µs118µsprint "\nlongest sequence is length $longest: @longseq\n";
# spent 18µs making 1 call to main::CORE:print
9110sexit 0;
92
93
94#
95# findseq( $currwno, $used, @seq );
96# Find all sequences of words from $currwno onwards,
97# given that we've already visited wordnos in @seq,
98# (the same info, as a set of word nos, is in @$used)
99# and update the global @longseq if any sequences
100# we find are longer than that.
101#
102
# spent 12.2s (12.2+-0ns) within main::findseq which was called 5016078 times, avg 2µs/call: # 5016008 times (12.2s+-12.2s) by main::findseq at line 112, avg 0s/call # 70 times (213µs+12.2s) by main::RUNTIME at line 84, avg 175ms/call
fun findseq( $currwno, $used, @seq )
103100321561.45s{
1045016078297ms push @seq, $currwno; # extend @seq sequence
1055016078315ms $used->[$currwno]=1; # update $used set
1065016078408ms my $lastletter = $lw[$currwno]; # last letter of currw
107
10850160781.59s if( $snew{$lastletter} ) # any words starting with letter?
109 {
110 foreach my $nextwordno (grep { ! $used->[$_] } @{$sw{$lastletter}})
111 {
11250160082.03s50160080s findseq( $nextwordno, $used, @seq );
# spent 165s making 5016008 calls to main::findseq, avg 33µs/call, recursion: max depth 22, sum of overlapping time 165s
113 }
114 } else # @seq is finished
115 {
116 #print "found sequence @seq\n";
1171346584104ms my $len = @seq;
1181346584105ms if( $len > @longseq )
119 {
120161µs print "longest seq so far (len $len): @seq\n" if $debug;
121167µs @longseq = @seq;
122 }
123 }
12450160785.95s $used->[$currwno]=0;
125147µs15µs}
# spent 5µs making 1 call to Function::Parameters::_register_info
 
# 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 31µs within main::CORE:match which was called 140 times, avg 219ns/call: # 70 times (16µs+0s) by main::RUNTIME at line 65, avg 230ns/call # 70 times (15µs+0s) by main::RUNTIME at line 71, avg 209ns/call
sub main::CORE:match; # opcode
# spent 18µs within main::CORE:print which was called: # once (18µs+0s) by main::RUNTIME at line 90
sub main::CORE:print; # opcode