While
Graph can certainly do this for you, understanding the graph theory involved is a good idea. Basically, here's what you do:
- For each available vertex:
- Select it ($seen{$vertex} = 1)
- Push the vertex to the current path (push @path, $vertex)
- If the number of vertices in the path equals the desired length (@path == $len)
- Store the path in the master list (push @all_paths, [@path])
- Else:
- Set "available vertices" to all unseen adjacent vertices (grep { !$seen{$_} } @{ $adjacent{$vertex} })
- Repeat from top
- Remove the latest vertex added to the path (pop @path)
- Un-select the vertex ($seen{$vertex} = 0)
This is a relatively simple recursive process. The code is basically something like:
my $paths_ref = get_paths(\%adjaceny_matrix, $length);
sub get_paths {
my ($adj, $len) = @_;
my @paths;
_get_paths_helper(\@paths, $adj, $len, [], {}, [keys %$adj]);
return \@paths;
}
sub _get_paths_helper {
my ($p, $am, $len, $curr, $seen, $avail) = @_;
for my $v (@$avail) {
push @$curr, $v;
local $seen->{$v} = 1;
if (@$curr == $len) { push @$p, [@$curr] }
else {
_get_paths_helper($p, $am, $len, $curr, $seen, [grep { !$seen->{
+$_} } @{ $am->{$v} }]);
}
pop @$curr;
}
}
This can be modified to allow you to search for multiple depths without having to call the main function multiple times (which would be terribly inefficient!).