Perl 'Expert' Quiz-of-the-Week #5
Mark Jason Dominus <[email protected]> Wed, 13 Nov 2002 18:19:05 -0500
| Newsgroups | gmane.comp.lang.perl.qotw.quiz-of-the-week |
|---|---|
| Organization | Plover Systems |
| Message-ID | <[email protected]> |
IMPORTANT: Please do not post solutions, hints, or other spoilers
until at least 60 hours after the date of this message.
Thanks.
IMPORTANTE: Por favor, no enviéis soluciones, pistas, o cualquier otra
cosa que pueda echar a perder la resolución del problema hasta
que hayan pasado por lo menos 60 horas desde el envío de este
mensaje. Gracias.
IMPORTANT: S'il vous plaît, attendez au minimum 60 heures après la
date de ce message avant de poster solutions, indices ou autres
révélations. Merci.
WICHTIG: Bitte schicken Sie keine Lösungen, Tipps oder Hinweise für
diese Aufgabe vor Ablauf von 60 Stunden nach dem Datum dieser
Mail. Danke.
Qing3 Zhu4Yi4: Qing3 Ning2 Deng3Dao4 Jie1Dao4 Ben3 Xin4Xi2 Zhi1Hou4 60
Xiao3Shi2, Zai4 Fa1Biao3 Jie3Da2, Ti2Shi4, Huo4 Qi2Ta1 Hui4
Xie4Lou4 Da2An4 De5 Jian4Yi4. Xie4Xie4.
----------------------------------------------------------------
You will write a function that lays out tree diagrams.
layout_tree's arguments will be (1) an object that represents a tree,
and (2) an optional hash containing some configuration parameters.
The tree object is opaque to your function, but is guaranteed to
support at least the following methods:
$tree->children
Returns a list of tree objects that represent the subtrees
of this tree
$tree->text
Returns a reference to an array of strings that show how the
root node of this tree should be displayed.
An example $tree object might be manufactured by the following class:
package ExampleTree;
# Create a new tree object
# arguments: ->(label of root node,
# [arguments for child 1],
# [arguments for child 2],
# ...);
sub new {
my ($pack, $label, @subnodes) = @_;
my @subobjects = map $pack->new(@$_), @subnodes;
bless [$label, @subobjects] => $pack;
}
# If the label of the tree node is 'foo',
# we format it like this:
# +-----+
# | foo |
# +-----+
sub text {
my $self = shift;
my $label = $self->[0];
my $ln = length $label;
$label .= " " x (5 - $ln) if $ln < 5; # pad with spaces to width 5
$ln = length $label;
my $top = "+" . "-" x $ln . "+";
return [$top, "|$label|", $top];
}
sub children {
my $self = shift;
my @children = @$self;
shift @children; # throw away the label
@children;
}
And then one might create such an object by calling
my $t = ExampleTree->new("5",
["4 1",
["3 1 1",
["2 1 1 1",
["1 1 1 1 1"],
],
],
["2 2 1"]
],
["3 2"]);
layout_tree($t) would then manufacture an array of strings, which,
when printed, would look something like this:
+-----+
|5 |
+-----+
,-' `--------.
+-----+ +-----+
|4 1 | |3 2 |
+-----+ +-----+
,-' `----.
+-----+ +-----+
|3 1 1| |2 2 1|
+-----+ +-----+
|
+-------+
|2 1 1 1|
+-------+
|
+---------+
|1 1 1 1 1|
+---------+
Details of exactly how this is laid out and what it looks like are up
to you; you might produce output like this instead:
+-----+ +-----+ +-----+ +-------+ +---------+
|5 |-+-|4 1 |-+-|3 1 1|---|2 1 1 1|---|1 1 1 1 1|
+-----+ | +-----+ | +-----+ +-------+ +---------+
| |
| | +-----+
| +-|2 2 1|
| +-----+
| +-----+
+-|3 2 |
+-----+
However, the tree node displays returned by ->text must appear in the
output exactly as they were returned, and it must be possible to
understand the tree structure from looking at the output.