PERL WEEKLY CHALLENGE – 032

This is my second week participating into the weekly challenge and I grow more impressed by Raku each time I look at the documentation. There is quite a bit to assimilate.

Apologies for not having the syntax highlighter on some of the solutions as the > symbols become & gt; and ruins the solution.


Easy Challenge

“Create a script that either reads standard input or one or more files specified on the command-line. Count the number of times and then print a summary, sorted by the count of each entry.”

Example file

apple
banana
apple
cherry
cherry
apple

This wasn’t too difficult, use Getopt::Long to capture the csv flag and use a hash to store the counts. I used STDIN rather than read one or more files out of pure laziness. Same for not using Text::CSV to output the CSV.

Perl 5 solution

#!/usr/bin/perl
# Test: cat example.txt | ./ch1.pl

use strict;
use warnings;
use Getopt::Long;

my $use_csv = 0;
my %counts;

GetOptions ("csv" => \$use_csv);

# Increment the counts hash for each line
for my $line ( <STDIN> ) {
	chomp($line);
	$counts{$line}++;
}

# Print the aggregated line items
for my $item (sort keys %counts) {
	if ($use_csv) {
		# Normally i'd use a module like Text::CSV
		print $item . ',' . $counts{$item};
	} else {
		printf("%-10s %d", $item, $counts{$item})
	}
	print "\n";
}

Output

apple      3
banana     1
cherry     2

Raku solution

# Test: cat example.txt | perl6 ch1.p6
use v6.d;
use Getopt::Long;
get-options("csv" => my $use_csv);

sub MAIN () {
	my %counts;

	# Increment the counts hash for each line
	for $*IN.lines() -> $line {
		%counts{$line.chomp}++ 	
	};

	# Print the aggregated line items
	for %counts.keys.sort -> $item {
		if ($use_csv) {
			# Normally i'd use a module like Text::CSV
			say $item ~ ',' ~ %counts{$item};
		} else {
			"%-10s %d\n".printf($item, %counts{$item});
		}
	}
}

Output

apple      3
banana     1
cherry     2

Hard Challenge

“Write a function that takes a hashref where the keys are labels and the values are integer or floating point values. Generate a bar graph of the data and display it to stdout. If you fancy then please try this as well: (a) the function could let you specify whether the chart should be ordered by (1) the labels, or (2) the values.”

Also not too difficult just a matter of using printf to format the text and create some sorting functions.

Doing it in raku and using when is awesome. Also not having to coerce the string multiplier ( x )’s value into an int is quite nice too.

Perl 5 solution

#!/usr/bin/perl

use 5.18.4; # for fc
use strict;
use warnings;

my $data   = { apple => 3, cherry => 2, banana => 1 };
my $params = { order_by => 'name' };
generate_bar_graph($data, $params);

# Generates the ASCII bar graph
sub generate_bar_graph {
	my ($data, $params) = @_;
	my $sort_func;

	# Sorting function - just 2 for now
	$sort_func = sub { $data->{$::b} <=> $data->{$::a} }
		if ($params->{order_by} eq 'size');
	$sort_func = sub { fc($::a) cmp fc($::b) }
		if ($params->{order_by} eq 'name');

	# Print the chart
	for my $key (sort $sort_func keys %$data) {
		printf("%10s | %s \n",
			$key, '#' x int(scalar($data->{$key}) * 4));
	}
}

Output

     apple | ############
    cherry | ########
    banana | ####

Raku solution

# Test: perl6 ch2.p6
use v6.d;

sub MAIN () {
	my %data   = 'apple' => 3,  'cherry' => 2, 'banana' => 1;
	my %params = 'order_by' => 'size';
	generate_bar_graph(%data, %params);
}

sub generate_bar_graph (%data, %params) {
	my $sort_func;

	# Sorting function - just 2 for now
	{
		when (%params.{'order_by'} eq 'size') {
			$sort_func = sub { %data.{$^b} <=> %data.{$^a} };
		}

		when (%params.{'order_by'} eq 'name') {
			$sort_func = sub { fc($^a) cmp fc($^b) };
		}
	}

	# Print the chart
	for %data.keys.sort($sort_func) -> $key {
		"%10s | %s \n".printf($key, '#' x (4 * %data.{$key}));
	}
}

Output

     apple | ############
    cherry | ########
    banana | ####

One thought on “PERL WEEKLY CHALLENGE – 032

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s