Genelleştirilmiş matris izi


23

İlham.

Verilen (herhangi bir şekilde):

  • İki argüman (veya iki elemanlı listeden oluşan tek argüman) kara kutu işlevi , (giriş ve çıkış 1, 2, 3,…)f: ℤ+ × ℤ+ → ℤ+
  • En az iki satır ve iki sütun içeren kesinlikle pozitif bir tam sayı matrisi

matrisin işlev izini döndür .

Bir nedir fonksiyon iz ?

Normal bir matris izi, bir matrisin ana köşegeninin (sol üstten sağ alt) toplamıdır:

[[1,2,3],[4,5,6],[7,8,9]][1,5,9]1+5+915

Ancak toplama yerine f, köşegen boyunca uygulamak istiyoruz :

[[1,2,3],[4,5,6],[7,8,9]][1,5,9]f(f(1,5),9)veyaf(1,f(5,9))

Lütfen soldan sağa mı yoksa sağdan sola mı kullandığınızı belirtin.

Verilen matris ve tüm ara değerler, dilinizin tamsayı alanı içinde kesinlikle pozitif tam sayılar olacaktır. Matris kare olmayabilir.

Örnekler

f(x,y) = xy, [[1,2,3],[4,5,6],[7,8,9]]1×5×945

f(x,y) = xy, [[1,2,3],[4,5,6],[7,8,9]]→ →1591

f(x,y) = x-y, [[4,5,6],[1,2,3]]4-22

f(x,y) = (x+y)⁄2, [[2,3,4],[5,6,7],[8,9,10]]5veya7

f(x,y) = x+2y, [[1,2,3],[4,5,6],[7,8,9]]47veya29

f(x,y) = max(x,y), [[1,2,3],[4,5,6],[7,8,9]]max(1,5,9)9

f(x,y) = 2x, [[1,2,3],[4,5,6],[7,8,9]]2veya4

f(x,y) = lcm(x,y), [[2,2,2],[2,2,3],[2,3,3],[4,4,4]]lcm(2,2,3)6

Referans uygulaması.


Diyagonal nedir [[2,2,2],[2,2,3],[2,3,3],[4,4,4]]?
Tamamen insan

3
@totallyhuman:[2,2,3]
Emigna

1
Kahretsin, başlığı "Generalized Matrix trance" olarak okudum ve sayfa yüklendiğinde çok hayal kırıklığına uğradım
tar

Yanıtlar:


9

R , 40 30 bayt

function(m,F)Reduce(F,diag(m))

Çevrimiçi deneyin!

Test durumlarını doğrulayın.

Köşegen aşağıya iner, bu durumda sola-sağa. Aritmetik operatörler için, "+"operatörleri ( +,*,-,%/%,^,%%) etrafında tekrar kullanabilir veya

Oldukça basit: ReduceR, eşdeğer bir olduğunu foldve bir matrisin köşegen bu unsurlar a_ijburada i==j, diğer bir deyişle rowve colindeksler UMN aynıdır. diagkare olmayan matrisler için uygun davranışa sahiptir.


8

Haskell , 39 bayt

Daha önce geçersiz olan çözümü düzeltmeme yardım ettiğiniz için teşekkürler @Likonik!

f!m=foldl1 f[h|h:_<-zipWith drop[0..]m]

Sola ortak, çevrimiçi deneyin! (yerine foldl1göre foldr1sağ birleştirici için)


nasıl foldl1 f$zipWith(!!)m[0..]?
Gurme haskeller

@proudhaskeller: Başkalarının daha önce denediği, fakat kare olmayan matrislerde başarısız olan ..
ბიმო

5

Mathematica , 16 bayt

Martin Ender sayesinde -1 bayt.

#~Tr~Fold[g]@*0&

Çevrimiçi deneyin!

Alternatif çözüm, 17 bayt

Fold[g]@*Diagonal

Çevrimiçi deneyin!


17 bayt (kara kutu işlevleri belirli bir ad altında kabul edilebilir)
Bay Xcoder

Bu @*{}sözdizimi çok fazla anlam ifade etmiyor (muhtemelen demek istedin @*List), ama yine de işe yaraması çok iyi. Aslında, {}ile değiştirin 0ve bir bayt kaydedebilirsiniz.
Martin Ender

