压缩稀疏矩阵


18

使用压缩的稀疏行(CSR,CRS或Yale格式)压缩稀疏矩阵。

这些都是相同的压缩形式(忽略新耶鲁)。

输入可以是任何二维数据结构(列表列表等):例如

[[0 0 0 0],
 [5 8 0 0],
 [0 0 3 0],
 [0 6 0 0]]

和输出应该有三个1D的数据结构(列表等),即表示输出AIAJA,例如

[5, 8, 3, 6]
[0, 0, 2, 3, 4]
[0, 1, 2, 1,]

维基百科描述了该过程:

  • 数组A的长度为NNZ,并按从左到右的顺序从上到下(“行优先”)保存M的所有非零条目。

  • 数组IA的长度为m +1。它由以下递归定义定义:

    • IA [0] = 0 IA [i] = IA [i-1] +(原始矩阵第(i-1)行中非零元素的数量)

    • 因此,IA的前m个元素将索引存储在M的每一行中的第一个非零元素的A中,而最后一个元素IA [m]存储NNZ,即A中的元素数,也可以认为是幻像行的第一个元素的A中的索引刚好在矩阵M的末尾。从元素A [IA [i]]到A [IA [i + 1]-1](两端都包括在内),即从一行的开始到紧挨着下一行的最后一个索引。[5]

    • 第三个数组JA包含A的每个元素的M列索引,因此长度也为NNZ。

如果您的语言不支持实际的数据结构,则输入和输出可能是文本。

测试用例

输入1:

[[0 0 0 0],
 [5 8 0 0],
 [0 0 3 0],
 [0 6 0 0]]

输出1:

[ 5, 8, 3, 6 ]
[ 0, 0, 2, 3, 4 ]
[ 0, 1, 2, 1, ]

输入2

[[10 20 0 0 0 0],
 [0 30 0 40 0 0],
 [0 0 50 60 70 0],
 [0 0 0 0 0 80]]

输出2:

[ 10 20 30 40 50 60 70 80 ]
[  0  2  4  7  8 ]
[  0  1  1  3  2  3  4  5 ]

输入3:

[[0 0 0],
 [0 0 0],
 [0 0 0]]

输出3:

[ ]
[ 0 0 0 0 ]
[ ]

输入4:

[[1 1 1],
 [1 1 1],
 [1 1 1]]

输出4:

[ 1 1 1 1 1 1 1 1 1 ]
[ 0 3 6 9 ]
[ 0 1 2 0 1 2 0 1 2 ]

输入5:

[[0 0 0 0],
 [5 -9 0 0],
 [0 0 0.3 0],
 [0 -400 0 0]]

输出5:

[ 5, -9, 0.3, -400 ]
[ 0, 0, 2, 3, 4 ]
[ 0, 1, 2, 1, ]

假设输入可以包含任何实数,则无需考虑数学符号或指数表示形式(例如,绝不会输入5,000作为5e3)。你不会需要处理inf-infNaN或任何其他“伪数字”。您可以输出不同的数字表示形式(如果您选择的话,可以将5,000 输出为5e3)。

得分:

这是一个,最少字节获胜。

排行榜

这是一个堆栈片段,用于按语言生成常规排行榜和获胜者概述。

为确保您的答案显示出来,请使用以下Markdown模板以标题开头。

# Language Name, N bytes

N您提交的文件大小在哪里。如果您提高了分数,则可以将旧分数保留在标题中,方法是将它们打掉。例如:

# Ruby, <s>104</s> <s>101</s> 96 bytes

如果您想在标头中包含多个数字(例如,因为您的分数是两个文件的总和,或者您想单独列出解释器标志罚分),请确保实际分数是标头中的最后一个数字:

# Perl, 43 + 2 (-p flag) = 45 bytes

您还可以将语言名称设置为链接,然后该链接将显示在页首横幅代码段中:

# [><>](http://esolangs.org/wiki/Fish), 121 bytes


从1开始的索引可以用于最后一行吗?
狮子座

