Sembolik matris çarpımı


26

Matris çarpımını açıklamanın birçok farklı yolu vardır. Buradaki çoğu insanın buna aşina olduğuna inandığım için tek bir figüre bağlı kalacağım (ve bu rakam çok açıklayıcı). Daha ayrıntılı bilgi edinmek için Wikipedia makalesini veya WolframMathWorld hakkındaki açıklamayı ziyaret etmenizi öneririm .

Basit açıklama:

Diyelim ki iki matrisiniz var, A ve B , A 3'e 2 ve B 2'ye 3. Bunlara matris çarpımı yaparsanız, AB veya BA matrislere atarsanız aşağıdaki sonuçları alırsınız:

görüntü tanımını buraya girin

Meydan okuma:

Uygulamak sembolik size dilinde matris çarpımı. Matrislerdeki her elemanın boşluksuz bir ASCII karakteri ile temsil edildiği girdi olarak iki matris alacaksınız (kod noktaları 33-126). Bu matrislerin ürününü çıkarmalısınız.

Çıktı ile ilgili kurallar:

İki girişli bir ürün arasında hiçbir sembol bulunmamalıdır. O var abdeğil, a*b, a·b, times(a,b)benzer ya da bir şey. Bu aadeğil a^2.

Terimlerin toplamı arasında bir boşluk (ASCII kod noktası 32) bulunmalıdır. O var a bdeğil, a+b, plus(a,b)benzer ya da bir şey.

Bu iki kuralın gerekçesi şudur: Beyaz boşluk olmayan tüm karakterlerin matrislerde semboller olarak kullanılmasına izin verilir, böylece onları matematiksel semboller olarak kullanmak dağınık olur. Normalde olduğu gibi yazabildiğiniz a*b+c*dşey ab cd.

Terimlerin sırasını seçebilirsiniz. ab cd, dc abve cd bamatematiksel olarak da aynı şekilde konuşuyorsunuz, bu yüzden burada emri de seçebilirsiniz. Siparişin matematiksel olarak doğru olduğu sürece tutarlı olması gerekmez.

Matris biçimlendirme ile ilgili kurallar:

Satırlar arasında sınırlayıcı olmayan tek bir dize dışında, istediğiniz formatta bir matris girilebilir (bunun nedeni çıktının tamamen karışmasıdır). Her iki matris de aynı formatta girilmelidir. Aşağıdaki tüm örnekler, bir matrise girmenin ve çıktının geçerli yollarıdır.

"ab;cd"     <- This will look awful, but it's still accepted.

"a,b\nc,d"

[[a,b],[c,d]] 

[a, b]
[c, d]

Bunun karmaşık görünecek bir çok formata izin verdiğinin farkındayım, ancak zorluk, matrislerin çarpımıyla değil, çıktıyı biçimlendirmeyle ilgili.

Genel kurallar:

  • Geçerli bir girdi kabul edebilirsiniz. Matris çarpımı, verilen boyutlarla her zaman mümkün olacaktır.
  • Sadece iki matris olacak.
  • Matrislerin boş olmadığını kabul edebilirsiniz.
  • Yerleşik işlevler kabul edilir (ancak biçimlendirme gereksinimlerinden dolayı muhtemelen biraz hantal).
  • Elbette eğer gerekliyse girişte kaçış karakterlerini kullanabilirsiniz ( \'yerine ').
  • Herhangi bir standart giriş ve çıkış yöntemi tamamdır .

Test durumları:

İki giriş matrisi, aralarında boş bir satırla gösterilir. Çıkış sonra gösterilir Output:. İki çıktı matrisi olduğunda, sadece kabul edilecek diğer çıktıları göstermek mümkündür.

Test durumu # 1

Inputs:
[a]

[b]

Output:
[ab]
[ba]      <- Also OK

Sınama durumu # 2

