列からのブロック対角行列


16

Stack Overflowのこの質問からコピーしたものに触発されました

行列が与えられた場合ABの列がAブロック対角形式で配置されるように行列を作成します。たとえば、与えられた

1 2 3
4 5 6

出力は

1 0 0
4 0 0
0 2 0
0 5 0
0 0 3
0 0 6

ルール

入力と出力は、2D配列、ネストされた配列、または行と列の区切り文字が異なる文字列の形式です。

入力(行列A)の数値は正の整数になります。

出力のゼロが何らかの合理的な方法で表示される限り、単項形式が許可されます。たとえば、上記の結果は、引用符を使用して各番号を囲むことで表示できます。

'1' '' ''
'1111' '' ''
'' '11' ''
'' '11111' ''
'' '' '111'
'' '' '111111'

テストケース

入出力:

1 2 3
4 5 6

1 0 0
4 0 0
0 2 0
0 5 0
0 0 3
0 0 6


10 20

10  0
 0 20    


10
20

10
20


  1   2   3
 10  20  30
100 200 300

  1   0   0
 10   0   0
100   0   0
  0   2   0
  0  20   0
  0 200   0
  0   0   3
  0   0  30
  0   0 300

 2  4
 6  8
10 12

 2  0
 6  0
10  0
 0  4
 0  8
 0 12

Aのすべての数値は異なりますか?
アダム

@Nᴮᶻいいえ、等しくすることができます
ルイスメンドー

回答:


7

MATL、6バイト

"@N$Yd

で動作し、現在のバージョン(13.0.0)言語/コンパイラの。

入力の形式は次のとおりです。セミコロンを行の区切り文字として、コンマまたはスペースを各行の列の区切り文字として使用します。

[1, 2, 3; 4, 5, 6]

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

説明

"         % implicitly input 2D array and loop over its columns
  @       %   push column
  N$Yd    %   build block-diagonal matrix from all stack contents. Stack contents are
          %   a single column in the first iteration, or a partially built 2D array
          %   and a new column in all other iterations
          % end loop
          % implicit display

実施例

入力を考慮してください[1 2 3; 4 5 6]。で始まるforループ"は、入力の各列を取ります。各反復内で@、現在の列をスタックにプッシュします。したがって、最初の反復でプッシュし[1; 4]ます。N$すべてのスタックの内容が次の関数の入力として使用されることを指定しますYd

この関数(MATLABのに対応blkdiag)は、その入力を「対角線状に連結」して、ブロック対角行列(2D配列)を生成します。したがって、最初の反復Ydでは1つの入力を受け取り、その入力に等しい出力を生成[1; 4]します。これはスタックに残されます。

2番目の反復では、入力の2番目の列[2; 5]がプッシュされます。ここYdで、2つの2×1入力、つまり[1; 4]とを受け取り[2; 5]、4×2配列を生成し[1 0; 4 0; 0 2; 0 5]ます。

3番目の反復でYdは、後者の4×2配列と入力の3番目の列を取り[3; 6]、最終結果を生成し[1 0 0; 4 0 0; 0 2 0; 0 5 0; 0 0 3; 0 0 6]ます。


3

ES6、65バイト

a=>[].concat(...a[0].map((_,i)=>a.map(b=>b.map((c,j)=>i-j?0:c))))

入力として受け取り、配列の配列を出力として返します。


1
@WashingtonGuedes内部マップは、1つを除くすべての列がゼロにリセットされた元の2D配列のコピーを返します。これらのコピーは、外側の3D配列の要素であるだけでなく、連結する必要があります。
ニール

3

Mathematica、40 39バイト

Infixingの@Seeqの功績Flatten

Transpose[DiagonalMatrix/@#]~Flatten~1&

入力は、{}括弧で区切られた行ベクトルのリストです。したがって、最初の例は

{{1,2,3},{4,5,6}}

アレイを生成DiagonalMatrix各々が入力(3-Dアレイ)の行から対角要素を有する場合です。Transposeそのため、Flatten操作は正しいブラケットペアを削除して、目的のマトリックス(現在は2次元配列)を提供します。


1
動作しませんDiagonalMatrix/@#か?そして、拡張により、Transpose[DiagonalMatrix/@#]~Flatten~1&
seequ

良いキャッチ、私はそれをロールアップした後にそれを修正するつもりでした。Infix Flattenしかし、使用するとは思わなかった。+1。
IPoiler


1

ゼリー、13バイト

ZLR’×L0ẋ;"Zz0

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

使い方

ZLR’×L0ẋ;"Zz0  Main link. Input: M (matrix)

Z              Transpose M.
 L             Get the length of the result. This yields the number of M's columns.
  R            Range; for m columns, yield [1, ..., m].
   ’           Decrement to yield [0, ..., m-1].
    ×L         Multiply each by the length (number of rows) of M.
               This yields [0, n, ..., n(m-1)], where n is the number of rows.
      0ẋ       Push a list of lists of zeroes.
               First element is [], last is n(m-1) zeroes.
        ;"Z    Prepend the kth vector of zeroes to the kth column of M.
           z0  Zip, filling the non-rectangular 2D array with zeroes.

1

Mathematica、111バイト

Join@@@ReplacePart[Table[0,#2/#3]~Table~#3~Table~#3,Table[{n,n}->#[[n]],{n,#3}]]&[Length@#,Length@Flatten@#,#]&

入力構文は何ですか?これはTablePart標準のMMAマトリックス表記を使用するとスローおよびエラーが発生し、結果として混合ディメンションの配列になります。
IPoiler

1

Ruby、81 78 76 62バイト

->a{i=-1;a[0].flat_map{i+=1;a.map{|b|x=b.map{0};x[i]=b[i];x}}}

ため息インデックスを手動で追跡するのは、より短いですwith_index

->a{
i=-1;            # index of the flat_map
a[0]             # duplicate all rows as many times as necessary
.flat_map{       # we're wrapping each "group" of original rows with yet another
                 #  array, so we need to flat_map to get rid of those
i+=1;            # increment the index of the current subarray
a.map{|b|        # for each sub-subarray (these are the rows)...
x=b.map{0};      # zero everything out
x[i]=b[i];       # replace the desired elements
x}}}             # finally, return the modified array

1

R、41バイト

pryr::f(Matrix::.bdiag(plyr::alply(a,2)))

前提としpryrMatrixそしてplyrパッケージがインストールされています。

これにより、2D配列(a)を取り、「sparseMatrix」を返す関数が作成されます(0はとして表されます.)。

(a=matrix(1:6,ncol=3))
#      [,1] [,2] [,3]
# [1,]    1    3    5
# [2,]    2    4    6
pryr::f(Matrix::.bdiag(plyr::alply(a,2)))(a)
# 6 x 3 sparse Matrix of class "dgTMatrix"
#          
# [1,] 1 . .
# [2,] 2 . .
# [3,] . 3 .
# [4,] . 4 .
# [5,] . . 5
# [6,] . . 6

説明:

plyr::alply(a,2)aandの各列は、これらの結果をリストに結合します

Matrix::.bdiag(lst) 行列のリストからブロック対角行列を作成します

pryr::f 関数を作成する簡単な方法です。

R59バイトの完全な基本ソリューション(@PieCotのMatlabの回答のロジックを使用):

function(a){l=dim(a);diag(l[2])%x%matrix(1,nrow=l[1])*c(a)}

1

MATLAB、69 68バイト

   function h=d(a)
   [r,c]=size(a);h=repmat(a,c,1).*kron(eye(c),~~(1:r)')

1バイト削られました:ルイス・メンドーのおかげで:)


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