まず、個々の点(各点の始点と終点)それらをリストに保管してください。あなたの場合は:
1,180,193,329,407,651,684,720.
このリストの各間隔について、それが重なるセグメントの数を調べます。あなたの場合、これは:
1, 180 -> 1
180, 193 -> 2
193, 329 -> 1
329, 407 -> 2
407, 651 -> 1
651, 684 -> 2
684, 720 -> 1
であり、どのセグメントが1より大きいか(この場合は3)ループするでしょう。したがって、ケースの合計数は2 x 2 x 2 = 8個の解です(ソリューション内で複数の区間を処理するセグメントは1つしか選択できません)。
,2,2,2(または2,3,4)が見つかりました。それらを配列にして、最後から始める。 0になるまで値を減らします。1に達すると前の値を減算し、最初の数値から1を引いた値を設定します。
最初のセグメントに番号を付けました(この場合は1,2,3,4,5,6
)。オーバーラップするセグメントには、次のセグメントが含まれます。[1,2], [2,3], [3,4]
したがって、3つのオーバーラップするセグメントがあります。ここで、選択/除外の再帰的プロセスを開始します。 各ステップで、複数のセグメントを持つ重複セグメントを見ています。私たちは選択肢を繰り返し、選択肢ごとに2つのことを行います。今度は選択しなかったセグメントを後続の重複セグメントから除外し、この選択肢を持つ可能性のある後続の重複セグメントごとに現在のセグメント選択を強制します。オーバーラップしないセグメントはすべて新しい選択肢として扱われます。次の複数選択肢と再帰を検索します。我々が選択肢を見つけることができなくなると、我々は部分的な解決策を持っている。重複していないセグメントを追加する必要があります。それを印刷します。これが正常に動作するはず
we are here [1,2], [2,3], [3,4]:
chose 1 -> // eliminate 2 from rest and force 1 (3 is a single choice so we do the same)
[1], [3], [3] -> [1, 3] solution
chose 2 -> // eliminate 1 from the rest and force 2 (2 single choice so we do the same).
[2], [2], [4] -> [2, 4] solution
:第1工程:
この場合、それは次のように行くだろう。
今(それは私が前提と周りのきれいなPerlコードではありませんが、私は実際にperlの男ではないよ)これを実装するコード:
#!/bin/perl
use strict;
use warnings;
use 5.010;
use Data::Dumper;
my $locs = {
loc_1 => {
start => 1,
end => 193,
},
loc_2 => {
start => 180,
end => 407,
},
loc_3 => {
start => 329,
end => 684,
},
loc_4 => {
start => 651,
end => 720,
}
};
my (%starts, %ends);
map {
my ($start, $end) = ($locs->{$_}->{start}, $locs->{$_}->{end});
push @{ $starts{$start} }, $_;
push @{ $ends{$end} }, $_;
} keys %$locs;
my @overlaps, my %tmp;
map {
map { $tmp{$_} = 1 } @{$starts{$_}};
map { delete $tmp{$_} } @{$ends{$_}};
my @segs = keys %tmp;
push @overlaps, \@segs if 1 < @segs
} sort (keys %starts, keys %ends);
sub parse_non_overlapping {
my ($array,$pos)=($_[0], $_[1]);
my @node = @{$array->[$pos]};
foreach my $value (@node) {
my @work = map { [@$_] } @$array;
$work[$pos] = [ $value ];
my ($removed, $forced) = ({}, {$value => 1});
map { $removed->{$_} = 1 if $_ ne $value } @node;
my ($i, $new_pos) = (0, -1);
for ($i = $pos + 1; $i <= $#work; $i++) {
$_ = $work[$i];
#apply map
@$_ = grep { not defined($removed->{$_}) } @$_;
if ($#$_ == 0) { $forced->{@$_[0]} = 1 }
#apply force
my @tmp = grep { defined $forced->{$_} } @$_;
if ($#tmp == 0) {
map { $removed->{$_} = 1 if $tmp[0] ne $_ } @$_;
@$_ = @tmp;
}
if ($#$_ > 0 && $new_pos == -1) {
$new_pos = $i;
}
$work[$i] = $_;
}
if ($new_pos != -1) {
parse_non_overlapping(\@work, $new_pos);
} else {
print Dumper \@work
# @work has the partial solution minux completely non overlapping segments.
}
}
}
parse_non_overlapping(\@overlaps, 0);
良い出力は '([qw(loc_1 loc_3)]、[qw(loc_1 loc_4)]、[qw(loc_2 loc_4)])'でしょうか? – Dancrumb
ええ、それは間違いなく簡潔です。私が必要とするデータにアクセスすることがそれ以上難しくないと思います。良い提案。 –
あなたの例では、重複しない領域のペアのみが許可されますが、重複しない領域の任意の大きなセットを可能な出力として探していますか? – Dancrumb