Обычная стратегия хранения разреженных данных - отбрасывать значения, которые вам не нужны (нули), и сохранять индексы строк и столбцов с каждым значением, которое вас волнует, сохраняя, таким образом, их позиционную информацию:
[VALUE, ROW, COLUMN]
В вашем случае вы можете сэкономить еще больше, поскольку все ваши потребности могут быть удовлетворены путем обработки данных столбец за столбцом, что означает, что нам не нужно повторять COLUMN для каждого значения.
use strict;
use warnings;
use Data::Dumper;
my ($r, $c, @dataC, @Ap, @Ai, @Ax, $cumul);
# Read data row by row, storing non-zero values by column.
# $dataC[COLUMN] = [
# [VALUE, ROW],
# [VALUE, ROW],
# etc.
# ]
$r = -1;
while (<DATA>) {
chomp;
$r ++;
$c = -1;
for my $v ( split '\s+', $_ ){
$c ++;
push @{$dataC[$c]}, [$v, $r] if $v;
}
}
# Iterate through the data column by column
# to compute the three result arrays.
$cumul = 0;
@Ap = ($cumul);
$c = -1;
for my $column (@dataC){
$c ++;
$cumul += @$column;
push @Ap, $cumul;
for my $value (@$column){
push @Ax, $value->[0];
push @Ai, $value->[1];
}
}
__DATA__
2 3 0 0 0
3 0 4 0 6
0 -1 -3 2 0
0 0 1 0 0
0 4 2 0 1