再帰的な2x2行列式


17

2行2列の行列式

a b
c d

によって与えられad - bcます。

次元2 n x 2 n、n≥1 の数字の行列が与えられた場合、単一の数に達するまで各2 x 2サブブロックの行列式を再帰的に計算することにより得られた結果を出力します。

例えば、与えられた入力

3 1 4 1
5 9 2 6
5 3 5 8
9 7 9 3

1つのステップの後、以下を取得します。

(3*9 - 1*5)    (4*6 - 1*2)    =    22  22
(5*7 - 3*9)    (5*3 - 8*9)         8  -57

そして、もう一度繰り返すと、次のようになります。

(22*-57 - 22*8) = -1430

したがって、出力はになります-1430

ルール

  • 行列の要素は常に1桁の整数、つまり0〜9です。
  • データの前処理が行われない限り、任意の便利なリストまたは文字列形式で入力を取得できます。マトリックスは常に正方形なので、必要に応じて、2Dリストではなく単一の1Dリストとして入力を受け取ることができます。
  • 入力は、関数入力、STDIN、コマンドライン引数、または最も近い代替を介して行うことができます。
  • 出力は、出力を機能させるための単一の整数、STDOUTまたは最も近い代替である必要があります。リストまたは行列に単一の整数を出力することはできません。
  • あなたの言語がたまたまそれらをサポートしている場合、組み込みの行列式と行列操作メソッドを使用できます。
  • アルゴリズムは、有効な入力に対して理論的に機能する必要があります。
  • 標準の規則が適用されます。

テストケース

次のテストケースは、Pythonスタイルのリストとして提供されます。

[[1,0],[0,1]] -> 1
[[1,9],[8,4]] -> -68
[[0,1,2,3],[4,5,6,7],[8,9,0,1],[2,3,4,5]] -> 40
[[3,1,4,1],[5,9,2,6],[5,3,5,8],[9,7,9,3]] -> -1430
[[9,0,0,9],[0,9,9,0],[9,0,9,0],[0,9,0,9]] -> 13122
[[1,0,0,0,0,0,0,0],[2,1,0,0,0,0,0,0],[3,2,1,0,0,0,0,0],[4,3,2,1,0,0,0,0],[5,4,3,2,1,0,0,0],[6,5,4,3,2,1,0,0],[7,6,5,4,3,2,1,0],[8,7,6,5,4,3,2,1]] -> 1
[[7,1,0,5,8,0,1,5],[9,9,6,6,1,2,4,8],[4,8,7,3,8,7,4,7],[4,6,1,9,7,0,1,7],[7,6,7,1,9,4,1,6],[8,0,0,8,5,5,9,9],[4,6,4,8,9,4,8,6],[9,0,8,7,6,2,1,5]] -> 2937504
[[1,2,3,4,5,6,7,8],[2,3,4,5,6,7,8,1],[3,4,5,6,7,8,1,2],[4,5,6,7,8,1,2,3],[5,6,7,8,1,2,3,4],[6,7,8,1,2,3,4,5],[7,8,1,2,3,4,5,6],[8,1,2,3,4,5,6,7]] -> -10549504
[[1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,0],[0,1,1,1,1,0,0,1,0,1,1,1,1,1,1,0],[1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,0],[0,1,1,1,1,0,0,0,0,1,1,1,1,1,0,1],[1,0,1,0,1,1,1,0,0,1,1,1,1,0,1,0],[0,0,1,1,1,0,1,1,1,1,1,1,1,0,0,0],[1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1],[1,1,0,1,1,1,1,1,1,1,1,1,0,1,0,1],[1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1],[0,1,1,1,1,1,1,1,1,0,0,1,0,1,0,1],[1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,0,1,1,0,1,1,1,1,1,0,0,1,1,0],[1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,0,1,0,0,1,0,1,0,1,1,1,1,1,0,1],[1,1,1,1,1,1,1,1,1,0,0,1,1,1,0,1]] -> -8

(この課題の支援について@MartinBüttnerに感謝します)


3
楽しい事実:これについていくつかの実験を行ったところ、驚くほど多数の非ゼロの行列式を持つバイナリマトリックスがあります。サイズが2x2、4x4、8x8、16x16の場合、6、16488、2229617029168687104、3349795881591711813037585032680117995553655026185547430764970842694019448832行列が得られます。これは、37.5%、25.1587%、12.0868%、2.989294%に対応します。
マーティンエンダー

@MartinBüttner:6、22560、10160459763342013440、... A055165に一致します
チャールズ