@MartinEnder Ben aslında Listilk yaptım ama {}sadece halt için denedim ve çalıştı çok şaşırdım. Mantıklı ama nasıl 0çalışıyor? o0
totallyhuman

1
@totallyhuman Aynı şekilde {}. Şu anda {}bir işlev olarak kullanıyorsunuz (veya aslında Mathematica terminolojisini kullanarak). Eğer forada bir jenerik kullanıyorsanız , f[1,2,3](köşegen buysa) alırsınız . Ama {}seninle olsun {}[1,2,3]. Bu tamamen anlamsız bir ifadedir, ancak kafalar keyfi ifadeler olabilir ve Mathematica onlarla ne yapacağını bilemezse, onları olduğu gibi bırakır. Mathematica'nın liste manipülasyon fonksiyonlarının çoğu aslında keyfi bir kafaya sahip ifadelerle çalışır ve bu durumda Foldkafa henüz göz ardı edilir. [tbc]
Martin Ender

Yani 0bunun yerine baş olarak kullanabilirsiniz , ki 0[1,2,3]hangisi hala anlamsızdır, fakat aynı şekilde çalışır.
Martin Ender

4

Octave , 61 57 53 bayt

function m=g(f,m)for i=diag(m)'(2:end)m=f(m(1),i);end

Çevrimiçi deneyin!

gBir işlev tanıtıcısı fve matrisi alan bir işlevi tanımlar m. İlk yinelemede, m(1)sol üst matris öğesini döndürür; Ondan sonra, sadece döner m.



@Giuseppe İlk 61 bayt versiyonum ile yaptığım şey bu. Tabii ki, 57 ve 61 baytlık sürümümün güçlü noktalarını birleştirmeliydim ki bu aslında 53 baytlık bir cevap veriyor. Bana tekrar bakmamı sağladığın için teşekkürler!
18'de Sanchises

3

Temiz , 56 bayt

t[[h:_]]f=h
t[[h]:_]f=h
t[[h:_]:r]f=f h(t[t\\[_:t]<-r]f)

Çevrimiçi deneyin! Sağdan sola kıvrılır.

[t\\[_:t]<-r]aynıdır map tl r, ancak buna gerek yoktur import StdEnv.


Çok şık bir şekilde kaçınmasıStdEnv
Janurous

3

Haskell , 47 45 42 bayt

f%((h:t):r)|[]<-t*>r=h|x<-tail<$>r=f h$f%x

Çevrimiçi deneyin! (%)Bir fonksiyon ve bir matrisi alan bir fonksiyonu liste olarak girdi listesi olarak tanımlar .

Fonksiyon sağdan sola doğru kıvrılır:

f % [[1,2,3], -> f 1 ( f % [[5,6],   -> f 1 ( f 5 ( f % [[9]] ) ) -> f 1 ( f 5 ( f 9 ) ) )
     [4,5,6],               [8,9]] )
     [7,8,9]]

f % ((h:t):r)              -- (h:t) is the first row and r the remaining rows
 | [] <- t *> r = h         -- a shorter way of checking wether t==[] or r==[]
 | x<-tail<$>r = f h $ f%x -- apply f to h and the result of recursively calling (%) on
                           -- the remaining matrix with the first column removed

Düzenleme: BMO sayesinde -2 bayt ve Zgarb sayesinde -3 bayt !


1
Koşullarını kullanarak $ve sadeleştirerek 43 bayt*> .
Zgarb

@ Zgarb Kullanmak için güzel bir fikir *>!
Laikoni

3