@Leo代表JA?号
Pureferret

1
不是IA[0] = 0完全没有必要吗?只需定义即可IA[i] = IA[i − 1]...,但是我们可以简单地声明是否i-1 < 0使用0。也就是说,IA [0] 始终等于0,因此可以将其压缩掉(是的,我意识到这是对算法的一种批评,不是这个挑战)。
Draco18s

我们也会遇到逆向挑战吗?
亚当

1
整齐!以前没有遇到过任何一种格式,但是我很高兴看到其他人以前也看到过这种格式(我不应该是那种在老算法中发现微不足道的优化的人)。
Draco18s

Answers:


6

MATL,19字节

!3#f!Dx0Gg!XsYshDq!

输入;用作行分隔符。

在线尝试!或验证所有测试情况:12345

说明

!     % Implicit input. Transpose
3#f   % 3-output version of find: it takes all nonzero values and pushes
      % their column indices, row indices, and values, as column vectors
!     % Transpose into a row vector
D     % Display (and pop) vector of values
x     % Delete vector of row values
0     % Push 0
G     % Push input
g     % Convert to logical: nonzeros become 1
!     % Transpose
Xs    % Sum of columns. Gives a row vector
Ys    % Cumulative sum
h     % Prepend the 0 that's below on the stack
D     % Display (and pop) that vector
q     % Subtract 1 from the vector of row indices
!     % Transpose into a row vector. Implicitly display


3

Haskell,87个字节

f s|a<-filter(/=0)<$>s=(id=<<a,scanl(+)0$length<$>a,s>>= \t->[i|(i,e)<-zip[0..]t,e/=0])

在线尝试!

怎么运行的:

a<-filter(/=0)<$>s           -- let a be the list of lists with all 0 removed]
                             -- e.g. [[1,0,0],[0,3,4]] -> [[1],[3,4]]

                             -- return a triple of

id=<<a                       -- a concatenated into a single list -> A 

scanl(+)0$length<$>a         -- partial sums of the length of the sublists of a
                             -- strating with an additional 0 -> IA

s>>=                         -- map the lambda over the sublists of s and concatenate
                             -- into a single list
   \t->[i|(i,e)<-zip[0..]t,e/=0]  -- the indices of the non-zero elements -> JA


2

APL(Dyalog)31个 28个字符或36 33个字节*

需要⎕IO←0从零开始的索引。I / O是列表的列表。

{(∊d)(0,+\≢¨d←⍵~¨0)(∊⍸¨⍵≠0)}

在线尝试!

{} 匿名函数,其中的参数由represented表示

(... ... )(... ... )(... ... ) 返回的三件事情的清单:

  ⍵≠0 布尔其中从0参数不同
  ⍸¨ɩ那些对于每个子列表的ndices
  ε NLIST(扁平化)结合成单个列表

  ⍵~¨0 从参数的每个子列表中删除零
  d← 商店,作为d
  ≢¨  帐簿各
  +\ 累计总和
  0, 前面加上一个零

  ∊dϵ nlist(展平)d合并为一个列表

  


*要在Dyalog Classic中运行,只需替换⎕U2378


很好,我不明白输入格式吗?f 4 4⍴然后是值?
Pureferret

@Pureferret代码定义了函数f。该输入是一个真正的REPL,它调用f上的结果4 4⍴…,其ř eshapes数据到一个4×4矩阵。
亚当

