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;
}