APL (Dyalog Unicode) , 7 bayt ( Adám's SBCS )

⎕/1 1⍉⎕

Çevrimiçi deneyin!

-3 Bunu, tam programa dönüştürmek için bir öneri bunu Adám .

Sağdan sola.


Adám'ın SBCS'sini burada kullanmanıza gerek yok: sadece Dyalog Classic'i kullanabilirsiniz.
Zacharý

@ Zacharý Mesele şu ki, Dyalog Unicode’da cevap veriyorum, Klasik zaman içinde itiraz ediliyor.
Outgolfer Erik,

Kod sayfası değil, kod sayfası devam edecek
Zacharý

@ Zacharý Peki, haydi tutarlı olalım. : P
Outgolfer Erik,



2

Python 2,61 bayt

lambda f,m:reduce(f,[l[i]for i,l in enumerate(m)if len(l)>i])

Çevrimiçi deneyin!

Bu soldan sağa çalışıyor.


@AsoneTuhid, herhangi bir şekilde olabilir, örnekleri (x+y)⁄2ve x+2yörnekleri kontrol edin
Rod

Doğru, yanlış
okudum

2

JavaScript (ES6), 58 56 bayt

g=(f,a,r=a[i=0][0],e=a[++i]&&a[i][i])=>e?g(f,a,f(r,e)):r

Soldan sağa katlanır. Düzenleme: Dizi kesinlikle olumlu olduğu gerçeğini kullanarak 2 bayt kaydedildi. Alternatif çözüm, ayrıca 56 bayt:

(f,a,g=r=>(e=a[++i]&&a[i][i])?g(f(r,e)):r)=>g(a[i=0][0])

İhtiyacınız gibi görünmüyor 1/ve çevresindeki bazı şeyler hareket ettirerek başka 2 bayt kaydedebilirsiniz: f=>a=>(h=r=>(e=a[++i]&&a[i][i])?h(f(r,e)):r)(a[i=0][0]). TIO
Shaggy

@Shaggy Ah, kesinlikle olumlu, bunu görmedim.
Neil

Görünüşe göre kara kutu işlevlerinin önceden tanımlanmış bir değişkene atandığını varsayabiliriz, böylece bundan yararlanmak istiyorsanız 2 bayt tasarruf edebilirsiniz.
Shaggy

@Shaggy Aslında f,ilk sürümden 4 bayt (2x ) tasarruf edeceğini düşünüyorum ?
Neil

Haklısın; üzgünüm, tekrar f,arama yaparken saymayı unuttum g.
Shaggy

2

JavaScript, 46 bayt

f=>a=>a.reduce((p,l,i)=>l[i]?f(p[0]|p,l[i]):p)

@Shaggy sayesinde, bitsel kullanın veya bir bayt kaydedin. Bu sihir.


Matrisin sütunlardan daha fazla satır varsa, bu işe yaramaz gibi görünüyor.
Shaggy

@Shaggy çok üzücü, şimdi 47 byte ...
tsh

Evet, ben de orijinal olarak sahip oldum. Çözümümü düzeltmek üzereydim ama beni de yendin :( Sanırım, bit biti VEYA kullanarak bir byte geri alabiliyorsunuz.
Shaggy

@Shaggy çok sihir
tsh

Söylemeyi unuttum: Görünüşe göre, kara kutu işlevlerinin önceden tanımlanmış bir değişkene atandığını varsayabiliriz, böylece bundan yararlanmak istiyorsanız 3 bayt kaydedebilirsiniz.
Shaggy

2

Java 8, 88 81 70 bayt

m->{int r=m[0][0],i=1;try{for(;;)r=f(r,m[i][i++]);}finally{return r;}}

Kıvrımlar [[1,2,3],[4,5,6],[7,8,9]]için f(f(1,5),9).

-7 byte dolaylı olarak @KamilDrakari sayesinde C # cevabında yaptığı gibi bir numara kullanarak : satırları / sütunları temel alan ilmek için maksimum bir sınır yerine, basitçe deneyin ArrayIndexOutOfBoundsException.
Değiştirilmesi -11 bayt catch(Exception e)ile finally.

Çevrimiçi deneyin.

Eski 88 baytlık cevap:

m->{int r=m[0][0],i=1;for(;i<Math.min(m.length,m[0].length);)r=f(r,m[i][i++]);return r;}

Çevrimiçi deneyin.

Açıklama:

m->{                   // Method with integer-matrix parameter and integer return-type
  int r=m[0][0],       //  Start the result at the integer of position 0,0 (0-indexed)
      i=1;             //  Start the index at 1 (0-indexed)
  try{for(;;)          //  Loop indefinitely
    r=f(r,m[i][i++]);} //   Call f with the result + next diagonal cell as arguments
                       //   (and increase `i` by 1 with `i++` afterwards)
  finally{             //  If an ArrayIndexOutOfBoundsException occurred we're done,
   return r;}}         //   in which case we return the result-integer

Kara kutu giriş formatı:

Bu meta cevabına göreint f(int x,int y) izin verilen adlandırılmış bir fonksiyonun olduğunu varsayar. .

TestVarsayılan işlevi f(x,y)ve yukarıdaki lambda'yı içeren soyut bir sınıfım var :

abstract class Test{
  int f(int x,int y){
    return x+y;
  }

  public java.util.function.Function<int[][],Integer>c=
    m->{int r=m[0][0],i=1;for(;i<Math.min(m.length,m[0].length);)r=f(r,m[i][i++]);return r;}
  ;
}

Test durumları için bu fonksiyonun üzerine yazarım f. Örneğin, ilk test durumu şöyle denir:

System.out.println(new Test(){
  @Override
  int f(int x,int y){
    return x*y;
  }
}.c.apply(new int[][]{
  new int[]{1,2,3},
  new int[]{4,5,6},
  new int[]{7,8,9}
}));

2

Ataşesi , 14 bayt

Fold#/Diagonal

Çevrimiçi deneyin! Olarak ayarlayın fve arayın f[function, array].

açıklama

Bu iki işlevden oluşan bir çatal: Foldve /Diagonal. Bu, argümanlar için fve aeşdeğerdir:

Fold[f, (/Diagonal)[f, a]]

/, bir fonksiyona tek taraflı olarak uygulandığında, son argümanına uygulanan bir fonksiyon döndürür. Yani, bu eşdeğerdir:

Fold[f, Diagonal[a]]

Bu, işlevi f, ana köşegenine katlar a.


Okunabilen bir ev
yapımı‽

@ Adám; D evet gerçekten!
Conor O'Brien,

2

AWK , 77 bayt

func z(F,M,r){for(e=1;e<M[1]&&e<M[2];)r=@F(r==""?M[1,1]:r,M[++e,e])
return r}

Çevrimiçi deneyin!

Merak ettim eğer AWKİşlevsel programlama yapabilir . Bence bu önemli.

"Matrix", standart bir ilişkisel dizi olarak tanımlanmıştır, fazladan alanlar M[1]=#rowsve M[2]=#columns. İşlev adı, @F(...)sözdizimi aracılığıyla değerlendirilen bir dize olarak geçirilir . Değerlendirme soldan sağa yapılır. rParametresi varolan üzerine yazılmasını önlemek için bir yer tutucudur rdeğişken ve her çağrı için yeniden başlatmak ihtiyacını önlemek için. AWKBu tür yer tutucuları belirtmek için tipik olarak fazladan boşluk eklenir , ancak bu kod golf, yani her bayt sayılır. :)

TIO linki tüm test durumlarını uygular.


2

05AB1E , 15 10 bayt

Sağdan sola kıvrımlar Kevin Cruijssen
tarafından önerildiği gibi yeni bir yerleşik kullanarak 5 bayt kurtardı

Å\`[.g#I.V

açıklama

Å\Ana köşegeni itmek için yeni bir yerleşik olması dışında eski sürümle aynı şekilde çalışır .

Çevrimiçi deneyin! veya Test Paketi olarak

Eski versiyon

¬g£vyNè}[.g#I.V

Çevrimiçi deneyin! veya Test paketi olarak

açıklama

¬                 # get the head of the input (first row)
 g                # get its length (number of columns)
  £               # take that many rows from input
   v              # for each row_index, row (N,y) do:
    y             # push the row
     Nè           # get the nth element of the row
       }          # end loop
        [.g#      # loop until one value remain on the stack
            I.V   # run the input function

1
¬g£vyNè}[Å\`[şimdi olabilir , 5 bayt kurtarıyor.
Kevin Cruijssen

1

Kabuğu , 7 bayt

Gönderimi düzelttiği için @ Zgarb'a teşekkürler!

Ḟ₁§z!Tŀ

Sola ortak, çevrimiçi deneyin! (sağ ilişkisel sürümü için basitçe yerine göre F)

açıklama

Ne yazık ki, bir matrisin köşegenini elde etmenin kolay bir yolu yoktur, bu nedenle çoğu bayt bunun içindir:

Ḟ₁§z!Tŀ  -- function ₁ is the function and matrix A implicit, example: 
  §      -- fork A
     T   -- | transpose A: [[1,4,7],[2,5,8],[3,6,9]]
      ŀ  -- | enumerate A: [1,2,3]
   z!    -- and zipWith index: [1,5,9]
Ḟ₁       -- right fold function

Huh, köşegenlere karşı yerleşik, ancak köşegenlere
değil‽‽

2
@ Adám, bunun nedeni sonsuz matrislerin antidagonlarını hesaplayabileceğiniz, ancak köşegenleri hesaplayamadığınızdır.
Martin Ender

1

SNOBOL4 (CSNOBOL4) , 86 bayt

T	I =1
	T =M<1,1>
I	I =I + 1
	T =EVAL(F '(T,M<I,I>)')	:S(I)F(RETURN)
	DEFINE('T(M,F)')

Çevrimiçi deneyin!

Alan bir işlevi T(için TRACE) tanımlar.ARRAY ve bir dizeF that's the name of a function. Folds left-to-right.

Dolaylı reference ( $) kullanmak işlevlerle çalışmaz. Yani kullanarakEVAL and passing a string to the name seems to be the only way to get a black-box function in SNOBOL.

Ayrıca, dizileri tanımlamak oldukça acı vericidir; Ancak, geçersiz dizi başvuruları nedenFAILURE , kare olmayan diziler için işe yarar I- her iki boyutta da sınırlar dışındaysa, F(RETURN) forces the function to return.

Düzenle:

Muhtemelen, göre bu meta yazı , bir kara kutu işlevi olduğunu varsayalım Fadı altında tanımlandığı F75 bayt (kaldırılmasının kullanımı bu düşeceği, EVALve ,Fişlev tanımında). Ancak, bu fonksiyonu tercih ediyorum, çünkü bir fonksiyona referans vermek daha yakın.



1

tinylisp, 79 bytes

(load library
(d D(q((M)(i(h M)(c(h(h M))(D(map t(t M))))(
(q((F M)(foldl F(D M

The last line is an unnamed lambda function that takes a function and matrix and returns the matrix trace. The trace is left-associative (i.e. f(f(1,5),9)). Try it online!

Ungolfed

We define a helper function to compute the diagonal; then generalized-trace is merely a small wrapper around the library function foldl.

(load library)

(def diagonal
 (lambda (matrix)
  (if (head matrix)
   (cons
    (head (head matrix))
    (diagonal (map tail (tail matrix))))
   nil)))

(def generalized-trace
 (lambda (func matrix)
  (foldl func (diagonal matrix))))

When computing the diagonal recursively, we check whether (head matrix) is truthy. If the matrix is out of rows, it will be the empty list (nil), and head of nil is nil--falsey. Or, if the matrix is out of columns, its first row (head) will be the empty list (nil)--falsey. Otherwise, there will be a nonempty first row, which is truthy.

So, if the first row doesn't exist or is empty, we return nil. Otherwise, if there is a nonempty first row, we take (head (head matrix))--the first element of the first row--and cons (prepend) it to the result of the recursive call. The argument to the recursive call is (map tail (tail matrix))--that is, take all rows but the first, and take all but the first element of each row.



1

C# (Visual C# Compiler), 72 69 60 bytes

m=>{try{for(int i=1;;m[0][0]=f(m[0][0],m[i][i++]));}catch{}}

Try it online!

try/catch allows the diagonal to be correctly reached by simply going along it and terminating when out of bounds.

3 bytes saved because, as pointed out by Kevin Cruijssen, black-box functions can be assumed to exist under a specific name.

9 bytes saved by returning via modifying an argument.

Thus, the function is called by storing the desired function under the name f, calling trace(matrix), and the result is stored in matrix[0][0].

Alternatively, if you really like verbosity,

C# (Visual C# Compiler), 97 + 13 = 110 78 69 bytes

(int[][]m)=>{try{for(int i=1;;m[0][0]=f(m[0][0],m[i][i++]));}catch{}}

Try it online!

32 bytes saved by using a predefined function, because not taking the function as a parameter allowed removing the System import and the long Func generic type.


Nice trick with the try-catch. I've been able to golf 7 bytes on my Java 8 answer (even though I have to use catch(Exception e) instead of catch. :) EDIT: Oh, been able to replace the catch(Exception e) with finally to save more bytes. Thanks again. +1 from me.
Kevin Cruijssen

@KevinCruijssen you may also be able to benefit from my newest improvement (though I don't remember for sure whether Java is amenable to modifying arguments)
Kamil Drakari

Thanks for letting me know. Although it is possible in Java, it means I'll have to change the finally into catch(Exception e), because I'm not returning inside the finally anymore. So m->{try{for(int i=1;;m[0][0]=f(m[0][0],m[i][i++]));}catch(Exception e){}} (73 bytes) is unfortunately longer for me in comparison to my current answer m->{int r=m[0][0],i=1;try{for(;;)r=f(r,m[i][i++]);}finally{return r;}} (70 bytes) But indeed a nice way to save bytes in your answer! :) Too bad I can only +1 your answer once.
Kevin Cruijssen

1

JavaScript, 61 57 56 52 50 44 42 bytes

Reduces left to right. Assumes the function is assigned to variable f, as per this meta post brought to my attention by Mr. Xcoder & totallyhuman. Can't say as I agree with it as it directly contradicts our existing consensus that we may not assume input is assigned to a pre-defined variable, but I'll take the few bytes saving for now.

a=>a.map((y,z)=>x=(n=y[z])?z?f(x,n):n:x)|x

Test Cases

g=
a=>a.map((y,z)=>x=(n=y[z])?z?f(x,n):n:x)|x
o.innerHTML=[[`f(x,y) = xy`,[[1,2,3],[4,5,6],[7,8,9]],(x,y)=>x*y,45],[`f(x,y) = x<sup>y</sup>`,[[1,2,3],[4,5,6],[7,8,9]],(x,y)=>x**y,1],[`f(x,y) = x-y`,[[4,5,6],[1,2,3]],(x,y)=>x-y,2],[`f(x,y) = <sup>(x+y)</sup>⁄<sub>2</sub>`,[[2,3,4],[5,6,7],[8,9,10]],(x,y)=>(x+y)/2,7],[`f(x,y) = x+2y`,[[1,2,3],[4,5,6],[7,8,9]],(x,y)=>x+2*y,29],[`f(x,y) = max(x,y)`,[[1,2,3],[4,5,6],[7,8,9]],(x,y)=>Math.max(x,y),9],[`f(x,y) = 2x`,[[1,2,3],[4,5,6],[7,8,9]],(x,y)=>2*x,4],[`f(x,y) = lcm(x,y)`,[[2,2,2],[2,2,3],[2,3,3],[4,4,4]],(x,y)=>-~[...Array(x*y).keys()].find(z=>!(++z%x|z%y)),6]].map(([a,b,c,d],e)=>`Test #${++e}:  ${a}\nMatrix:   ${JSON.stringify(b)}\nFunction: ${f=c}\nResult:   ${g(b)}\nExpected: ${d}`).join`\n\n`
<pre id=o></pre>


1

APL NARS, 20 bytes, 10 chars

{⍺⍺/1 1⍉⍵}

test:

  f←{⍺⍺/1 1⍉⍵}
  ⎕←q←3 3⍴⍳10    
1 2 3
4 5 6
7 8 9
  ×f q
45
  *f q
1
  {⍺+2×⍵}f q
47
  ⌈f q
9
  {2×⍺+0×⍵}f q
2
  -f ⊃(4 5 6)(1 2 3)
2
  {(⍺+⍵)÷2}f ⊃(2 3 4)(5 6 7)(8 9 10)
5
  ∧f ⊃(2 2 2)(2 2 3)(2 3 3)(4 4 4)
6

Good job. While I think you arrive to this on you own, it happens to be identical to Erik the Outgolfer's original solution.
Adám

0

Jelly, 5 bytes

Left-to-right.

ŒDḢç/

Try it online!

Disclaimer: I do not know if this an acceptable input method for black-box functions. This assumes that the function is implemented in the link above, and is thus "named" (that is, it's callable with) ç, but otherwise I have no way to assign it to ç. If anyone has more experience with Jelly + black box functions, I would appreciate thoughts. After spending some time in chat, we figured that using ç might indeed be valid.


0

Clojure, 30 bytes

#(reduce %2(map nth %(range)))

Reduces "from the left".


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.