The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!perl
use strict;
use warnings;
use 5.010_000;
use feature ':5.10';
use File::Basename qw( dirname );
use lib dirname(__FILE__);
use TM qw( size );
use Getopt::Long qw( GetOptions );

GetOptions(
    help => sub { die 'pod2usage( -verbose => 2 )' },
    
    
my $in_edge  = "$ARGV[0].fulledge";
my $out_edge = "$ARGV[0].edge";

say "Read $in_edge (@{[ size( -s $in_edge ) ]})";
my $edge = retrieve( $in_edge );

# Find the shortest paths to each node except the ones that go directly from 'root'. I want at least a /little/ indirection.
my %paths;
our %WALK;
walk( 'root' );
undef %WALK;

# Compute all the parent -> @children paths
my %edges;
for my $child ( keys %paths ) {
    my $path = delete $paths{$child};
    
    my $parent = $path->[1]; # $path->[0] eq $child
    next if ! defined $parent;
    
    push @{ $edges{$parent} }, $child;
}

store( \ %edges, $out_edge );
say "Wrote $out_edge (@{[ size( -s $out_edge ) ]})";

sub walk {
    my $node = $_[-0];

    # Do not recurse infinitely.
    return if $WALK{$node};
    local $WALK{$node} = 1;

    # Process this path.
    my $prev = $paths{$node};
    if ( ! $prev ) {
        $paths{$node} = [ @_ ];
    }
    elsif ( @$prev <= 1 ) {
        # say "Preferring [@_] to [@$prev] because \@\$prev <= 1";
        $paths{$node} = [ @_ ];
    }
    elsif ( @_ > 2 && @$prev > @_ ) {
        # say "Preferring [@_] to [@$prev] because \@_ > 2 && \@\$prev > \@_";
        $paths{$node} = [ @_ ];
    }

    # Find children to recurse into.
    my $children = $edge->{$node};
    return if ! $children;

    # Recurse into children.
    walk( $_, @_ ) for keys %$children;
}