質問者が考えられているプログラムには、無理があると思います。
my @list1 = ([1,6],[2,5],[3,4],[5,14],[20,25]);
my @list2 = ([2,3],[5,8],[12,20],[16,28]);
while($i < @list1){
while($n < @list2){
.....
#終点の比較
if($list1[$i]->[1] < $list2[$n]->[1]){
$i++;
}
elsif($list2[$n]->[1] < $list1[$i]->[1]){
$n++;
}
}
}
上のプログラムでは、次のように進みます。
1) 1 - 6 と 2 - 3 を比較する
2) 1 - 6 と 5 - 8 を比較する
3) 2 - 5 と 5 - 8 を比較する
この時点で、list2 の 2 - 3 の比較は終了していて、本来比較しなければならない list1
の 2 - 5 と 3 - 4 とは行われないままになってしまいます。これを行うように while ル
ープに組み込むのは、至難の技のように思います。
次の条件式 (elsif の条件式も含めて) には誤りがあります。1 - 6 と 12 - 20 を比較した
場合を考えてみてください。重複がないのに条件式は真となってしまいます。
#重複か否かの比較
if($list1[$i]->[0] < $list2[$n]->[0] && $list1[$i]->[1] < $list2[$n]->[1] ){
重複の判断は、どちらかの最小値 (または最大値) が他方の範囲内にあることを確認すること
でできます。
if ($list1[$i]->[0] >= $list2[$n]->[0] && $list1[$i]->[0] <= $list2[$n]->[1]
or $list1[$n]->[0] >= $list2[$i]->[0] && $list1[$n]->[0] <= $list2[$i]->[1]) {
もう少し単純なプログラムを考えてはどうでしょうか。次のような foreach の2段重ねる
方法でも十分ではないでしょうか。
my @list1 = ([1,6],[2,5],[3,4],[5,14],[20,25]);
my @list2 = ([2,3],[5,8],[12,20],[16,28]);
my $flag1 = 0;
my $flag2 = 0;
foreach my $list1_ref (@list1) {
foreach my $list2_ref (@list2) {
if ($list1_ref->[0] >= $list2_ref->[0] && $list1_ref->[0] <= $list2_ref->[1]
or $list2_ref->[0] >= $list1_ref->[0] && $list2_ref->[0] <= $list1_ref->[1]) {
$flag1++;
$flag2++;
}
}
}
print "list1 : $flag1\n";
print "list2 : $flag2\n";
お礼
ありがとうございます。 ソースが出来ましたので報告します。 下記は配列からそれぞれの配列データの比較の順番を リストアップしたものを作成します。 その後、リストアップしたファイルを重複判断&フラグ付けする プログラムに入力し、最終的にlist1,list2の重複のあるフラグ数をカウント、出力させます。 my $i = 0; my $s = 0; my @s_index; my @i_index; my @oList1 = ([1,6],[2,5],[3,4],[5,14],[20,25]); my @oList2 = ([2,3],[5,8],[12,20],[16,28]); while(($i < $#oList1 || $s <= $#oList2)&&($i <= $#oList1 || $s < $#oList2)){ my $ra1 = $oList1[$i]->[0]; my $ra2 = $oList1[$i]->[1]; my $ra3 = $oList2[$s]->[0]; my $ra4 = $oList2[$s]->[1]; ### 片方の行が終わって、片方の行が残っている場合、リストの最後の行と残りの行で比較を行う if($i == $#oList1) { if($s <= $#oList1 && $#oList1 <= $#oList2){ $s++; } elsif($s >= $#oList1 && $s <= $#oList2){ $s++; } elsif($s <= $#oList1 && $#oList2 <= $#oList1){ $s++; } else{ exit; } } elsif($s == $#oList2) { 上と同じ処理 } else{ if($ra2 < $ra4) { ### 終点同士を比較して、終点の値が小さい方の行をカウントアップ $i++; } elsif($ra2 > $ra4) { 上と同じ処理 } } }