Özyinelemeli 2x2 determinant


17

2'ye 2 matrisinin belirleyicisi

a b
c d

tarafından verilir ad - bc.

2 n x 2 n , n ≥ 1 boyutlarına sahip bir basamak matrisi verildiğinde , tek bir sayıya ulaşıncaya kadar her bir 2 ile 2 alt bloğun belirleyicisini tekrar tekrar hesaplayarak elde edilen sonucu çıkar.

Örneğin, girdi verildiğinde

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

Bir adımdan sonra şunları elde ederiz:

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

Ve bir kez daha yineleyerek:

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

Bu nedenle, çıktı olmalıdır -1430.

kurallar

  • Matrisin elemanları her zaman tek haneli tamsayılar olacaktır, yani 0 ila 9.
  • Verilerin ön işlemesi yapılmadığı sürece herhangi bir uygun liste veya dize biçiminde girdi alabilirsiniz. Matris her zaman kare olduğundan, isterseniz 2B listesi yerine tek bir 1D listesi olarak giriş alabilirsiniz.
  • Giriş, işlev girişi, STDIN, komut satırı argümanı veya en yakın alternatif aracılığıyla olabilir.
  • Çıktı, fonksiyon çıktısı için tek bir tamsayı, STDOUT veya en yakın alternatif olmalıdır. Bir tamsayı bir liste veya matriste çıkaramazsınız.
  • Diliniz bunları destekliyorsa yerleşik determinant ve matris manipülasyon yöntemlerini kullanabilirsiniz.
  • Geçerli herhangi bir girdi için algoritmanız teoride çalışmalıdır.
  • Standart kuralları geçerlidir.

Test senaryoları

Aşağıdaki test senaryoları Python tarzı listeler olarak verilmiştir:

[[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

(Bu sorunla ilgili yardım için @ MartinBüttner'a teşekkürler)


3
Eğlenceli gerçek: Bu konuda bazı deneyler yaptım ve sıfır olmayan özyinelemeli determinant ile şaşırtıcı derecede çok sayıda ikili matris var. 2x2, 4x4, 8x8, 16x16 boyutları için 6, 16488, 2229617029168687104, 3349795881591711813037585032680117995553655026185547430764970842694019448832 matrisleri sırasıyla sıfır olmayan%,% 12.5,% 12.5,% 12.5%
Martin Ender

@ MartinBüttner: A055165 ile eşleşen 6, 22560, 10160459763342013440 elde ediyorum .
Charles

@Charles garip, kodumu kontrol edeceğim
Martin Ender

@ MartinBüttner: Muhtemelen iki farklı şey hesaplıyor muyuz?
Charles

@Charles Matrisi düşünün [1,0,1,0;1,1,1,1;1,1,1,1;0,0,0,1] . İki belirleyici satırı olduğundan tam belirleyicisi sıfırdır. Bu nedenle bu tekil (tersine çevrilemez anlamına gelir) 4 × 4 matristir, bu nedenle A055165 tarafından sayılmaz. Ancak burada tartışılan "özyinelemeli" determinanttır 1*1-1*0==1. Ters yönde, matris [0,0,0,1;1,0,0,0;0,1,0,0;0,0,1,0]"özyinelemeli" belirleyiciye sahiptir 0*0-0*0==0. Bununla birlikte, tam belirleyicisi sıfır olmamalıdır, çünkü satırları sadece kimlik matrisinin başka bir sıradaki satırlarıdır; ve A055165 ile sayılır.
Jeppe Stig Nielsen

Yanıtlar:


8

J, 21 25 bayt

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

Kullanımı:

   ]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

Her adımda matrisi 2'ye 2'ye keseriz ve bir sonraki adımın giriş matrisiyle sonuçlanan her birini belirleyici olarak hesaplarız. Sonuç değişmeyene kadar bu işlemi tekrarlıyoruz (son eleman belirleyicinin kendisidir). Nihai sonucu ile bir skalere dönüştürürüz 0{0{.

Burada çevrimiçi deneyin.


Bunu yapmak için Cut'un döşeme işlevini kullanarak denedim, ancak sürümünüze kadar golf oynayamadı. 29 bayt: (2 2$2)&(-/ .*;._3^:(2^.#@])) Çevrimiçi deneyin!
Jonah

4

Mathematica, 52 40 bayt

Martin Büttner'e 12 bayt kazandığı için teşekkürler.

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

açıklama

BlockMap[f,expr,n]her alt listede exprboyut nve haritanın alt listelerine bölünür f.BlockMap[Det,#,{2,2}]&giriş dizisini 2 * 2 bloğa bölün ve belirleyicilerini hesaplayın.


Test durumu

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

1
Mathematica'da Sp3000 ve 40 bayt ile ilgili zorluk fikrini tartışırken bir referans uygulaması yazdım. Yine de sizinkine oldukça benzer, bu yüzden isterseniz kendiniz bulmanız için biraz zaman vereceğim. :)
Martin Ender

@ MartinBüttner Başarısız oldum. :(
njpipeorgan

1
Sen önleyebilirsiniz [[1,1]]ile Trve Nestile //.:Tr[#//.l:{_,__}:>BlockMap[Det,l,{2,2}]]&
Martin Ender

@ MartinBüttner Aslında // ile geldim. J yanıtı okurken fikir, ama dizi maç için iyi bir yol bulmak için sıkışmış. : P
njpipeorgan

Cevabınızı güncellemek için çözümümü kullanmaktan çekinmeyin
Martin Ender

3

Jöle, 20 17 bayt

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

Çevrimiçi deneyin! veya tüm test senaryolarını bir kerede doğrulayın .

Nasıl çalışır

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

Haskell , 93 86 bayt

EDIT: @Laikoni bu 7 bayt kısaltmak için teşekkürler!

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]

= 'Den önce bir let ifadesi koyabileceğinizi bilmiyordum ve bu monad operatörlerine hiç alışmadım. Tekrar teşekkürler @Laikoni

Eski versiyon:

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]

Çevrimiçi deneyin!

Bu, kendini iki farklı şekilde tekrarlayan bir işlevdir. İlk olarak desen eşleşmesi temel durumu yakalar: 2x2 bir matris ve hesaplamayı yapar. Ben özyinelemeli durumda özyinelemeli çözümler içeren 2x2 matris ile fonksiyonu çağırarak hesaplama yapmak için bunu kullanın. Bu matris, her biri bir listeyi yarıya bölen bir işlev dizisi üzerinde iki kez yinelenerek oluşturulur. Basit bir çağrı ile satırlara uygular ve kullanarak sütunlara uygularım map.


Bunun yerine where h=length m`div`2;l=[take h,drop h]kullanabilirsiniz f m|let l=[take,drop]<*>[length m`div`2]=. map b molabilir b<$>mve [f$a$b<$>m|a<-l]daha da kısaltılabilir f.($b<$>m)<$>l. Tamamen 86 bayt: [ tio.run/… Çevrimiçi deneyin!]
Laikoni

1

Python, 166 bayt

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]

Bu, sağlanan tüm test senaryolarını geçer. m bir 2D dizi olmalıdır (test durumlarında olduğu gibi), g alt matrisi seçer.


1

Pyth, 26

M-F*VG_HhhumgMCcR2dcG2llQQ

Test odası

Bunun iki bölümü vardır: M-F*VG_Hişlevi yeniden tanımlarg ikiye iki matrisin determinantını hesaplama . Bu, iki satırı açtığı için yalnızca bir kez kullanmamıza rağmen bayt tasarrufu sağlar.

Diğer kısım, zaman dediğimiz büyük bir azaltma ifadesidir log_2( len( input() ) ). Ne yazık ki, bire bir matris üzerinde azaltmada bir adım yapmak sonucun bir listeye sarılmasına neden olur, bu yüzden sabit bir nokta elde edemeyiz. Azaltma çoğunlukla 2'ye 2 matris elde etmek için matrisi bölerek uygular g.


1

MATL , 26 30 bayt

`tnX^teHHhZC2Ih2#Y)pwp-tnq

Giriş, satırlarla ayrılmış ;, yani,

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

Çevrimiçi deneyin!

`             % 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

1

Perl 5 , 120 + 1 ( -a) = 121 bayt

while($#F){@r=();for$i(@o=0..($l=sqrt@F)/2-1){push@r,$F[$k=$i*$l*2+2*$_]*$F[$k+$l+1]-$F[$k+$l]*$F[$k+1]for@o}@F=@r}say@F

Çevrimiçi deneyin!

Girdiyi boşlukla ayrılmış numaraların listesi olarak alır.


0

ES6, 91 bayt

(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]

Basit özyinelemeli çözüm.


0

R , 111 bayt

f=function(m)"if"((n=nrow(m))-2,f(matrix(c(f(m[x<-1:(n/2),x]),f(m[y<-x+n/2,x]),f(m[x,y]),f(m[y,y])),2)),det(m))

Çevrimiçi deneyin!

Girişi bir R matrisi olarak alır (başlıktaki fonksiyon tarafından dönüştürülür).


0

Groovy, 221 189 bayt (Bu noktada Java'yı kullanabilirdim)

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 bayt) olabileceği gibi eski crappy sürümü:

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

Kod çözülmemiş kod:

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)
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.