@チャールズ奇妙、私は私のコードをチェックします
マーティン・エンダー

@MartinBüttner:おそらく2つの異なることを計算しているだけでしょうか?
チャールズ

@Charlesマトリックスを考え[1,0,1,0;1,1,1,1;1,1,1,1;0,0,0,1]ます。2つの同一の行があるため、その完全な行列式はゼロです。したがって、これは特異な(非可逆を意味する)4×4行列であるため、A055165にはカウントされません。ただし、ここで説明する「再帰的」決定要因は1*1-1*0==1です。反対の方向では、マトリックスに[0,0,0,1;1,0,0,0;0,1,0,0;0,0,1,0]は「再帰的な」行列式があり0*0-0*0==0ます。ただし、その行は別の順序の単位行列の行であるため、その完全な行列式はゼロ以外でなければなりません。A055165によってカウントされます。
ジェッペスティグニールセン

回答:


8

J、21 25バイト

0{0{(_2(_2-/ .*\|:)\])^:_

使用法:

   ]input=.(3,1,4,1),(5,9,2,6),(5,3,5,8),:(9,7,9,3)
3 1 4 1
5 9 2 6
5 3 5 8
9 7 9 3
   (0{0{(_2(_2-/ .*\|:)\])^:_) input
_1430

すべてのステップで、マトリックスを2行2列に分割し、それぞれの行列式を計算して、次のステップの入力マトリックスを作成します。結果が変わらなくなるまでこのプロセスを繰り返します(最終要素は決定要素そのものです)。で最終結果をスカラーに変換し0{0{ます。

こちらからオンラインでお試しください。


これを行うためにCutのタイル関数を使用してみましたが、バージョンまではゴルフできませんでした。29バイト:(2 2$2)&(-/ .*;._3^:(2^.#@])) オンラインでお試しください!
ジョナ

4

Mathematica、52 40バイト

12バイトを節約してくれたMartinBüttnerに感謝します。

Tr[#//.l:{_,__}:>BlockMap[Det,l,{2,2}]]&

説明

BlockMap[f,expr,n]exprサイズのサブリストに分割し、すべてのサブリストにnマッピングfします。BlockMap[Det,#,{2,2}]&入力配列を2 * 2ブロックに分割し、それらの行列式を計算します。


テストケース

%[{{3,1,4,1},{5,9,2,6},{5,3,5,8},{9,7,9,3}}]
(* -1430 *)

1
Sp3000でチャレンジのアイデアを議論しながら、Mathematicaでリファレンス実装を作成しました。これは40バイトです。それはあなたのものとかなり似ているので、あなたが好きならあなた自身でそれを見つけるための時間を与えます。:)
マーティンエンダー

@MartinBüttner失敗しました。:(
njpipeorgan

1
あなたは避けることができる[[1,1]]TrしてNestとし//.Tr[#//.l:{_,__}:>BlockMap[Det,l,{2,2}]]&
マーティン・エンダー

@MartinBüttner実際、私は//を思いついた。Jで答えを読むときのアイデアですが、配列に一致する良い方法を見つけることにこだわっています。:P
njpipeorgan

あなたの答えを更新するために、私の解決策を使用して自由に感じる
マーティン・エンダー

3

ゼリー、20 17バイト

s€2s2U×¥/€ḅ-µL¡SS

オンラインでお試しください!または、すべてのテストケースを一度に検証します

使い方

s€2s2U×¥/€ḅ-µL¡SS  Main link. Input: M (matrix)

s€2                Split each row of M into pairs.
   s2              Split the result into pairs of rows.
        /€         Reduce each pair...
       ¥             by applying the following, dyadic chain:
     U                 Reverse each pair of the left argument (1st row).
      ×                Multiply element-wise with the right argument (2nd row).
          ḅ-       Convert each resulting pair from base -1 to integer.
                   This maps [a, b] -> b - a.
            µ      Turn the previous links into a monadic chain. Begin a new one.
             L     Yield the length of the input.
              ¡    Execute the previous chain L times.
                   log2(L) times would do, but who's counting?
               SS  Sum twice to turn the resulting 1x1 matrix into a scalar.

2

Haskell93 86バイト

編集:これを全体で7バイト短縮してくれた@Laikoniに感謝します!

f[[a,b],[c,d]]=a*d-b*c
f m|let l=[take,drop]<*>[div(length m)2]=f[f.($b<$>m)<$>l|b<-l]

=の前にletステートメントを置くことができるとは知りませんでしたが、これらのモナド演算子に慣れたことはありません。再びありがとう@ライコニ

古いバージョン:

f[[a,b],[c,d]]=a*d-b*c
f m=f[[f$a$map b m|a<-l]|b<-l]where h=length m`div`2;l=[take h,drop h]

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

これは、2つの異なる方法で繰り返される関数です。最初に、パターンマッチングが基本ケースである2x2マトリックスをキャッチし、計算を実行します。これを使用して、再帰解を含む生成した2x2行列で関数を呼び出すことにより、再帰的なケースで計算を行います。このマトリックスは、それぞれがリストを半分に分割する関数の配列を2回繰り返すことで生成されます。単純な呼び出しで行に適用し、を使用して列に適用しますmap


代わりにwhere h=length m`div`2;l=[take h,drop h]、を使用できますf m|let l=[take,drop]<*>[length m`div`2]=map b mすることができb<$>m、そして[f$a$b<$>m|a<-l]さらにに短縮することができますf.($b<$>m)<$>l。全体で86バイト:[ tio.run / ...オンラインで試してみてください!]
Laikoni

1

Python、166バイト

def f(m):l=len(m)/2;g=lambda x,y:[(s[:l],s[l:])[x]for s in(m[:l],m[l:])[y]];return f(g(0,0))*f(g(1,1))-f(g(0,1))*f(g(1,0)) if l>1 else m[0][0]*m[1][1]-m[1][0]*m[0][1]

これにより、提供されたすべてのテストケースに合格します。mは(テストケースのように)2D配列でなければなりません。gはサブ行列を選択します。


1

Pyth、26

M-F*VG_HhhumgMCcR2dcG2llQQ

テストスイート

これには2つの部分があります。2×2行列の行列式を計算するM-F*VG_H関数gを再定義します。これにより、2つの行がアンパックされるため、1回しか使用しなくてもバイトが節約されます。

もう1つの部分は、timeと呼ばれる大きなreduceステートメントですlog_2( len( input() ) )。残念ながら、1行1列の行列でリダクションのステップを実行すると、結果がリストにラップされるため、固定小数点を取得できません。reduceは、ほとんどの場合、マトリックスを分割して2 x 2のマトリックスを取得し、適用しgます。


1

MATL、26 30バイト

`tnX^teHHhZC2Ih2#Y)pwp-tnq

入力は、で区切られた行を持つ2D配列;です。つまり、

[3 1 4 1; 5 9 2 6; 5 3 5 8; 9 7 9 3]

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

`             % do...while loop
  tnX^te      %   reshape into square matrix. Implicitly asks for input the first time
  HHhZC       %   transform each 2x2 block into a column
  2Ih2#Y)     %   push matrix with rows 2,3, and also matrix with remaining rows (1,4)
  pwp-        %   multiplications and subtraction to compute the 2x2 determinants
  tnq         %   condition of do...while loop: is number of elements greater than 1?
              % implicitly end loop
              % implicitly display


0

ES6、91バイト

(a,x=0,y=0,w=a.length)=>(w>>=1)?f(a,x,y,w)*f(a,x+w,y+w,w)-f(a,x,y+w,w)*f(a,x+w,y,w):a[x][y]

簡単な再帰的ソリューション。



0

Groovy、221 189バイト(この時点でJavaを使用できた)

f={x->b=x.size();c=b/2-1;a=(0..c).collect{i->(0..c).collect{j->z=x.toList().subList(i*2,i*2+2).collect{it.toList().subList(j*2,j*2+2)};z[0][0]*z[1][1]-z[0][1]*z[1][0];}};a.size()==1?a:f(a)}

Java(221バイト)である可能性のある古いくだらないバージョン:

f={x->b=x.size();a=new int[b/2][b/2];for(i=0;i<b-1;i+=2){for(j=0;j<b-1;j+=2){z=x.toList().subList(i,i+2).collect{it.toList().subList(j,j+2)};a[(int)(i/2)][(int)(j/2)]=z[0][0]*z[1][1]-z[0][1]*z[1][0];}};a.size()==1?a:f(a)}

未ゴルフコード:

f=
{x->
  b=x.size();
  int[][]a=new int[b/2][b/2];
  for(i=0;i<b-1;i+=2) {
    for(j=0;j<b-1;j+=2) {
      z=x.toList().subList(i,i+2).collect{
        it.toList().subList(j,j+2)
      };
      a[(int)(i/2)][(int)(j/2)]=z[0][0]*z[1][1]-z[0][1]*z[1][0];
    }
  }
  a.size()==1
    ?
      a:f(a)
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.