Skip to content

Instantly share code, notes, and snippets.

@MadcapJake
Last active May 16, 2016 03:43
Show Gist options
  • Save MadcapJake/efbcb2400c061c30fc9cb713a263c7c7 to your computer and use it in GitHub Desktop.
Save MadcapJake/efbcb2400c061c30fc9cb713a263c7c7 to your computer and use it in GitHub Desktop.
Perl 6 Graph Theory
class Graph {
has array[int] %!repr{Int};
has int $.elems;
submethod BUILD(Str:D :$input) {
# Adjacenyc matrix
($!elems, my $edges) = $_[0].Int, $_[1..*] given $input.lines;
%!repr = 1..$!elems Z=> array[int].new(0 xx $!elems) xx $!elems;
for $edges».split(' ')».Int.flat -> @e {
my int ($x, $y) = @e[0..1];
++%!repr{$x}[$y - 1]; ++%!repr{$y}[$x - 1]
}
}
method adjacency { %!repr.sort(*.key)».values.flat.map: *.say }
method degrees {
say "Node $_.key() has a degree of {[+] $_.value}" for %!repr.sort(*.key)
}
method ecc($v) { max (self.path($v, $_):cost for %!repr.keys.grep(* != $v)) }
method rad { min (self.ecc($_) for %!repr.keys) }
method diam { max (self.ecc($_) for %!repr.keys) }
method path(Int $from, Int $to, :cost($c)) {
die "$from is not in graph" unless %!repr{$from};
die "$to is not in graph" unless %!repr{$to};
return 0 if $from == $to;
my int @nodes = %!repr.keys;
my int @path = $from;
my Set $to-visit .= new(|@nodes);
my %cost = @nodes »=>» Nil;
%cost{$from} = 0;
$to-visit (-)= $from;
my $x = $from;
loop {
"Checking $x\'s connections".say;
for %!repr{$x}.grep(*.so, :k).map(* + 1) -> $y {
"\tChecking cost from $x to $y".say;
my $new-cost = %cost{$y} min (%cost{$x}//0) + 1;
if not %cost{$y}.so orelse $new-cost < %cost{$y} {
"\t\tUpdating cost of $y to ¤$new-cost".say;
%cost{$y} = $new-cost;
@path = |@path, $y;
last if $y == $to;
}
$to-visit (-)= $y;
}
%cost.grep(*.value.so).say;
last unless $to-visit;
$x = $to-visit.first.key;
$to-visit (-)= $x;
}
$c ?? @path.elems - 1 !! @path
}
=begin naive
method connected(Int $i, Int $j --> Int) {
return 0 if $i == $j;
my array[int] @paths = %!repr{$i}.grep(*.so, :k).map({array[int].new($i, $_+1)});
return 1 if $j == @paths».[*-1].any;
repeat {
for @paths <-> @path {
given %!repr{@path[*-1]}
.grep(*.so, :k)
.map(* + 1)
.grep(* != @path.any) {
say "Current path: @path[]";
say "Possible next nodes: $_";
@paths.push(array[int].new(|@path, $_)) for $_[1..*];
@path.push: $_[0] if so $_;
}
}
my @reached = @paths.grep(*.[*-1] == $j);
return min @reached».elems if so @reached;
} until $!nodes == @paths».elems.all;
-1
}
=end naive
}
given Graph.new(input => $input) {
.adjacency;
.path(2,3).say;
# .ecc(2).say;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment