[SPOILER] Perl 'Easy' Quiz of the Week #2005-2
Roger Burton West <roger-UvLOT2mcgw/[email protected]> Sun, 13 Feb 2005 11:03:38 +0000
| Newsgroups | gmane.comp.lang.perl.qotw.discuss |
|---|---|
| Message-ID | <[email protected]> |
On Wed, Feb 09, 2005 at 09:30:52AM -0800, Dan Sanderson wrote:
>Write a subroutine called print_list that takes a number indicating
>the width of the display as a number of characters, and a list of
>strings, and prints the strings in a sorted columnar display, using as
>many columns that will fit in the display for the given list and as few
>rows as possible.
Intriguingly complex once one looks at it...
sub print_list {
my ($width,@list)=@_;
my $spacing=2;
@list=sort @list;
my @len=map {length($_)} @list;
$width=&max($width,@len);
push @len,(0) x scalar @len;
my $columns=scalar @list;
my $startinc;
my @colsize;
while (1) {
$startinc=int(scalar @list/$columns+.999999);
@colsize=();
foreach my $cn (0..$columns-1) {
$colsize[$cn]=&max(@len[$startinc*$cn..$startinc*($cn+1)-1])
}
if (&sum(@colsize[0..$columns-1],$spacing*($columns-1)) <= $width) {
last;
} else {
$columns--;
}
}
my $format=join(' ' x $spacing,map {"%-${_}s"} @colsize[0..$columns-1])."\n";
foreach my $row (0..$startinc-1) {
my @c;
foreach my $cn (0..$columns-1) {
my $i=$startinc*$cn+$row;
if ($i<=$#list) {
push @c,$list[$i];
}
}
printf($format,@c);
}
}
sub max {
my @t=@_;
my $a=$t[0];
foreach my $b (@t[1..$#t]) {
if ($b>$a) {
$a=$b;
}
}
return $a;
}
sub sum {
my @t=@_;
my $a=$t[0];
foreach my $b (@t[1..$#t]) {
$a+=$b;
}
return $a;
}
Sorry, no PostScript version...
R