SPOILER - Perl Easy quiz 2005-2

Chris Charley <charley-UXds4KHJg9RWk0Htik3J/[email protected]> Sun, 13 Feb 2005 01:06:01 +0000 (UTC)
Newsgroups gmane.comp.lang.perl.qotw.discuss
Message-ID <[email protected]>
Hi

First time caller  :-)

My solution matched the requirements for the test cases given
by Dan for the <AT> strings array for widths of 1, 30, 40, and 80.

I ran tests with other numbers of values in the strings array
as well as various other widths and got reasonable results.

The algorithm was: start with one name per column and then 2 names
per column and so on until the width of the columns was less than
or equal to the desired width. 

Like:
	Abby  Al  Constance  Daniel  Jonathan  Julia  Sam  Terrence
	
	Abby  Constance    Jonathan  Sam  
	Al    Daniel       Julia     Terrence
	
I enjoyed working on this quiz. In the Perl Cookbook
(in the chapter on arrays), there is a very similiar example
(transforming rows to cols) which I briefly examined (but
I think the spacing requirements were different than this quiz).

Chris

#!/usr/bin/perl
use strict;
use warnings;
use List::Util qw/max sum/;


sub print_list {
	my $width = shift  or die $!;
	my @data = sort @_ or die $!;
	
	my  <AT> cols;
	my  <AT> col_wids;
	for my $offset (0.. <AT> data) {
		 <AT> cols = ();
		for (my $i = 0; $i <  <AT> data; $i += $offset+1) {
			my $end = $i+$offset < $#data ? $i+$offset : $#data;
			push  <AT> cols, [  <AT> data[$i..$end] ];
		}
		 <AT> col_wids = map {max_len( <AT> $_)}  <AT> cols;

		# last if spaces between cols + width of total cols <= $width
		last if 2 * ( <AT> cols -1) + sum( <AT> col_wids) <= $width;
	}
	my  <AT> rows = cols2rows( <AT> cols);
	for my $row ( <AT> rows) {
		$row = join "  ", 
				map{ sprintf "%-$col_wids[$_]s", $row->[$_] } 
0..$#$row;
	}
	print join("\n",  <AT> rows), "\n";
}

sub max_len {
	my  <AT> lens = map {length}  <AT> _;
	return max( <AT> lens);
}

sub cols2rows {
	my  <AT> cols =  <AT> _;
	my  <AT> rows;
	while(1) {
		last unless grep  <AT> $_,  <AT> cols;
		push  <AT> rows, [ map{ <AT> $_ ? shift  <AT> $_ : ""}  <AT> 
cols ];
	}
	return  <AT> rows;
}