スパース行列を圧縮する


18

圧縮されたスパース行(CSR、CRSまたはYale形式)を使用してスパース行列を圧縮します

これらはすべて同じ圧縮形式です(新しいエールを無視します)。

入力は、任意の2Dデータ構造(リストのリストなど)である場合があります:例

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

出力は出力を示し、3つの1Dデータ構造(リストなど)でなければならないAIAそしてJA例えば、

[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]は、Aの要素数NNZを格納します。行列Mの最後を超えたファントム行の最初の要素のAのインデックス。元の行列のi番目の行の値は、要素A [IA [i]]からA [IA [i + 1] − 1](両端を含む)、つまり、ある行の開始から次の開始の直前の最後のインデックスまで。[5]

    • 3番目の配列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として出力される場合があります)。

得点:

これは、最少バイトが勝ちます。

リーダーボード

これは、通常のリーダーボードと言語ごとの勝者の概要の両方を生成するスタックスニペットです。

回答が表示されるようにするには、次のマークダウンテンプレートを使用して、見出しから回答を開始してください。

# Language Name, N bytes

N提出物のサイズはどこですか。スコアを改善する場合、古いスコアを打つことで見出しに残すことができます。例えば:

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

ヘッダーに複数の数字を含める場合(たとえば、スコアが2つのファイルの合計であるか、インタープリターフラグペナルティーを個別にリストする場合)、実際のスコアがヘッダーの最後の数字であることを確認します。

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

言語名をリンクにして、リーダーボードスニペットに表示することもできます。

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


最後の行に1から始まるインデックスを使用できますか?
レオ

@Leo for JA?いいえ
Pureferret

1
IA[0] = 0完全に不要ではありませんか?定義するだけで十分ですが、0を使用するIA[i] = IA[i − 1]...場合は単純に指定できます。i-1 < 0つまり、IA [0]は常に 0に等しいため、圧縮することができます(はい、これはアルゴリズムの批評であることがわかります。この挑戦ではありません)。
Draco18s

逆の挑戦もありますか?
アダム

1
きちんとした!以前はどちらの形式にも遭遇しませんでしたが、他の誰かが以前にそれを見ていたのを見てうれしいです(私はこの古いアルゴリズムの些細な最適化を見つけるような人であってはなりません)。
Draco18s

回答:


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)}

オンラインでお試しください!

{... } 引数が表され匿名関数

(……… )(次 の3つのリストを返します)()

  ⍵≠0 引数が0と異なるブールɩ各サブリストの引数の
  ⍸¨ndices
  ϵ nlist(平坦化)を組み合わせて単一のリストにする

  ⍵~¨0 引数
  d← ストアの各サブリストからゼロを削除し、dとして
  ≢¨ 各
  +\ 累積合計
  0, がゼロの前に追加されます

  ∊dϵ nlist(フラット化)dを組み合わせて単一のリストに

  


* Dyalogクラシックで実行するには、単純に置き換える⎕U2378


いいですね、私は入力フォーマットを理解していませんか?f 4 4⍴そして、値?
-Pureferret

@Pureferretコードは関数を定義しますf。入力は、実際コールREPL、あるf結果に4 4⍴…どのrが 4×4の行列にデータをeshapes。
アダム

1
以下のためのRho のR eshapes。わかった!
-Pureferret

1
@Pureferret試用版をオンラインで更新しましたテストケースをより適切に表示するためのリンク。
アダム

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

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回複製され、ゼロ要素は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視覚化の目的でのみフラグを立てる)


説明

arrayの暗黙的な入力U
[[1,1,1],[1,1,1],[1,1,1]]

Uc f

最初のsub = -arrayについては、平坦化(cUしてからフィルター(f)し、偽の要素(つまり0)を削除します
[1,1,1,1,1,1,1,1,1]

U®         Ã

をマッピングすることにより、他の2つのサブ配列を同時に構築しUます。

£     Ã

各要素(サブ配列)をマップします U

Xは、現在のサブ配列の現在の要素であり、©論理AND(&&)であるため、X真でない(ゼロではない)場合、次の部分は実行されません。

NpY

Japtでは、Nすべての入力を含む配列であるため、ここで、もしX真実であれば、現在の要素のpインデックス(Y)を(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を挿入して、2番目のサブ配列を完成させます。
[0,3,6,9]

最後のサブアレイについてはN、最初の要素から単純にスライスします。
[0,1,2,0,1,2,0,1,2]


私は他の例を実行しましたが、動作します
-Pureferret
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.