结合一组可逆路径

时间:2016-09-01 00:29:46

标签: arrays perl set

我需要一些帮助来识别这个问题并找到解决方案。我不需要有人来编写解决方案,只是说如何解决它。

哈希数组,每个哈希包含一个路径,其ID及其顺序(前向(F)或反向(R))

每条路径都在F位置初始化

my @paths = (
    { id => 1, path => [ A, B ],    order => 'F' },
    { id => 2, path => [ C, D, E ], order => 'F' },
    { id => 3, path => [ E, B ],    order => 'F' }
);

每个路径的每个节点或顶点也有一个方向(+或 - )

my %plus_minus;
$plus_minus{1}{A} = '+';
$plus_minus{1}{B} = '+';
$plus_minus{2}{C} = '+';
$plus_minus{2}{D} = '-';
$plus_minus{2}{E} = '-';
$plus_minus{3}{E} = '-';
$plus_minus{3}{B} = '-';

您可以反转路径的顺序(例如,[A,B]到[B,A]) 当您从F =>逆转订单时R或R => F您还可以将路径中每个节点的方向从+切换到 - 或 - 到+

方向的路径如下所示:

  1. A +:B +

  2. C +:D-:E -

  3. E-:B-

  4. 这是问题输入

    对于输出,我想知道是否可以通过反转路径顺序来创建共识路径,以及执行此操作的方式是什么,以确保您找到共识路径。

    例如,如果我们颠倒路径1,我们会得到:

    1. B-:A -
    2. C +:D-:E -
    3. E-:B-
    4. 和由此产生的共识路径是:

      C +:D-:E-:B-:A-

      但目前尚不清楚首先反转路径1。例如,如果我们首先反转3怎么办?所以你不能随意进行。

      有没有人认识到这个问题或知道如何解决它?

1 个答案:

答案 0 :(得分:1)

您所要求的并不容易,而且我对您的要求并不十分清楚

这种局部解决方案采用蛮力方法创建有向图,添加数据及其反转的所有路径,并在结果数据结构中找到最长路径

使用您的示例数据,它会生成您期望的共识路径 反向 ,但根据您的规则,将始终存在如果有任何两个同样有效的答案,并且由于Perl哈希的随机性,任何一个都可以作为从一次运行到下一次运行的结果呈现

如果我理解正确,那么您还需要确保结果包含原始数据中的所有路径

use strict;
use warnings 'all';
use feature 'say';

use Graph::Directed;
use List::Util 'max';
use List::MoreUtils 'first_index';

my @paths = (
    { id => 1, path => [ qw[ A B ] ],   order => 'F' },
    { id => 2, path => [ qw[ C D E ] ], order => 'F' },
    { id => 3, path => [ qw[ E B ] ],   order => 'F' },
);

my %plus_minus;
$plus_minus{1}{A} = '+';
$plus_minus{1}{B} = '+';
$plus_minus{2}{C} = '+';
$plus_minus{2}{D} = '-';
$plus_minus{2}{E} = '-';
$plus_minus{3}{E} = '-';
$plus_minus{3}{B} = '-';

# index the array by ID
#
my %paths;
$paths{$_->{id}} = $_ for @paths;

# Incorporate the inexplicably separate plus-minus data
#
for my $id ( keys %plus_minus ) {

    my $nodes = $plus_minus{$id};

    for my $node ( keys %$nodes ) {

        my $sign  = $nodes->{$node};
        my $nodes = $paths{$id}{path};

        my $i = first_index { $_ eq $node } @$nodes;
        die sprintf "Node $node not found in path ID $id" if $i < 0;

        $nodes->[$i] .= $sign;
    }
}

# Add the reverse paths to the hash:
#     - Change the `order` field to `R` (original is reliably `F`)
#     - Reverse the order of the elements of `path`
#     - Reverse the sign of the elements of `path`
#
my $n = max map { $_->{id} } values %paths;

for my $path ( @paths ) {

    my $nodes = $path->{path};
    my $new_id = ++$n;

    $paths{$new_id} = {
        id    => $new_id,
        order => 'R',
        path  => [
            map {
                s/([+-])/ $1 eq '+' ? '-' : '+' /er or die;
            } reverse @$nodes
        ],
    };
}

# Build the directed graph
#
my $g = Graph::Directed->new;

for my $path ( values %paths ) {
    my $nodes = $path->{path};

    for my $i ( 0 .. $#$nodes - 1 ) {
        $g->add_edge(@{$nodes}[$i, $i+1]);
    }
}

# Report the longest path
#
say join ' : ', $g->longest_path;

输出

C+ : D- : E- : B- : A-