diff options
| author | Ryan Thompson <i@ry.ca> | 2019-11-02 18:07:25 -0600 |
|---|---|---|
| committer | Ryan Thompson <i@ry.ca> | 2019-11-02 18:07:25 -0600 |
| commit | ed35b511e8ed24f1c6f0de037e08f74665c6d0cf (patch) | |
| tree | 05063ab60ac6c356048d971d68a62bf2732aeb97 /challenge-032/ryan-thompson/perl5 | |
| parent | 7a2acac4849ee76c96c510aa64d9fc4502854c0e (diff) | |
| download | perlweeklychallenge-club-ed35b511e8ed24f1c6f0de037e08f74665c6d0cf.tar.gz perlweeklychallenge-club-ed35b511e8ed24f1c6f0de037e08f74665c6d0cf.tar.bz2 perlweeklychallenge-club-ed35b511e8ed24f1c6f0de037e08f74665c6d0cf.zip | |
Week 32 solutions
Diffstat (limited to 'challenge-032/ryan-thompson/perl5')
| -rwxr-xr-x | challenge-032/ryan-thompson/perl5/ch-1.pl | 26 | ||||
| -rwxr-xr-x | challenge-032/ryan-thompson/perl5/ch-2.pl | 55 |
2 files changed, 81 insertions, 0 deletions
diff --git a/challenge-032/ryan-thompson/perl5/ch-1.pl b/challenge-032/ryan-thompson/perl5/ch-1.pl new file mode 100755 index 0000000000..3ec455ad1c --- /dev/null +++ b/challenge-032/ryan-thompson/perl5/ch-1.pl @@ -0,0 +1,26 @@ +#!/usr/bin/env perl + +# Instance Count +# +# Ryan Thompson <rjt@cpan.org> + +use strict; +use warnings; +no warnings 'uninitialized'; +use List::Util qw< max >; + +# -csv must be first argument, in case you need to process a file named '-csv' +# Usually I'd use Getopt::Long, but this is even simpler. +my $csv = $ARGV[0] eq '-csv' ? shift : 0; + +my %count; # string => count +chomp, $count{$_}++ while <>; + +# Pretty output is better than a lower constant on your complexity. :-) +my $key_width = max map { length } keys %count; +my $val_width = max map { length } values %count; +my $fmt = $csv ? "%s,%d\n" : "%-${key_width}s %${val_width}d\n"; + +# Sort by result count, then alphabetically by keyword +printf $fmt, $_, $count{$_} + for sort { $count{$a} <=> $count{$b} || $a cmp $b } keys %count; diff --git a/challenge-032/ryan-thompson/perl5/ch-2.pl b/challenge-032/ryan-thompson/perl5/ch-2.pl new file mode 100755 index 0000000000..1d90fe363c --- /dev/null +++ b/challenge-032/ryan-thompson/perl5/ch-2.pl @@ -0,0 +1,55 @@ +#!/usr/bin/env perl + +# ASCII Bar Chart +# +# I've added the optional "sort by" option, and then I went and added +# negative numbers and auto-scaling to a user-specified --width for fun. +# +# Ryan Thompson <rjt@cpan.org> + +use 5.010; +use strict; +use warnings; +use List::Util qw/min max/; +use Math::Round; + +my %data = ( foo => 10, bar => 20, foobar => 50 ); + +print_bar_graph_simple(\%data); +say ''; +print_bar_graph({ %data, neg => -25 }, { char => '=', width => 50 }); + +# Simple version. Auto-sizes the labels, that's about it. +sub print_bar_graph_simple { + my ($data) = @_; + + my $len = max map { length } keys %$data; + printf "%-${len}s | %s\n", $_, '#' x round($data->{$_}) + for sort keys %$data; +} + +# "Deluxe" version with scaling, custom bars, and negative number support +# by_key: True = Sort by key, then value [Default: value, then key ] +# width: Scale to total width, including labels [Default: undef (no scale)] +# char: Character to use for bars in bar chart [Default: # ] +sub print_bar_graph { + my ($data, $opts) = @_; + + my $sort = $opts->{by_key} + ? sub { $a cmp $b || $data->{$a} <=> $data->{$b} } + : sub { $data->{$a} <=> $data->{$b} || $a cmp $b }; + + # Housekeeping for number scaling and label sizing + my $len = max map { length } keys %$data; + my $width = $opts->{width} ? $opts->{width} - $len - 1 : 0; + my $max = max $width, values %$data; + my $negmax = min 0, values %$data; + my $scale = $width ? $width / (abs($negmax) + 1 + $max) : 1; + my $negpad = round($scale * abs($negmax)); + + printf "%-${len}s %${negpad}s|%s\n", $_, + $data->{$_} < 0 + ? ( $opts->{char} x round(abs($data->{$_}) * $scale), '') + : ('', $opts->{char} x round( $data->{$_} * $scale)) + for sort $sort keys %$data; +} |