1
卢为[R eshapes。我知道了!
Pureferret

1
@Pureferret我已经更新了在线试用!链接以更好地显示测试案例。
阿达姆(Adám)

2

PHP,107字节

<?for($y=[$c=0];$r=$_GET[+$l++];)foreach($r as$k=>$v)!$v?:[$x[]=$v,$z[]=$k,$y[$l]=++$c];var_dump($x,$y,$z);

在线尝试!

PHP,109字节

<?$y=[$c=0];foreach($_GET as$r){foreach($r as$k=>$v)if($v){$x[]=$v;$z[]=$k;$c++;}$y[]=$c;}var_dump($x,$y,$z);

在线尝试!


这是否需要数字为字符串?
Pureferret

1
@Pureferret PHP中的任何输入都是字符串或字符串数​​组。所以如果你想输出是纯粹的INT代替我还没有铸造输入$x[]=$v$x[]=+$v
约尔格Hülsermann

2

JavaScript(ES6),117个字节

a=>[a.map((b,i)=>(b=b.filter((x,c)=>x&&o.push(c)),m[i+1]=m[i]+b.length,b),m=[0],o=[]).reduce((x,y)=>x.concat(y)),m,o]

输入是2D数字数组,输出是的数组[A, IA, JA]

讲解

a=>[
    a.map((b,i) => (                                // map each matrix row
            b = b.filter((x,c) => x                 // filter to only non-zero elements
                && o.push(c)                        // and add this index to JA
            )
            m[i+1] = m[i] + b.length,               // set next value of IA
            b                                       // and return filtered row
        ),
        m=[0],o=[]                          // initialize IA (m) and JA (o)
    ).reduce((x,y) => x.concat(y)),                 // flatten the non-zero matrix
m,o]                                                // append IA and JA

测验


1

Python 2,115个字节

lambda m:zip(*[[v,i]for k in m for i,v in enumerate(k)if v])+[reduce(lambda a,b:a+[len(b)-b.count(0)+a[-1]],m,[0])]

在线尝试!

输出是 [A, JA, IA]


1

Perl 6,84个字节

{.flatmap(*.grep(+*)),(0,|[\+] .map(+*.grep(+*))),.flat.kv.flatmap:{$^a%.[0]xx?$^b}}

在线尝试!

单个矩阵参数在中$_

  • .flatmap(*.grep(+*)) 选择整个矩阵的非零元素。
  • [\+] .map(+*.grep(+*))是每行中元素数量的三角形减少(某些语言称为scan)。 (0,|...)在该列表前加上零。
  • .flat.kv产生矩阵所有元素的索引列表。 .flatmap: { $^a % .[0] xx ?$^b }由数组.[0]本身的列数(数组中的列数,即第一行中的元素数)对每个索引的模数进行平面映射,由元素本身复制,解释为布尔值。即,非零元素被复制一次,零元素被复制零次(即,被删除)。

1

Python + SciPy,79个字节

我想不是内置的禁止

from scipy.sparse import*
A=csr_matrix(input())
print A.data,A.indptr,A.indices

接受格式的输入 [[0, 0, 0, 0],[5, 8, 0, 0],[0, 0, 3, 0],[0, 6, 0, 0]]


1

Japt31 27字节

将输入作为数组数组并返回数组数组。

[Uc f U®£X©NpYÃZèÃå+ iT NÅ]

测试它-Q仅用于可视化的标志)


说明

数组的隐式输入U
[[1,1,1],[1,1,1],[1,1,1]]

Uc f

对于第一个sub = -array,我们将其展平(cU,然后对其进行过滤(f),删除所有虚假元素(即0s)
[1,1,1,1,1,1,1,1,1]

U®         Ã

通过映射,我们将同时构建其他2个子数组U

£     Ã

我们映射到每个元素(子数组) U

X是当前子数组的当前元素,并且©是逻辑AND(&&),因此,如果X不正确(不为零),则不会执行下一部分。

NpY

在Japt中,N是一个包含所有输入的数组,因此在这里,如果X是真的,我们将(pY当前元素的索引()推到N
[[[1,1,1],[1,1,1],[1,1,1]],0,1,2,0,1,2,0,1,2]

返回主数组的映射,对于每个元素(Z),我们获得该子数组中真实的元素计数(不为零)。
[3,3,3]

å+

通过求和来累计减少此数组。
[3,6,9]

iT

i在索引0处插入()0以完成第二个子数组。
[0,3,6,9]

对于最终的子数组,我们N仅从第一个元素中切片。
[0,1,2,0,1,2,0,1,2]


不过,我只是运行了其他示例,它就起作用了
Pureferret
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.