diff options
| author | Mohammad S Anwar <mohammad.anwar@yahoo.com> | 2020-05-04 04:08:12 +0100 |
|---|---|---|
| committer | Mohammad S Anwar <mohammad.anwar@yahoo.com> | 2020-05-04 04:08:12 +0100 |
| commit | 67cdd35efcf8c026c738ede53dcf8662282fbe29 (patch) | |
| tree | d2bd813d75102310bc0c5a90d8f3eb28b3d47e19 /challenge-059/james-smith | |
| parent | 0d75138306bf5598becdcd034ee148ef8fd9da68 (diff) | |
| download | perlweeklychallenge-club-67cdd35efcf8c026c738ede53dcf8662282fbe29.tar.gz perlweeklychallenge-club-67cdd35efcf8c026c738ede53dcf8662282fbe29.tar.bz2 perlweeklychallenge-club-67cdd35efcf8c026c738ede53dcf8662282fbe29.zip | |
- Added template for Challenge 059.
Diffstat (limited to 'challenge-059/james-smith')
| -rw-r--r-- | challenge-059/james-smith/README.md | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/challenge-059/james-smith/README.md b/challenge-059/james-smith/README.md new file mode 100644 index 0000000000..6d816375c5 --- /dev/null +++ b/challenge-059/james-smith/README.md @@ -0,0 +1,129 @@ +Solutions by James Smith. + +# Challenge 1 - Counting letters + +There are two ways to solve this -> split and count or using tr... one is short code - one is longer - but much faster. + +## Version 1 - short code + +Uses lc, split and grep to count the elements and put them in a hash... looping through each file a line at a time with <> + +```perl +use feature 'say'; +use strict; +my %T = map { $_=>0 } foreach 'a'..'z'; +while(<>) { + $T{$_}++ foreach grep { /[a-z]/ } split m{}, lc $_; +} + +say "$_: $T{$_}" foreach 'a'..'z'; +``` + +Running this over 13Mbytes of PHP takes approximately 6.5 seconds... + +## Version 2 - faster code + +Now counting letters in a string is quickest using the tr or y operator - as this requires the number of characters +changed. Without using eval you can't unfortunately sub in a variable into the pattern unlike with m/s... So we +either need to use string eval (which is evIl) or manually replicate the loop - $T{'a'} =~ y/aA/aA/ etc - in this +code... Note we set $/ to undef so that we slurp the whole file in in one go (to improve performance of using tr) +and less modifications to the %T hash... + +```perl +use feature 'say'; +$/=undef; + +while(<>) { + $T{'a'} += y/aA/aA/; + $T{'b'} += y/bB/bB/; +.. +.. + $T{'y'} += y/yY/yY/; + $T{'z'} += y/zZ/zZ/; +} + +say $_,': ',$T{$_}||0 foreach 'a'..'z'; + +``` +OK - so didn't want to type 26 lines so used this one liner to do it for me! + +```bash +perl -E 'say " \$t{'"'"'$_'"'"'} += y/$_".uc($_)."/$_".uc($_)."/;" foreach "a".."z";' +``` + +This now runs in approxy 0.25 seconds a big improvement... + +## Version 3 - nicer output... + +The version 3 code just expands the version 2 code - but creates a "histogram" to show the distribution (and at the same time formats the totals better) + +``` +a : 584193 : ########################## +b : 108267 : #### +c : 287124 : ############# +d : 272798 : ############ +e : 877936 : ######################################## +f : 209371 : ######### +g : 152944 : ###### +h : 200641 : ######### +i : 546465 : ######################## +j : 15133 : +k : 50049 : ## +l : 326976 : ############## +m : 214631 : ######### +n : 438874 : ################### +o : 436059 : ################### +p : 282120 : ############ +q : 19825 : +r : 551144 : ######################### +s : 552344 : ######################### +t : 724711 : ################################# +u : 260233 : ########### +v : 68882 : ### +w : 80759 : ### +x : 57019 : ## +y : 115201 : ##### +z : 11021 : +``` + +# Challenge 2 - multiplication square... + +Again going to extend the challenge to make this generic (in case someone wants a different version) + +Hidden in the solution above was getting the number of digits for a number (so we can format the totals) - we do this again to get the size of the left hand column and the main table columns. + +```perl +my $sl = int(log($N)/log(10)+1); ## Get size of integer $N - defines the width of the LH column +my $sr = int(2*log($N)/log(10)+1); ## Get size of $N squared - defines the width of other columns +``` +and we use this to tweak the formats and the padding/line drawing elements! +```perl +#!/usr/bin/perl + +use strict; +use feature 'say'; + +## This solves more than the puzzle - but thought I would make it more generic! + +## This gets the size of the square that we want to display... + +my $N = shift =~ s{\D}{}gr || 11; ## Default to 11 - but use first parameter as size of square! +my @R = 1..$N; ## Create a "range array" - we use this 4 times!!! + +## Get width of columns for use in the renderer.. + +my $sl = int( log($N) / log(10) + 1); ## Get size of integer $N - defines the width of the LH column +my $sr = int( 2 * log($N) / log(10) + 1); ## Get size of $N squared - defines the width of other columns +my $fl = sprintf ' %%%dd |', $sl; ## Create a template for the first column.. +my $fr = sprintf ' %%%dd', $sr; ## .... and for the other columns! + +## Finally we render - make a use of sprintf with the templates and '$' x $ to generate padding + +say ' ' x $sl, 'x |', ## Header (LH side) + map { sprintf $fr, $_ } @R; ## (column headers) +say join '-', '-' x $sl, '-+', ## Separator (LH side) + map { '-' x $sr } @R; ## (RH side) +say sprintf( $fl, $a=$_ ), ## Body of table (LH headers) + map { $a>$_ ? ' ' x ($sr+1) : sprintf $fr, $a*$_ } @R ## (content of row) + foreach @R; +``` |
