Skip to content

Commit b7d0b9b

Browse files
committed
Depends.pm: add Depends::tsort
1 parent dd51867 commit b7d0b9b

File tree

1 file changed

+62
-1
lines changed

1 file changed

+62
-1
lines changed

perl/AUR/Depends.pm

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ use List::Util qw(first);
77
use Carp;
88
use Exporter qw(import);
99
use AUR::Vercmp qw(vercmp);
10-
our @EXPORT_OK = qw(recurse prune graph);
1110

1211
use constant EX_SUCCESS => 0;
1312
use constant EX_FAILURE => 1;
1413
use constant EX_OUT_OF_RANGE => 34;
14+
our @EXPORT_OK = qw(recurse prune graph tsort);
1515
our $VERSION = 'unstable';
1616

1717
# Maximum number of calling the callback
@@ -296,4 +296,65 @@ sub prune {
296296
return @removals;
297297
}
298298

299+
=head2 tsort()
300+
301+
Topological sorting adapted from PerlPowerTools.
302+
303+
=Performs depth-first traversal by default.
304+
305+
=over
306+
307+
=item C<$bfs> Perform breadth-first traversal.
308+
309+
=back
310+
311+
=cut
312+
313+
sub tsort {
314+
my ($bfs, $input) = @_;
315+
$bfs //= 0;
316+
317+
my %pairs; # all pairs ($l, $r)
318+
my %npred; # number of predecessors
319+
my %succ; # list of successors
320+
my @output;
321+
322+
if (scalar(@{$input}) % 2 == 1) {
323+
say STDERR __PACKAGE__ . ": odd number of tokens";
324+
exit EX_FAILURE;
325+
}
326+
327+
while (@{$input}) {
328+
my $l = shift @${input};
329+
my $r = shift @${input};
330+
331+
next if defined $pairs{$l}{$r};
332+
$pairs{$l}{$r}++;
333+
$npred{$l} += 0;
334+
335+
next if $l eq $r;
336+
++$npred{$r};
337+
push @{$succ{$l}}, $r;
338+
}
339+
340+
# create a list of nodes without predecessors
341+
my @list = grep {!$npred{$_}} keys %npred;
342+
343+
while (@list) {
344+
$_ = pop @list;
345+
push @output, $_;
346+
347+
foreach my $child (@{$succ{$_}}) {
348+
if ($bfs) { # breadth-first
349+
unshift @list, $child unless --$npred{$child};
350+
} else { # depth-first (default)
351+
push @list, $child unless --$npred{$child};
352+
}
353+
354+
}
355+
}
356+
warn "$Program: cycle detected\n" if grep {$npred{$_}} keys %npred;
357+
358+
return @output;
359+
}
299360
# vim: set et sw=4 sts=4 ft=perl:

0 commit comments

Comments
 (0)