计算重叠数区域的收益和损失

时间:2017-01-22 22:08:53

标签: bash perl sorting add

第二列和第三列中的数字指定范围。我想要的是(如果第一列中的数字是相同的)来计算重叠区域,并计算一个范围中获得或丢失的数量,由右边的数字确定(+1 =一个获得,-1 =一个人输了)。 例如,如果我有

1   0   100   +2
1   100 200   +1
1   200 300   +2
2   100 200   -1

这意味着我实际上有

1   100 200

因为1 0 300与创建0 100 +2100 200 +1200 300 +2的{​​{1}}重叠,但2 100 200没有重叠,只打印出{{1} }}

示例输入

2   100 200   -1

预期结果

1   0   5000    +1
1   100 400 -1
1   300 500 +2
1   1000    1200    +3
1   1000    1100    -2
1   0   50  -1

如何实现这一目标的某种伪代码将是不错的

但对我有用的语言是bash,perl,awk或sed

2 个答案:

答案 0 :(得分:2)

对于第一列的每个不同值,创建一个列表,列出其划分的范围的所有起点和终点。

对这些点进行排序

对于每行数据,将delta值添加到限制之间的所有范围

(如果它们相邻并且最终具有相同的值,则可以组合多个范围)

打印结果

答案 1 :(得分:1)

将数据存储在哈希表中。最顶层的密钥是id(1 st 列)。第二级密钥是“中断”,即增益改变的区域的边界。值是增益变化的程度。

打印输出时,只需保持运行增益并将存储值添加到其中;如果结果不为零则打印。请注意,输出与您预期的输出不同,但在尝试通过笔和纸解决问题时,我也得到了它。

#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

my %table;

while (<>) {
    my ($id, $from, $to, $gain) = split;
    $table{$id}{$from} += $gain;
    $table{$id}{$to} -= $gain;
}

for my $id (sort { $a <=> $b } keys %table) {
    my $previous;
    my $gain = 0;
    for my $break (sort { $a <=> $b } keys %{ $table{$id} }) {
        if (defined $previous) {
            $gain += $table{$id}{$previous};
            say join "\t", $id, $previous, $break, $gain
                if $gain;
        }
        $previous = $break;
    }
}

输出:

1       50      100     1
1       300     400     2
1       400     500     3
1       500     1000    1
1       1000    1100    2
1       1100    1200    4
1       1200    5000    1