In that case, try this:
#! perl -slw
use strict;
sub _pathsFrom {
my( $code, $graph, $start, $path, $seen ) = @_;
return $code->( @$path, $start )
unless exists $graph->{ $start };
for my $next ( @{ $graph->{ $start } } ) {
if( exists $seen->{ "$start-$next" } ) {
return $code->( @$path, $start );
}
else {
_pathsFrom(
$code, $graph, $next,
[ @$path, $start ],
{ %$seen, "$start-$next", undef }
);
}
}
}
sub pathsFrom(&@) { _pathsFrom( @_, [], {} ) }
my %graph = (
a => [ 'b' ],
b => [ 'c' ],
c => [ 'd', 'j' ],
d => [ 'e', 'g' ],
g => [ 'h' ],
h => [ 'c' ],
j => [ 'k' ],
);
pathsFrom{
print join '->', @_;
} \%graph, 'a';
__END__
c:\test>904729-2
a->b->c->d->e
a->b->c->d->g->h->c->j->k
a->b->c->j->k
This version is the identical algorithm but somewhat more efficient:
use enum qw[ CODE GRAPH START PATH SEEN ];
sub _pathsFrom2 {
return $_[CODE]->( @{ $_[PATH] }, $_[START] )
unless exists $_[GRAPH]->{ $_[START] };
for ( @{ $_[GRAPH]->{ $_[START] } } ) {
if( exists $_[SEEN]->{ $_[START] . "-$_" } ) {
return $_[CODE]->( @{ $_[PATH] }, $_[START] );
}
else {
_pathsFrom2(
@_[ CODE, GRAPH ], $_,
[ @{ $_[PATH] }, $_[START] ],
{ %{ $_[SEEN] }, $_[START] . "-$_", undef }
);
}
}
}
sub pathsFrom(&@) { _pathsFrom2( @_, [], {} ) }
BTW: If you have a dataset that forms a decent sized test I'd like to get a copy as I've found generating legal directed graphs quite difficult.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
Read Where should I post X? if you're not absolutely sure you're posting in the right place.
Please read these before you post! —
Posts may use any of the Perl Monks Approved HTML tags:
- a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
|
For: |
|
Use: |
| & | | & |
| < | | < |
| > | | > |
| [ | | [ |
| ] | | ] |
Link using PerlMonks shortcuts! What shortcuts can I use for linking?
See Writeup Formatting Tips and other pages linked from there for more info.