Inputs:
[a, b]
[1, 4] 
[y, {]

[%, 4, 1] 
[a, b, c]

Output:    
[a% ba, a4 bb, a1 bc] 
[1% 4a, 14 4b, 11 4c] 
[y% {a, y4 {b, y1 {c]

Test durumu # 3:

Inputs:
[1, 2, 3, 4]
[5, 6, 7, 8]
[9, 1, 2, 3]
[4, 5, 6, 7]

[a]
[b]
[c]
[d]

Output:
[1a 2b 3c 4d]
[5a 6b 7c 8d]
[9a 1b 2c 3d]
[4a 5b 6c 7d]

[d4 c3 b2 a1]      <-- Also OK
[d8 c7 b6 a5]
[1b 9a c2 3d]
[a4 b5 d7 6c]

Yerine koymak ab cdyerine kurallara cevabınız a*b+c*d: eğer hantal giriş / çıkış biçimlerinden kaçınmalısınız , o zaman giriş ve çıkış biçimlerinin çok esnek olduğunu unutmayın. Gerçek şu ki kullanamazsınız *ve +ürün ve toplamlar için zor yerleşik bir basit kullanmayı hale getirebileceğini, ancak bunun olumsuz bir şey düşünmüyoruz.


Bir işlev için, iki 2B dizge dizisi alıyor ve bir 2B dizge dizisi döndürüyor kabul edilebilir mi?
Dennis

Evet, sorun yok. Ancak boyutlar eşleşmelidir, ikinci girişin çevrilmesi mümkün olamaz. Bu mantıklı mıydı?
Stewie Griffin

Anlattığın için teşekkürler. Son bir soru: Bir 2D karakter dizisini girdi olarak alabilir ve 2D dizgiyi döndürebilir miyim?
Dennis

@Dennis, şunu yazdım: "Her iki matris de aynı biçimde girilmelidir." Orada çıktı matrisini söylemeyi unuttum, bu yüzden böyle tutacağım. Girişler aynı formatta olmalıdır, ancak farklı bir çıkış formatına sahip olabilirsiniz. (Bu çözümü gerçekten sevmiyorum, ama şu an bir şeyleri değiştirmek istemiyorum, sanırım zaten farklı girdi ve çıktı biçimlerine sahip bir cevap var)
Stewie Griffin

Ruby'nin cevabını kastediyorsanız, işaretledim ve bu karakter yerine karakter dizeleriyle çalıştığını söyledi.
Dennis

Yanıtlar:


9

Haskell , 62 61 bayt

e=[]:e
a!b=[unwords.zipWith(++)r<$>foldr(zipWith(:))e b|r<-a]

Çevrimiçi deneyin! Örnek kullanım:

Prelude> [["a","b"],["c","e"]] ! [["f","g"],["h","i"]]
[["af bh","ag bi"],["cf eh","cg ei"]]

Bir transposeişlevi bir baytta almak için içe aktarmayı kullanmaktan daha kısa bir yol buldum :

import Data.List;transpose
e=[]:e;foldr(zipWith(:))e

İçe aktarmalı eski sürüm: (62 bayt)

import Data.List
a!b=[unwords.zipWith(++)r<$>transpose b|r<-a]

Çevrimiçi deneyin!

Bu, sembolik olmayan matris çarpımına verdiğim cevaba oldukça benziyor : a!b=[sum.zipWith(*)r<$>transpose b|r<-a]çarpımı (*)dize bitiştirme yerine koyma (++)ve sumaralarında unwordsboşluk bulunan bir dize listesi bitiştirme. İçe aktarma transposeişlevi için gereklidir , bu yüzden ikinci matrisin tümünün aktarımında tüm baytların yarısını kullanır ...


İçe aktarma olmadan eski sürüm: (64 bayt)

a![]=[];a!b=(unwords.zipWith(++)[h|h:_<-b]<$>a):a![s:t|_:s:t<-b]

Çevrimiçi deneyin!

İçe aktarma ve transposeişlev çok fazla bayt alarak , işlemi içe aktarma olmadan çözmeyi denedim. Şimdiye kadar bu yaklaşımın iki bayt daha uzun olduğu ortaya çıktı, ancak daha fazla golf oynayabilir. Düzenleme: En üstteki diğer yaklaşım şimdi ithalat yener!

Liste kavraması [s:t|_:s:t<-b], listelerin boş olmayan kuyruklarını alır, byalnızca [t|_:t<-b]kuyrukları kullanmak için 4 bayt daha kısa olur (içe aktarma sürümünü bile döker), ancak ["","",""]izin verilmeyen matris gibi boş bir satır ekler .


6

Mathematica, 36 bayt

Inner[#<>#2&,##,StringRiffle@*List]&

InnerMathematica'nın genelleştirilmesidir Dot(yani olağan matris / vektör ürünü). Bu iki işlevi sağlamak sağlayarak nokta ürününü genelleştirir fve gsırasıyla her zamanki çarpma ve ek, yerine kullanılacaktır. Çarpımı, #<>#2&(iki karakteri tek bir dizgeye birleştiren) ve StringRiffle@*Listönce tüm summanları bir listeye sarar ve sonra StringRiffleboşluklarla birleştiren ekini değiştiriyoruz .

Bir kişi potansiyel olarak Dotoperatörü kullanabilir .ve daha sonra sonucu dönüştürebilir, ancak sorun şu ki gibi şeyler "a"*"a"derhal bir araya gelip "a"^2(toplamlar için aynı), bu da tekrar ayrılmaya can sıkıcı olacaktı.


6

Ruby, 61 bayt

->a,b{a.map{|x|b.transpose.map{|y|x.zip(y).map(&:join)*' '}}}

Örnek çalışma:

main(0):007> ->a,b{a.map{|x|b.transpose.map{|y|x.zip(y).map(&:join)*' '}}}[[[?a, ?b], [?1, ?4], [?y, ?{]], [[?%, ?4, ?1], [?a, ?b, ?c]]]
=> [["a% ba", "a4 bb", "a1 bc"], ["1% 4a", "14 4b", "11 4c"], ["y% {a", "y4 {b", "y1 {c"]]
->a,b{
a.map{|x|            # for each row of a
b.transpose.map{|y|  # and for each column of b
x.zip(y)             # match up corresponding elements
.map(&:join)         # join each pair together
*' '                 # join the entire thing on space
}}}

4

Clojure, 53 bayt

#(for[a %](for[b(apply map vector %2)](map str a b)))

Argümanlar [["a" "b"]["c" "e"]]ve [["f" "g"]["h" "i"]]döndürmeler ile çalışıyor ((("af" "bh") ("ag" "bi")) (("cf" "eh") ("cg" "ei"))). Bu aslında sayısal versiyondan daha kısa .


3

Dyalog APL , 10 bayt

Karakter matrislerini sol ve sağ argümanlar olarak alır. Karakter listelerinin matrisini döndürür. (APL, dizeleri karakter listeleri olarak gösterir.)

{∊⍺' '⍵}.,

TryAPL çevrimiçi!

Normal iç ürün APL'dedir +.×, fakat toplama ve çarpma, özellikle de herhangi bir fonksiyon olabilir:

Ek,
{ adsız bir işlevle değiştirildi :  sol argüman, boşluk ve sağ argümandan oluşan
 düzleştirilmiş
⍺ ' ' ⍵liste
}

Çarpma, birleştirme ile değiştirildi, ,


2

Jöle , 7 bayt

Z;"þK€€

Bu, B ve A'yı argüman olarak alan (sırayla) ve AB'yi döndüren ikili bir bağlantıdır . Giriş ve çıkış, gerçekte karakterlerin 3B dizileri olan 2B dizgileri şeklindedir. Giriş olarak 2B karakter dizileri alınarak başka bir bayt kaydedilebilir . Buna izin verilip verilmediğinden emin değilim.

Çevrimiçi deneyin!

İplikler söz konusu olduğunda Jelly'in kaputun altında ne yapacağını belirlemek biraz zor, çünkü baskıdan önce çok fazla sıçrama yapıyor. Jelly, dahili olarak girişi ve çıkışı temsil eder.

Nasıl çalışır

Z;"þK€€  Dyadic link. Left argument: B. Right argument: A

Z        Zip/transpose B.
 ;"þ     Table vectorized concatenation; for each row in B' and each row in A,
         concatenate the corresponding strings.
    K€€  Join the arrays that correspond to the rows of A by spaces.

2

Prolog,> 256 Bayt

{_ | Kullanıyorum bir findall / 3 olan _}, bazı arg / 3 olan _ [_, _] ve bazı toplam olan toplam (_). Hepsi içinde kullanılabilir / 2:

*(X, Y, Z) :- functor(Y, matrice, _), L is len(X[1]), L =:= len(Y), !,
   M is len(X), N is len(Y[1]),
   Z is { { sum({ X[J,K] * Y[K,I] | between(1,L,K) })
                                  | between(1,N,I) }
                                  | between(1,M,J) }.

Birlikte ile ekstra tanımlamalar yukarıda belirtilen önermeler ve non-standart için 2 numaraları, onun emin> 256 bayt daha dönebilmek / olduğunu.


1

JavaScript (ES6), 65 bayt

(a,b)=>a.map(c=>b[0].map((_,j)=>c.map((e,i)=>e+b[i][j]).join` `))

Girdiyi 2B karakter dizisi olarak alır ve 2B dizge dizisi döndürür. İki 1D dizge dizisi olarak girişi desteklemek için 10 bayt ekleyin.


1

Pyth, 14 bayt

clQmj;sMCd*QCE

İki yeni satırla ayrılmış iki boyutlu karakter listesinin girişini alan ve iki boyutlu bir dize listesi basan bir program.

Test odası

Nasıl çalışır

[Açıklama daha sonra gelecek]


1

Pip , 17 bayt

{Y Zb{a._JsMy}Ma}

Bu, iç içe geçmiş (tek karakterli) dizelerin listesini alan ve iç içe geçmiş bir dizeler listesi döndüren bir işlevdir. Çevrimiçi deneyin! (iki test durumuyla).

açıklama

Bir üzere Argümanlar {}-delimited işlevi yerel değişkenlere atanır aiçin e. Bir lambda işlevinin ilk argümanı ile temsil edilir _.

{               }  Define a function:
   Zb              Zip rows of b, transposing it
 Y                 Yank into global variable y for access in nested function
     {       }Ma   To the rows of a, map this function:
           My       To the rows of y (i.e. columns of b), map this function:
      a._           Concatenate, itemwise, the current row of a and row of y
         Js         Join the resulting list on space
                   The result of the outer map operation is returned
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.