第二列和第三列中的数字指定范围。我想要的是(如果第一列中的数字是相同的)来计算重叠区域,并计算一个范围中获得或丢失的数量,由右边的数字确定(+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 +2
,100 200 +1
和200 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
答案 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