#!/usr/bin/perl use strict; use warnings; my %tree = ( FOO => [qw/BAR BLAH ASDF/], BAR => [qw/LA/], BLAH => [qw/XYZ/], ASDF => [qw/OOOOO/], LA => [], XYZ => [qw/LA/], OOOOO => [] ); { my %seen; my %onstack; my @list; sub how_to_uninstall { my $target = shift; ### COMMENT OUT THE FOLLOWING LINE ### # (@list, %seen, %onstack) = (); print "HOWTO ($target) START\n"; _traverse($target); ### NEW STUFF ### for my $token (keys(%tree)) { for (@{$tree{$token}}) { if (defined($seen{$_}) != 1) { how_to_uninstall($token); } } } ### END NEW STUFF ### print "HOWTO ($target) FINISH\n"; return @list; } sub _traverse { my $x = shift; print " TRAVERSE ($x) START\n"; $seen{$x} = $onstack{$x} = 1; for my $y (@{$tree{$x}}) { die "cyclic!" if $onstack{$y}; # back edge print " Found $y\n"; _traverse($y) unless $seen{$y}; } push @list, $x; $onstack{$x} = 0; print " TRAVERSE ($x) FINISH\n"; } } my @order = how_to_uninstall('BLAH'); print "\nANSWER = @order\n"; #### {C} > 808487.pl HOWTO (BLAH) START TRAVERSE (BLAH) START Found XYZ TRAVERSE (XYZ) START Found LA TRAVERSE (LA) START TRAVERSE (LA) FINISH TRAVERSE (XYZ) FINISH TRAVERSE (BLAH) FINISH HOWTO (ASDF) START TRAVERSE (ASDF) START Found OOOOO TRAVERSE (OOOOO) START TRAVERSE (OOOOO) FINISH TRAVERSE (ASDF) FINISH HOWTO (FOO) START TRAVERSE (FOO) START Found BAR TRAVERSE (BAR) START Found LA TRAVERSE (BAR) FINISH Found BLAH Found ASDF TRAVERSE (FOO) FINISH HOWTO (FOO) FINISH HOWTO (ASDF) FINISH HOWTO (BLAH) FINISH ANSWER = LA XYZ BLAH OOOOO ASDF BAR FOO