aboutsummaryrefslogtreecommitdiff
path: root/challenge-032/ryan-thompson/perl5
diff options
context:
space:
mode:
authorRyan Thompson <i@ry.ca>2019-11-02 18:07:25 -0600
committerRyan Thompson <i@ry.ca>2019-11-02 18:07:25 -0600
commited35b511e8ed24f1c6f0de037e08f74665c6d0cf (patch)
tree05063ab60ac6c356048d971d68a62bf2732aeb97 /challenge-032/ryan-thompson/perl5
parent7a2acac4849ee76c96c510aa64d9fc4502854c0e (diff)
downloadperlweeklychallenge-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-xchallenge-032/ryan-thompson/perl5/ch-1.pl26
-rwxr-xr-xchallenge-032/ryan-thompson/perl5/ch-2.pl55
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;
+}